> ## Documentation Index
> Fetch the complete documentation index at: https://test-8ad8522e-feat-doc-review-auto-fix.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# 自定义变更事件

> 通过标准协议推送自有系统变更事件到 Flashduty On-call，大部分故障由变更导致，变更和告警事件联动有助于快速定位故障原因

<Tip>**版本要求**：此功能需要 On-call 标准版及以上订阅。[了解更多](https://flashcat.cloud/flashduty/price/)</Tip>

<Tip>
  Flashduty On-call 已适配部分常用工单、部署系统的 webhook 协议，对于这些系统您应该首先使用对应的集成。本集成提供了一个标准的 HTTP 接口，需要您开发适配，好处是可以与任何部署系统集成。
</Tip>

## 操作步骤

<Steps>
  <Step title="进入集成中心">
    进入 Flashduty 控制台，选择 **集成中心 => 变更事件**，进入集成选择页面。
  </Step>

  <Step title="创建集成">
    选择 **自定义事件** 集成，为当前集成定义一个名称。
  </Step>

  <Step title="获取推送地址">
    点击 **保存** 后，复制当前页面新生成的 **推送地址** 备用。
  </Step>
</Steps>

## 实现协议

### 请求描述

请求方式：

```http theme={null}
POST, Content-Type: application/json
```

请求地址为集成详情页展示的 **推送地址**，格式如下：

```text theme={null}
{api_host}/event/push/change/standard?integration_key={integration_key}
```

### 请求参数

#### Headers

| 字段           |  必含 | 类型     | 说明                      |
| :----------- | :-: | :----- | :---------------------- |
| Content-Type |  是  | string | 固定值：`application/json`。 |

#### Query Strings

| 字段               |  必含 | 类型     | 说明                          |
| :--------------- | :-: | :----- | :-------------------------- |
| integration\_key |  是  | string | 集成秘钥，用于访问控制。创建集成后可在推送地址中获取。 |

#### Payload

| 字段             |  必含 | 类型      | 说明                                                                                          |
| :------------- | :-: | :------ | :------------------------------------------------------------------------------------------ |
| title          |  是  | string  | 变更标题，例如发布单标题、工单标题或部署任务名称。                                                                   |
| change\_key    |  是  | string  | 变更标识。相同 `change_key` 会被识别为同一个变更，后续事件会更新该变更的状态、标签和链接。                                        |
| change\_status |  是  | string  | 变更状态。枚举值（首字母大写）：`Planned` 计划中、`Ready` 待执行、`Processing` 执行中、`Canceled` 已取消、`Done` 已完成。       |
| event\_time    |  否  | integer | 事件发生时间，Unix 时间戳。支持秒级或毫秒级时间戳；未传时使用 Flashduty 接收事件的时间。                                        |
| description    |  否  | string  | 变更描述，例如变更内容、影响范围、执行步骤或回滚方案。                                                                 |
| link           |  否  | string  | 变更详情链接，例如发布单、工单或 CI/CD 任务地址。                                                                |
| labels         |  否  | map     | 变更标签集合，key 和 value 均为 string 类型。建议 key 遵循 Prometheus 标签命名规范；系统会将 key 中的空格、点号、斜杠等特殊字符替换为下划线。 |

<Note>
  当 `change_status` 为 `Done` 或 `Canceled` 时，Flashduty 会将该事件时间记录为变更结束时间；再次上报非结束状态时，结束时间会被清空。
</Note>

### 请求响应

| 字段          |  必含 | 类型              | 说明              |
| :---------- | :-: | :-------------- | :-------------- |
| request\_id |  是  | string          | 请求 ID，用于链路追踪。   |
| error       |  否  | [Error](#error) | 错误描述，仅当出现错误时返回。 |
| data        |  否  | object          | 上报成功时返回空对象。     |

#### Error <span id="error" />

| 字段      |  必含 | 类型     | 说明                       |
| :------ | :-: | :----- | :----------------------- |
| code    |  是  | string | 错误码，枚举值参考 [Code](#code)。 |
| message |  否  | string | 错误描述。                    |

#### Code <span id="code" />

| 错误码                  | HTTP Status | 说明                             |
| :------------------- | :---------: | :----------------------------- |
| InvalidParameter     |     400     | 参数错误，例如缺少必填字段、状态枚举值不合法或集成秘钥无效。 |
| InvalidContentType   |     400     | `Content-Type` 不支持。            |
| MethodNotAllowed     |     405     | HTTP Method 不支持。               |
| Unauthorized         |     401     | 登录认证未通过。                       |
| AccessDenied         |     403     | 权限认证未通过。                       |
| RequestTooFrequently |     429     | 请求过于频繁。                        |
| RouteNotFound        |     404     | 请求 Method 和 Path 未匹配。          |
| ResourceNotFound     |     400     | 账户未购买资源，请先前往费用中心下单。            |
| NoLicense            |     400     | 账户无充足订阅 License，请先升级或购买订阅。     |
| InternalError        |     500     | 内部或未知错误。                       |

### 请求示例

请求：

```bash theme={null}
curl -X POST '{api_host}/event/push/change/standard?integration_key={integration_key}' \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "order-service v1.12.0 production release",
    "change_key": "deploy-order-service-202607231030",
    "change_status": "Processing",
    "event_time": 1784773800,
    "description": "Deploy order-service v1.12.0 to production cluster cn-shanghai-prod.",
    "link": "https://deploy.example.com/releases/deploy-order-service-202607231030",
    "labels": {
      "service": "order-service",
      "env": "prod",
      "cluster": "cn-shanghai-prod",
      "owner": "sre"
    }
  }' -v
```

成功响应：

```json theme={null}
{
  "request_id": "0ace00116215ab4ca0ec5244b8fc54b0",
  "data": {}
}
```

失败响应：

```json theme={null}
{
  "request_id": "0ace00116215abc0ba4e52449bd305b0",
  "error": {
    "code": "InvalidParameter",
    "message": "Key: 'ChangeEvent.ChangeStatus' Error:Field validation for 'ChangeStatus' failed on the 'oneof' tag"
  }
}
```

## 最佳实践

标签是事件的描述，应尽量丰富标签内容：

* **变更的应用范围**：如 host、cluster 等
* **变更的归属信息**：如 team、owner 等
* **变更的生命周期**：同一个变更在计划、执行、完成或取消时，使用相同 `change_key` 持续上报不同 `change_status`，便于在故障时间线上还原变更过程

## 常见问题

<AccordionGroup>
  <Accordion title="为什么在 Flashduty 没有收到变更？">
    **在 Flashduty On-call 排查**

    查看集成是否展示了 **最新事件时间**？如果没有，代表 Flashduty 没有收到推送，请优先排查您的系统。

    **在您的系统排查**

    1. 确认您请求的地址与集成详情中的地址完全一致
    2. 确认您的服务可以访问外网 `api.flashcat.cloud` 域名。如果不可以，您需要为 server 开通外网，或单独针对 Flashduty On-call 的域名开通外网访问
    3. 打印 Flashduty 服务的响应结果，查看是否有明确信息

    如果以上步骤执行后仍未找到问题根因，请 **携带请求响应中的 request\_id** 联系我们。
  </Accordion>
</AccordionGroup>
