diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/AlibabaCloudCmsExternAlert.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/AlibabaCloudCmsExternAlert.java
new file mode 100644
index 00000000000..2970dcd63a0
--- /dev/null
+++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/AlibabaCloudCmsExternAlert.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hertzbeat.alert.dto;
+
+import com.fasterxml.jackson.annotation.JsonAlias;
+import java.util.Map;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * Alibaba Cloud Monitor 2.0 webhook alert entity.
+ *
+ * @see
+ * Alibaba Cloud Monitor webhook payload fields
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class AlibabaCloudCmsExternAlert {
+
+ private String specversion;
+
+ private String id;
+
+ private String type;
+
+ private String subtype;
+
+ private String source;
+
+ private String sourcetype;
+
+ private String time;
+
+ private Long timestamp;
+
+ private String subject;
+
+ private String datacontenttype;
+
+ private String severity;
+
+ private String status;
+
+ private String userId;
+
+ private String ruleId;
+
+ private String workspace;
+
+ private String traceId;
+
+ private String alertMessage;
+
+ private String alertEntityId;
+
+ private Resource resource;
+
+ private Map labels;
+
+ private Map annotations;
+
+ private AlertData data;
+
+ private Map alertEntityFields;
+
+ private String ruleUrl;
+
+ private String entityUrl;
+
+ private String alertRuleUrl;
+
+ private String alertHistoryUrl;
+
+ /**
+ * Alert resource.
+ */
+ @Data
+ @Builder
+ @AllArgsConstructor
+ @NoArgsConstructor
+ public static class Resource {
+
+ private Entity entity;
+
+ private Map tags;
+ }
+
+ /**
+ * Alert resource entity.
+ */
+ @Data
+ @Builder
+ @AllArgsConstructor
+ @NoArgsConstructor
+ public static class Entity {
+
+ private String domain;
+
+ @JsonAlias("entity_type")
+ private String entityType;
+
+ @JsonAlias("entity_id")
+ private String entityId;
+
+ private Map prop;
+ }
+
+ /**
+ * Threshold alert data.
+ */
+ @Data
+ @Builder
+ @AllArgsConstructor
+ @NoArgsConstructor
+ public static class AlertData {
+
+ private Object value;
+
+ private Object threshold;
+
+ private String comparisonOperator;
+ }
+}
diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlibabaCloudCmsExternAlertService.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlibabaCloudCmsExternAlertService.java
new file mode 100644
index 00000000000..3b032e9fa0c
--- /dev/null
+++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlibabaCloudCmsExternAlertService.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hertzbeat.alert.service.impl;
+
+import java.time.Instant;
+import java.time.format.DateTimeParseException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hertzbeat.alert.dto.AlibabaCloudCmsExternAlert;
+import org.apache.hertzbeat.alert.reduce.AlarmCommonReduce;
+import org.apache.hertzbeat.alert.service.ExternAlertService;
+import org.apache.hertzbeat.common.constants.CommonConstants;
+import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
+import org.apache.hertzbeat.common.util.JsonUtil;
+import org.springframework.stereotype.Service;
+
+/**
+ * Alibaba Cloud Monitor 2.0 external alert service.
+ */
+@Slf4j
+@Service
+public class AlibabaCloudCmsExternAlertService implements ExternAlertService {
+
+ private static final String SOURCE = "alibabacloud-cms";
+
+ private final AlarmCommonReduce alarmCommonReduce;
+
+ public AlibabaCloudCmsExternAlertService(AlarmCommonReduce alarmCommonReduce) {
+ this.alarmCommonReduce = alarmCommonReduce;
+ }
+
+ @Override
+ public void addExternAlert(String content) {
+ AlibabaCloudCmsExternAlert externAlert = JsonUtil.fromJson(content, AlibabaCloudCmsExternAlert.class);
+ if (externAlert == null || StringUtils.isBlank(externAlert.getStatus())) {
+ log.warn("Failed to parse Alibaba Cloud Monitor external alert content: {}", content);
+ return;
+ }
+ alarmCommonReduce.reduceAndSendAlarm(convert(externAlert));
+ }
+
+ @Override
+ public String supportSource() {
+ return SOURCE;
+ }
+
+ private SingleAlert convert(AlibabaCloudCmsExternAlert externAlert) {
+ boolean resolved = isResolved(externAlert);
+ long eventTime = getEventTime(externAlert);
+ return SingleAlert.builder()
+ .content(getAlertContent(externAlert))
+ .status(resolved ? CommonConstants.ALERT_STATUS_RESOLVED : CommonConstants.ALERT_STATUS_FIRING)
+ .startAt(eventTime)
+ .activeAt(resolved ? null : eventTime)
+ .endAt(resolved ? eventTime : null)
+ .labels(buildLabels(externAlert))
+ .annotations(buildAnnotations(externAlert))
+ .triggerTimes(1)
+ .build();
+ }
+
+ private boolean isResolved(AlibabaCloudCmsExternAlert externAlert) {
+ return "RESOLVED".equalsIgnoreCase(externAlert.getStatus())
+ || "RECOVERED".equalsIgnoreCase(externAlert.getStatus())
+ || "NORMAL_RESOLVE".equalsIgnoreCase(externAlert.getSubtype());
+ }
+
+ private long getEventTime(AlibabaCloudCmsExternAlert externAlert) {
+ if (externAlert.getTimestamp() != null && externAlert.getTimestamp() > 0) {
+ return externAlert.getTimestamp();
+ }
+ if (StringUtils.isNotBlank(externAlert.getTime())) {
+ try {
+ return Instant.parse(externAlert.getTime()).toEpochMilli();
+ } catch (DateTimeParseException e) {
+ log.warn("Failed to parse Alibaba Cloud Monitor event time: {}", externAlert.getTime());
+ }
+ }
+ return Instant.now().toEpochMilli();
+ }
+
+ private Map buildLabels(AlibabaCloudCmsExternAlert externAlert) {
+ Map labels = new HashMap<>(16);
+ putValues(labels, externAlert.getLabels());
+ AlibabaCloudCmsExternAlert.Resource resource = externAlert.getResource();
+ if (resource != null) {
+ putValues(labels, resource.getTags());
+ AlibabaCloudCmsExternAlert.Entity entity = resource.getEntity();
+ if (entity != null) {
+ putIfNotBlank(labels, "resourceDomain", entity.getDomain());
+ putIfNotBlank(labels, "resourceType", entity.getEntityType());
+ putIfNotBlank(labels, "resourceId", entity.getEntityId());
+ }
+ }
+ labels.put("__source__", SOURCE);
+ putIfNotBlank(labels, CommonConstants.LABEL_ALERT_NAME, externAlert.getSubject());
+ putIfNotBlank(labels, CommonConstants.LABEL_ALERT_SEVERITY, convertSeverity(externAlert.getSeverity()));
+ putIfNotBlank(labels, "ruleId", externAlert.getRuleId());
+ putIfNotBlank(labels, "workspace", externAlert.getWorkspace());
+ putIfNotBlank(labels, "alertEntityId", externAlert.getAlertEntityId());
+ putIfNotBlank(labels, "userId", externAlert.getUserId());
+ return labels;
+ }
+
+ private Map buildAnnotations(AlibabaCloudCmsExternAlert externAlert) {
+ Map annotations = new HashMap<>(16);
+ putValues(annotations, externAlert.getAnnotations());
+ AlibabaCloudCmsExternAlert.Resource resource = externAlert.getResource();
+ if (resource != null && resource.getEntity() != null) {
+ putValues(annotations, resource.getEntity().getProp());
+ }
+ putValues(annotations, externAlert.getAlertEntityFields());
+ AlibabaCloudCmsExternAlert.AlertData data = externAlert.getData();
+ if (data != null) {
+ putValue(annotations, "value", data.getValue());
+ putValue(annotations, "threshold", data.getThreshold());
+ putIfNotBlank(annotations, "comparisonOperator", data.getComparisonOperator());
+ }
+ putIfNotBlank(annotations, "alertMessage", externAlert.getAlertMessage());
+ putIfNotBlank(annotations, "traceId", externAlert.getTraceId());
+ putIfNotBlank(annotations, "ruleUrl", externAlert.getRuleUrl());
+ putIfNotBlank(annotations, "entityUrl", externAlert.getEntityUrl());
+ putIfNotBlank(annotations, "alertRuleUrl", externAlert.getAlertRuleUrl());
+ putIfNotBlank(annotations, "alertHistoryUrl", externAlert.getAlertHistoryUrl());
+ return annotations;
+ }
+
+ private String getAlertContent(AlibabaCloudCmsExternAlert externAlert) {
+ if (StringUtils.isNotBlank(externAlert.getAlertMessage())) {
+ return externAlert.getAlertMessage();
+ }
+ if (StringUtils.isNotBlank(externAlert.getSubject())) {
+ return externAlert.getSubject();
+ }
+ return "Alibaba Cloud Monitor alert";
+ }
+
+ private String convertSeverity(String severity) {
+ if (StringUtils.isBlank(severity)) {
+ return null;
+ }
+ return switch (severity.toUpperCase(Locale.ROOT)) {
+ case "EMERGENCY" -> CommonConstants.ALERT_SEVERITY_EMERGENCY;
+ case "CRITICAL" -> CommonConstants.ALERT_SEVERITY_CRITICAL;
+ case "WARN", "WARNING" -> CommonConstants.ALERT_SEVERITY_WARNING;
+ case "INFO", "INFORMATIONAL" -> CommonConstants.ALERT_SEVERITY_INFO;
+ default -> severity.toLowerCase(Locale.ROOT);
+ };
+ }
+
+ private void putValues(Map target, Map values) {
+ if (values == null || values.isEmpty()) {
+ return;
+ }
+ values.forEach((key, value) -> putValue(target, key, value));
+ }
+
+ private void putValue(Map target, String key, Object value) {
+ if (StringUtils.isBlank(key) || value == null) {
+ return;
+ }
+ String stringValue;
+ if (value instanceof Map, ?> || value instanceof Collection>) {
+ stringValue = JsonUtil.toJson(value);
+ } else {
+ stringValue = String.valueOf(value);
+ }
+ putIfNotBlank(target, key, stringValue);
+ }
+
+ private void putIfNotBlank(Map target, String key, String value) {
+ if (StringUtils.isNotBlank(value)) {
+ target.put(key, value);
+ }
+ }
+}
diff --git a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AlibabaCloudCmsExternAlertServiceTest.java b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AlibabaCloudCmsExternAlertServiceTest.java
new file mode 100644
index 00000000000..53c89d113db
--- /dev/null
+++ b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AlibabaCloudCmsExternAlertServiceTest.java
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hertzbeat.alert.service;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import java.time.Instant;
+import org.apache.hertzbeat.alert.reduce.AlarmCommonReduce;
+import org.apache.hertzbeat.alert.service.impl.AlibabaCloudCmsExternAlertService;
+import org.apache.hertzbeat.common.constants.CommonConstants;
+import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+/**
+ * Unit test for {@link AlibabaCloudCmsExternAlertService}.
+ */
+@ExtendWith(MockitoExtension.class)
+class AlibabaCloudCmsExternAlertServiceTest {
+
+ private static final long EVENT_TIME = 1785300000123L;
+
+ @Mock
+ private AlarmCommonReduce alarmCommonReduce;
+
+ private AlibabaCloudCmsExternAlertService externAlertService;
+
+ @BeforeEach
+ void setUp() {
+ externAlertService = new AlibabaCloudCmsExternAlertService(alarmCommonReduce);
+ }
+
+ @Test
+ void shouldConvertTriggeredAlert() {
+ externAlertService.addExternAlert("""
+ {
+ "specversion": "1.0",
+ "id": "alert-event-1",
+ "type": "ALERT",
+ "subtype": "NORMAL_TRIGGER",
+ "time": "2026-07-29T06:00:00Z",
+ "timestamp": 1785300000123,
+ "subject": "ECS CPU usage is high",
+ "severity": "WARNING",
+ "status": "OCCURRED",
+ "userId": "123456",
+ "ruleId": "rule-1",
+ "workspace": "default-cms-123456-cn-hangzhou",
+ "traceId": "trace-1",
+ "alertMessage": "CPU usage exceeded 80%",
+ "alertEntityId": "ecs:i-123",
+ "resource": {
+ "entity": {
+ "domain": "ecs",
+ "entity_type": "instance",
+ "entity_id": "i-123",
+ "prop": {
+ "instanceName": "api-server"
+ }
+ },
+ "tags": {
+ "regionId": "cn-hangzhou",
+ "environment": "production"
+ }
+ },
+ "labels": {
+ "_cms_region": "cn-hangzhou",
+ "customNumber": 7
+ },
+ "annotations": {
+ "current_value": "92.5"
+ },
+ "data": {
+ "value": 92.5,
+ "threshold": 80,
+ "comparisonOperator": ">"
+ },
+ "alertEntityFields": {
+ "privateIp": "10.0.0.1"
+ },
+ "alertHistoryUrl": "https://cmsnext.console.aliyun.com/history",
+ "futureField": "ignored"
+ }
+ """);
+
+ SingleAlert alert = captureAlert();
+ assertEquals(CommonConstants.ALERT_STATUS_FIRING, alert.getStatus());
+ assertEquals(EVENT_TIME, alert.getStartAt());
+ assertEquals(EVENT_TIME, alert.getActiveAt());
+ assertNull(alert.getEndAt());
+ assertEquals("CPU usage exceeded 80%", alert.getContent());
+ assertEquals("alibabacloud-cms", alert.getLabels().get("__source__"));
+ assertEquals("ECS CPU usage is high", alert.getLabels().get("alertname"));
+ assertEquals(CommonConstants.ALERT_SEVERITY_WARNING, alert.getLabels().get("severity"));
+ assertEquals("instance", alert.getLabels().get("resourceType"));
+ assertEquals("i-123", alert.getLabels().get("resourceId"));
+ assertEquals("7", alert.getLabels().get("customNumber"));
+ assertEquals("api-server", alert.getAnnotations().get("instanceName"));
+ assertEquals("92.5", alert.getAnnotations().get("value"));
+ assertEquals("80", alert.getAnnotations().get("threshold"));
+ assertEquals("10.0.0.1", alert.getAnnotations().get("privateIp"));
+ }
+
+ @Test
+ void shouldConvertResolvedAlertAndIsoTime() {
+ externAlertService.addExternAlert("""
+ {
+ "subtype": "NORMAL_RESOLVE",
+ "time": "2026-07-29T06:00:00Z",
+ "subject": "ECS CPU usage is high",
+ "severity": "CRITICAL",
+ "status": "RESOLVED",
+ "labels": {
+ "instanceId": "i-123"
+ }
+ }
+ """);
+
+ SingleAlert alert = captureAlert();
+ long expectedTime = Instant.parse("2026-07-29T06:00:00Z").toEpochMilli();
+ assertEquals(CommonConstants.ALERT_STATUS_RESOLVED, alert.getStatus());
+ assertEquals(expectedTime, alert.getStartAt());
+ assertNull(alert.getActiveAt());
+ assertEquals(expectedTime, alert.getEndAt());
+ assertEquals("ECS CPU usage is high", alert.getContent());
+ assertEquals(CommonConstants.ALERT_SEVERITY_CRITICAL, alert.getLabels().get("severity"));
+ }
+
+ @Test
+ void shouldTreatRecoveredStatusAsResolved() {
+ externAlertService.addExternAlert("""
+ {
+ "timestamp": 1785300000123,
+ "subject": "Recovered alert",
+ "status": "RECOVERED"
+ }
+ """);
+
+ SingleAlert alert = captureAlert();
+ assertEquals(CommonConstants.ALERT_STATUS_RESOLVED, alert.getStatus());
+ assertEquals(EVENT_TIME, alert.getEndAt());
+ }
+
+ @Test
+ void shouldIgnoreInvalidPayload() {
+ externAlertService.addExternAlert("invalid json");
+ externAlertService.addExternAlert("{\"subject\":\"missing status\"}");
+
+ verify(alarmCommonReduce, never()).reduceAndSendAlarm(any(SingleAlert.class));
+ assertEquals("alibabacloud-cms", externAlertService.supportSource());
+ }
+
+ private SingleAlert captureAlert() {
+ ArgumentCaptor captor = ArgumentCaptor.forClass(SingleAlert.class);
+ verify(alarmCommonReduce).reduceAndSendAlarm(captor.capture());
+ return captor.getValue();
+ }
+}
diff --git a/web-app/src/app/routes/alert/alert-integration/alert-integration.component.ts b/web-app/src/app/routes/alert/alert-integration/alert-integration.component.ts
index 57eab71d8f6..f4e539821d4 100644
--- a/web-app/src/app/routes/alert/alert-integration/alert-integration.component.ts
+++ b/web-app/src/app/routes/alert/alert-integration/alert-integration.component.ts
@@ -80,6 +80,11 @@ export class AlertIntegrationComponent implements OnInit {
name: this.i18nSvc.fanyi('alert.integration.source.tencent'),
icon: 'assets/img/integration/tencent.svg'
},
+ {
+ id: 'alibabacloud-cms',
+ name: this.i18nSvc.fanyi('alert.integration.source.alibabacloud-cms'),
+ icon: 'assets/img/integration/alibabacloud.svg'
+ },
{
id: 'alibabacloud-sls',
name: this.i18nSvc.fanyi('alert.integration.source.alibabacloud-sls'),
diff --git a/web-app/src/assets/doc/alert-integration/alibabacloud-cms.en-US.md b/web-app/src/assets/doc/alert-integration/alibabacloud-cms.en-US.md
new file mode 100644
index 00000000000..e36af233f7b
--- /dev/null
+++ b/web-app/src/assets/doc/alert-integration/alibabacloud-cms.en-US.md
@@ -0,0 +1,75 @@
+> Send Alibaba Cloud Monitor 2.0 alerts to the HertzBeat alert platform through a webhook.
+
+### Prepare a HertzBeat API token
+
+1. Click **Manage API Tokens** in the upper-right corner of this page.
+2. Create a token and save it securely. The complete token is displayed only once.
+
+### Create an Alibaba Cloud Monitor webhook
+
+1. Log on to the [Alibaba Cloud Monitor 2.0 console](https://cmsnext.console.aliyun.com/).
+2. Select or create the target workspace, then go to **Alert Center** > **Notification Management** > **Notification Objects**.
+3. Open the **Custom Webhook** tab and click **Create Webhook**.
+4. Configure the webhook:
+ - Name: `HertzBeat`
+ - Identifier: for example, `hertzbeat`
+ - URL:
+
+ ```text
+ http://{hertzbeat_host}:1157/api/alerts/report/alibabacloud-cms
+ ```
+
+ - Headers: add `Authorization` with the value `Bearer {token}`
+ - Method: `POST`
+ - Data format: `JSON`
+ - Language: select as needed
+5. Save the webhook.
+
+> Use the notification objects in an Alibaba Cloud Monitor 2.0 workspace. Notification objects in Prometheus Monitoring or ARMS Alert Management use a different webhook format and are not supported by this integration.
+
+> `{hertzbeat_host}` must be publicly reachable from Alibaba Cloud Monitor. Expose this endpoint through an HTTPS reverse proxy in production.
+
+### Bind an alert rule
+
+1. Go to **Alert Center** > **Alert Management** > **Alert Rules**.
+2. Create or edit an alert rule.
+3. Select the HertzBeat custom webhook in the alert notification settings.
+4. Enable recovery notifications if alerts should be resolved automatically in HertzBeat.
+5. Save and enable the alert rule.
+
+### Field mapping
+
+| Alibaba Cloud Monitor field | HertzBeat field |
+| --- | --- |
+| `status: OCCURRED/PERSISTENT` | `status: firing` |
+| `status: RESOLVED/RECOVERED` | `status: resolved` |
+| `subject` | `labels.alertname` |
+| `severity` | `labels.severity` |
+| `alertMessage` | Alert content |
+| `labels`, `resource.tags` | Alert labels |
+| `annotations`, threshold, and resource properties | Alert annotations |
+| `timestamp` or `time` | Alert time |
+
+### Troubleshooting
+
+#### The webhook returns 401 or 403
+
+- Make sure the HertzBeat API token is active.
+- Make sure the header is named `Authorization` and its value starts with `Bearer `.
+
+#### HertzBeat does not receive an alert
+
+- Make sure the webhook URL and port are publicly reachable.
+- Make sure the data format is `JSON` and the request method is `POST`.
+- Check Alibaba Cloud Monitor alert history and the HertzBeat service logs.
+- If source IP allowlisting is enabled, use the latest CIDR list in the Alibaba Cloud documentation.
+
+#### An alert is not resolved automatically
+
+- Make sure recovery notifications are enabled in the alert rule or notification policy.
+- Make sure the recovery webhook contains a `status` of `RESOLVED` or `RECOVERED`.
+
+For more information:
+
+- [Alibaba Cloud Monitor notification objects and webhook fields](https://help.aliyun.com/en/cms/cloudmonitor-2-0/notification-object)
+- [Alibaba Cloud Monitor alert rules](https://help.aliyun.com/en/cms/cloudmonitor-2-0/alert-rules-cms-2-0)
diff --git a/web-app/src/assets/doc/alert-integration/alibabacloud-cms.zh-CN.md b/web-app/src/assets/doc/alert-integration/alibabacloud-cms.zh-CN.md
new file mode 100644
index 00000000000..72ba07b4e3d
--- /dev/null
+++ b/web-app/src/assets/doc/alert-integration/alibabacloud-cms.zh-CN.md
@@ -0,0 +1,75 @@
+> 将阿里云云监控 2.0 的告警通过 Webhook 发送到 HertzBeat 告警平台。
+
+### 准备 HertzBeat API Token
+
+1. 单击页面右上角的 **管理 API Token**。
+2. 创建一个 Token 并立即妥善保存。Token 只会完整显示一次。
+
+### 创建阿里云云监控 Webhook
+
+1. 登录 [阿里云云监控 2.0 控制台](https://cmsnext.console.aliyun.com/)。
+2. 选择或创建目标工作空间,然后进入 **告警中心** > **通知管理** > **通知对象**。
+3. 选择 **自定义 Webhook** 页签,单击 **新建 Webhook**。
+4. 填写 Webhook 配置:
+ - 名称:`HertzBeat`
+ - 标识符:例如 `hertzbeat`
+ - URL:
+
+ ```text
+ http://{hertzbeat_host}:1157/api/alerts/report/alibabacloud-cms
+ ```
+
+ - Headers:添加 `Authorization`,值为 `Bearer {token}`
+ - Method:`POST`
+ - 数据格式:`JSON`
+ - 语言:按需选择
+5. 保存 Webhook。
+
+> 请使用云监控 2.0 工作空间内的通知对象。Prometheus 监控或 ARMS 告警管理中的通知对象使用不同的 Webhook 格式,不适用于此集成。
+
+> `{hertzbeat_host}` 必须是阿里云云监控可以访问的公网地址。生产环境建议通过 HTTPS 反向代理暴露此接口。
+
+### 绑定告警规则
+
+1. 进入 **告警中心** > **告警管理** > **告警规则**。
+2. 创建或编辑告警规则。
+3. 在告警通知中选择上一步创建的 HertzBeat 自定义 Webhook。
+4. 如需在 HertzBeat 中自动恢复告警,请同时启用恢复通知。
+5. 保存并启用告警规则。
+
+### 字段映射
+
+| 阿里云云监控字段 | HertzBeat 字段 |
+| --- | --- |
+| `status: OCCURRED/PERSISTENT` | `status: firing` |
+| `status: RESOLVED/RECOVERED` | `status: resolved` |
+| `subject` | `labels.alertname` |
+| `severity` | `labels.severity` |
+| `alertMessage` | 告警内容 |
+| `labels`、`resource.tags` | 告警标签 |
+| `annotations`、阈值和资源属性 | 告警注解 |
+| `timestamp` 或 `time` | 告警时间 |
+
+### 常见问题
+
+#### 返回 401 或 403
+
+- 确认已创建有效的 HertzBeat API Token。
+- 确认 Webhook Header 名称为 `Authorization`,值以 `Bearer ` 开头。
+
+#### HertzBeat 未收到告警
+
+- 确认 Webhook URL 可从公网访问,并且端口已放行。
+- 确认数据格式选择为 `JSON`,请求方法选择为 `POST`。
+- 检查阿里云云监控的告警历史以及 HertzBeat 服务日志。
+- 若配置了来源 IP 白名单,请以阿里云官方文档中的最新地址段为准。
+
+#### 告警没有自动恢复
+
+- 确认告警规则或通知策略已启用恢复通知。
+- 确认恢复 Webhook 中的 `status` 为 `RESOLVED` 或 `RECOVERED`。
+
+更多信息请参考:
+
+- [阿里云云监控通知对象与 Webhook 字段](https://help.aliyun.com/zh/cms/cloudmonitor-2-0/notification-object)
+- [阿里云云监控告警规则](https://help.aliyun.com/zh/cms/cloudmonitor-2-0/alert-rules-cms-2-0)
diff --git a/web-app/src/assets/i18n/en-US.json b/web-app/src/assets/i18n/en-US.json
index 369ca6600af..d90653bbcf6 100644
--- a/web-app/src/assets/i18n/en-US.json
+++ b/web-app/src/assets/i18n/en-US.json
@@ -100,6 +100,7 @@
"alert.integration.source.skywalking": "SkyWalking",
"alert.integration.source.uptime-kuma": "Uptime Kuma",
"alert.integration.source.zabbix": "Zabbix",
+ "alert.integration.source.alibabacloud-cms": "Alibaba Cloud Monitor",
"alert.integration.source.alibabacloud-sls": "AlibabaCloud-SLS",
"alert.integration.source.huaweicloud-ces": "Huawei Cloud Eye",
"alert.integration.source.volcengine": "Volcengine Monitoring",
diff --git a/web-app/src/assets/i18n/ja-JP.json b/web-app/src/assets/i18n/ja-JP.json
index 41f9776a829..6abb46ef906 100644
--- a/web-app/src/assets/i18n/ja-JP.json
+++ b/web-app/src/assets/i18n/ja-JP.json
@@ -100,6 +100,7 @@
"alert.integration.source.skywalking": "SkyWalking",
"alert.integration.source.uptime-kuma": "Uptime Kuma",
"alert.integration.source.zabbix": "Zabbix",
+ "alert.integration.source.alibabacloud-cms": "Alibaba Cloud Monitor",
"alert.integration.source.alibabacloud-sls": "AlibabaCloud-SLS",
"alert.integration.source.huaweicloud-ces": "Huawei Cloud Eye",
"alert.integration.source.volcengine": "火山エンジン監視",
diff --git a/web-app/src/assets/i18n/ko-KR.json b/web-app/src/assets/i18n/ko-KR.json
index 23145f738b9..34ee1f4b1ad 100644
--- a/web-app/src/assets/i18n/ko-KR.json
+++ b/web-app/src/assets/i18n/ko-KR.json
@@ -100,6 +100,7 @@
"alert.integration.source.skywalking": "SkyWalking",
"alert.integration.source.uptime-kuma": "Uptime Kuma",
"alert.integration.source.zabbix": "Zabbix",
+ "alert.integration.source.alibabacloud-cms": "Alibaba Cloud Monitor",
"alert.integration.source.alibabacloud-sls": "AlibabaCloud-SLS",
"alert.integration.source.huaweicloud-ces": "Huawei Cloud Eye",
"alert.integration.source.volcengine": "Volcengine Monitoring",
diff --git a/web-app/src/assets/i18n/pt-BR.json b/web-app/src/assets/i18n/pt-BR.json
index e089b95d532..601f2bb9885 100644
--- a/web-app/src/assets/i18n/pt-BR.json
+++ b/web-app/src/assets/i18n/pt-BR.json
@@ -251,6 +251,7 @@
"alert.integration.source.prometheus": "Prometheus",
"alert.integration.source.tencent": "Monitoramento de nuvem Tencent",
"alert.integration.source.webhook": "PadrãoWebhook",
+ "alert.integration.source.alibabacloud-cms": "Alibaba Cloud Monitor",
"alert.integration.source.alibabacloud-sls": "AlibabaCloud-SLS",
"alert.integration.source.huaweicloud-ces": "Huawei Cloud Eye",
"alert.integration.source.volcengine": "Volcengine",
diff --git a/web-app/src/assets/i18n/zh-CN.json b/web-app/src/assets/i18n/zh-CN.json
index d6397daa0f1..0eda95a3c0a 100644
--- a/web-app/src/assets/i18n/zh-CN.json
+++ b/web-app/src/assets/i18n/zh-CN.json
@@ -100,6 +100,7 @@
"alert.integration.source.skywalking": "SkyWalking",
"alert.integration.source.uptime-kuma": "Uptime Kuma",
"alert.integration.source.zabbix": "Zabbix",
+ "alert.integration.source.alibabacloud-cms": "阿里云云监控",
"alert.integration.source.alibabacloud-sls": "阿里云日志服务 SLS",
"alert.integration.source.huaweicloud-ces": "华为云监控服务",
"alert.integration.source.volcengine": "火山引擎云监控",
diff --git a/web-app/src/assets/i18n/zh-TW.json b/web-app/src/assets/i18n/zh-TW.json
index 4cdbf1d2be7..8d66b3bd679 100644
--- a/web-app/src/assets/i18n/zh-TW.json
+++ b/web-app/src/assets/i18n/zh-TW.json
@@ -100,6 +100,7 @@
"alert.integration.source.skywalking": "SkyWalking",
"alert.integration.source.uptime-kuma": "Uptime Kuma",
"alert.integration.source.zabbix": "Zabbix",
+ "alert.integration.source.alibabacloud-cms": "阿里雲雲監控",
"alert.integration.source.alibabacloud-sls": "阿里雲端日誌服務 SLS",
"alert.integration.source.huaweicloud-ces": "華為雲監控服務",
"alert.integration.source.volcengine": "火山引擎監控",