> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ycloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 配置 Webhook

> 在您的 HTTPS 端点接收 YCloud 事件。

## 功能简介

Webhook 是 YCloud 在消息送达、入站消息、联系人、模板、通话以及其他资源发生变动时，向您的应用程序发送的 HTTPS 请求。

## 开始之前

* 将您的 YCloud API 密钥存储在 `YCLOUD_API_KEY` 中。
* 部署一个公网可访问的 HTTPS 端点。
* 保留原始请求体以进行签名验证。
* 确定您的应用程序需要哪些事件类型。

## 工作原理

1. 创建一个 Webhook 端点并为其订阅事件类型。
2. 存储返回的端点 `secret`。
3. YCloud 向您的端点发送事件请求。
4. 在信任请求之前验证 `YCloud-Signature`。
5. 及时返回 `2xx` 响应。
6. 以幂等方式处理事件，因为推送可能会重复。

## 请求

使用 `POST /webhookEndpoints` 创建端点。

### 请求字段

| 字段 | 是否必填 | 描述 |
| - | - | - |
| `url` | 是 | 接收事件请求的公网 HTTPS URL。最多 500 个字符。 |
| `enabledEvents` | 是 | 推送到此端点的事件类型。 |
| `eventProperties` | 条件必填 | 为所选事件类型包含的属性。对 `contact.attributes_changed` 为必填项。 |
| `description` | 否 | 端点的描述。最多 400 个字符。 |
| `status` | 否 | 端点的初始状态。 |

### 请求示例

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request POST https://api.ycloud.com/v2/webhookEndpoints \
  --header "X-API-Key: $YCLOUD_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "url": "https://example.com/webhooks/ycloud",
    "enabledEvents": [
      "whatsapp.inbound_message.received",
      "whatsapp.message.updated",
      "sms.message.updated"
    ],
    "description": "Production messaging events"
}'
```

### 订阅回显与交接事件

对于通过公开 REST API 接入的 Agent，请创建包含以下订阅的端点。在控制台创建的 Agent 不会触发这三个事件。如需修改现有端点，请保留您仍需要的任何事件订阅。

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request POST https://api.ycloud.com/v2/webhookEndpoints \
  --header "X-API-Key: $YCLOUD_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "url": "https://example.com/webhooks/ycloud",
    "enabledEvents": [
      "whatsapp.echo_message.created",
      "whatsapp.echo_message.updated",
      "whatsapp.meta_business_agent.handover.updated",
      "whatsapp.inbound_message.received"
    ],
    "description": "API Agent echo and handover events"
  }'
```

这两种回显事件类型携带标准消息格式的 `whatsappMessage` 负载。交接事件携带 `whatsappMetaBusinessAgent` 并保留其 Agent/控制信息。它们不使用 WhatsApp Business App `whatsapp.smb.message.echoes` 约定。有关字段定义、示例、顺序以及交接关联限制，请参见 [回显和交接事件详情](/zh/api-reference/guides/examples/webhook-examples/overview#echo-and-agent-handover-events)。

## 响应

响应会返回创建的端点及其签名 `secret`。请妥善保存该密钥。YCloud 会使用它来生成 Webhook 签名。

### 响应示例

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "id": "WEBHOOK_ENDPOINT_ID",
  "url": "https://example.com/webhooks/ycloud",
  "enabledEvents": [
    "whatsapp.inbound_message.received",
    "whatsapp.message.updated",
    "sms.message.updated"
  ],
  "description": "Production messaging events",
  "status": "active",
  "secret": "whsec_REPLACE_WITH_RETURNED_SECRET",
  "createTime": "2026-07-16T12:00:00.000Z",
  "updateTime": "2026-07-16T12:00:00.000Z"
}
```

### 响应字段

| 字段 | 描述 |
| - | - |
| `id` | Webhook 端点 ID，用于获取、更新、删除或轮换端点密钥。 |
| `url` | 事件推送的目标 URL。 |
| `enabledEvents` | 当前已启用的事件类型。 |
| `status` | 端点的当前状态。 |
| `secret` | 用于验证 `YCloud-Signature` 的密钥。请妥善保存。 |
| `createTime`、`updateTime` | RFC 3339 格式的端点时间戳。 |

## 接收事件

### 事件请求

YCloud 向配置的 `url` 发送一个 JSON 事件对象。该事件包含通用字段，例如 `id`、`type`、`apiVersion` 和 `createTime`，以及特定类型的负载。

您的处理程序应当：

1. 读取原始请求体。
2. 在信任负载之前，使用端点密钥验证 `YCloud-Signature` 请求头。
3. 及时返回成功的 `2xx` 响应。
4. 将耗时较长的处理移至队列中。
5. 保证事件处理的幂等性，以确保重复推送不会重复执行业务操作。

<Warning>
  在签名验证之前，请勿解析或修改请求体。请使用服务器接收到的精确原始字节。
</Warning>

### 接收端响应

一旦签名和请求被接受，请立即返回成功的 `2xx` HTTP 响应。响应体可以为空。

```http theme={"theme":{"light":"github-light","dark":"github-dark"}}
HTTP/1.1 204 No Content
```

将耗时较长的业务处理移至队列中。超时或非 `2xx` 响应可能会导致 YCloud 重试该事件，因此请按事件 `id` 进行去重。

## 常用负载示例

展开事件以查看其完整的示例负载。这些示例来自 OpenAPI webhook 规范。有关每种受支持的事件类型，请参见 [所有 webhook 负载示例](/zh/api-reference/guides/examples/webhook-examples/webhook-payload-examples)。

<AccordionGroup>
  <Accordion title="联系人属性变更事件">
    联系人属性变更时的示例负载

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_1234567890",
      "type": "contact.attributes_changed",
      "apiVersion": "v2",
      "createTime": "2024-01-01T12:00:00.000Z",
      "contactAttributesChanged": {
        "id": "1824266594102064128",
        "updateTime": "2024-01-01T12:00:00.000Z",
        "changedAttributes": {
          "nickName": {
            "oldValue": "John Doe",
            "newValue": "Johnny Doe"
          },
          "email": {
            "oldValue": "john.doe@example.com",
            "newValue": "johnny.doe@example.com"
          },
          "tags": {
            "oldValue": [
              "premium",
              "newsletter"
            ],
            "newValue": [
              "premium",
              "newsletter",
              "vip"
            ],
            "extra": [
              {
                "action": "ADDED",
                "id": "686dd294334be8606a5bf312",
                "value": "vip"
              }
            ]
          }
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="联系人创建事件">
    创建新联系人时的示例负载

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_2345678901",
      "type": "contact.created",
      "apiVersion": "v2",
      "createTime": "2024-01-01T12:00:00.000Z",
      "contactCreated": {
        "id": "1824266594102064128",
        "nickName": "John Doe",
        "realName": "John Smith",
        "phoneNumber": "+16315551111",
        "countryCode": "US",
        "countryName": "United States",
        "email": "john.doe@example.com",
        "sourceType": "api",
        "sourceId": "import_batch_123",
        "sourceUrl": "https://example.com/signup",
        "lastSeen": "2024-01-01T11:59:00.000Z",
        "lastConnectedNumber": "+16315552222",
        "ownerEmail": "owner@example.com",
        "tags": [
          "premium",
          "newsletter"
        ],
        "createTime": "2024-01-01T12:00:00.000Z",
        "updateTime": "2024-01-01T12:00:00.000Z",
        "blocked": false,
        "customAttributes": {
          "attr1": "value1",
          "attr2": "value2",
          "attr3": 123
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="联系人删除事件">
    联系人被删除时的示例负载

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_3456789012",
      "type": "contact.deleted",
      "apiVersion": "v2",
      "createTime": "2024-01-01T12:00:00.000Z",
      "contactDeleted": {
        "id": "1824266594102064128",
        "nickName": "John Doe",
        "phoneNumber": "+16315551111",
        "updateTime": "2024-01-01T12:00:00.000Z"
      }
    }
    ```
  </Accordion>

  <Accordion title="客户取消订阅事件">
    客户取消订阅时的示例负载

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_3456789012",
      "type": "contact.unsubscribe.created",
      "apiVersion": "v2",
      "createTime": "2024-01-01T12:00:00.000Z",
      "unsubscriberChanged": {
        "phoneNumber": "+16315551111",
        "source": "Whatsapp",
        "updateTime": "2024-01-01T12:00:00.000Z"
      }
    }
    ```
  </Accordion>

  <Accordion title="客户恢复订阅">
    客户恢复订阅时的示例负载

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_3456789012",
      "type": "contact.unsubscribe.deleted",
      "apiVersion": "v2",
      "createTime": "2024-01-01T12:00:00.000Z",
      "unsubscriberChanged": {
        "phoneNumber": "+16315551111",
        "source": "Whatsapp",
        "updateTime": "2024-01-01T12:00:00.000Z"
      }
    }
    ```
  </Accordion>

  <Accordion title="WhatsApp 模板归档事件">
    WhatsApp 消息模板归档时的示例负载

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_template_archived_123",
      "type": "whatsapp.template.reviewed",
      "apiVersion": "v2",
      "createTime": "2024-01-01T12:00:00.000Z",
      "whatsappTemplate": {
        "id": "template-id",
        "officialTemplateId": "official-template-id",
        "wabaId": "whatsapp-business-account-id",
        "name": "sample_whatsapp_template",
        "language": "en",
        "category": "MARKETING",
        "status": "ARCHIVED",
        "statusUpdateEvent": "ARCHIVED",
        "createTime": "2024-01-01T12:00:00.000Z",
        "updateTime": "2024-01-01T12:00:00.000Z"
      }
    }
    ```
  </Accordion>

  <Accordion title="WhatsApp 模板取消归档事件">
    WhatsApp 消息模板取消归档时的示例负载。模板状态为 Meta 返回的当前状态，并不代表重新进行了审核。

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_template_unarchived_123",
      "type": "whatsapp.template.reviewed",
      "apiVersion": "v2",
      "createTime": "2024-01-01T12:00:00.000Z",
      "whatsappTemplate": {
        "id": "template-id",
        "officialTemplateId": "official-template-id",
        "wabaId": "whatsapp-business-account-id",
        "name": "sample_whatsapp_template",
        "language": "en",
        "category": "MARKETING",
        "status": "APPROVED",
        "statusUpdateEvent": "UNARCHIVED",
        "createTime": "2024-01-01T12:00:00.000Z",
        "updateTime": "2024-01-01T12:00:00.000Z"
      }
    }
    ```
  </Accordion>

  <Accordion title="WhatsApp 通话接通事件">
    WhatsApp 通话接通时的示例负载

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_call_connect_123",
      "type": "whatsapp.call.connect",
      "apiVersion": "v2",
      "createTime": "2024-01-01T12:00:00.000Z",
      "callingConnect": {
        "id": "6757b723960b25543b9ecc66",
        "wacid": "wacid.HBgNNjI4MTM2MTkwNTEzMxUCABIYIEF",
        "phoneId": "461269257068832",
        "from": "+6281361905133",
        "to": "+6283138205150",
        "direction": "USER_INITIATED",
        "dialTime": 1733826430000,
        "sdpType": "offer",
        "sdp": "v=0\r\no=- 1732169627243 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE audio\r\na=msid-semantic: WMS af3b01e3-eb42-4244-812e-db903c062ae7\r\na=ice-lite\r\nm=audio 3480 UDP/TLS/RTP/SAVPF 111 126\r\nc=IN IP4 31.13.87.130\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=candidate:785588535 1 udp 2122260223 31.13.87.130 3480 typ host generation 0 network-cost 50\r\na=candidate:1906600321 1 udp 2122262783 2a03:2880:f217:d0:face:b00c:0:699c 3480 typ host generation 0 network-cost 50\r\na=ice-ufrag:CvRXRnInnWhQzLIE\r\na=ice-pwd:HGXUGAFI8wK6seuVknBT2Q==\r\na=fingerprint:sha-256 FB:56:A1:C5:37:35:6C:5C:1B:05:23:B0:DD:BB:2E:C9:5F:E4:70:61:7B:D9:1D:09:84:76:46:23:12:38:B7:01\r\na=setup:actpass\r\na=mid:audio\r\na=sendrecv\r\na=msid:af3b01e3-eb42-4244-812e-db903c062ae7 WhatsAppTrack1\r\na=rtcp-mux\r\na=rtpmap:111 opus/48000/2\r\na=rtcp-fb:111 transport-cc\r\na=fmtp:111 maxaveragebitrate=20000;maxplaybackrate=16000;minptime=20;sprop-maxcapturerate=16000;useinbandfec=1\r\na=rtpmap:126 telephone-event/8000\r\na=maxptime:20\r\na=ptime:20\r\na=ssrc:659928310 cname:WhatsAppAudioStream1\r\n"
      }
    }
    ```
  </Accordion>

  <Accordion title="WhatsApp 通话结束事件">
    WhatsApp 通话结束时的载荷示例

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_6757b889a5a42d369ef48481",
      "type": "whatsapp.call.terminate",
      "apiVersion": "v2",
      "createTime": "2024-12-10T03:42:01.822Z",
      "callingTerminate": {
        "id": "6757b889960b25543b9ecc67",
        "wacid": "wacid.HBgNNjI4MTM2MTkwNTEzMxUCABIYIEFENjB",
        "phoneId": "461269257068832",
        "from": "+6281361905133",
        "to": "+6283138205150",
        "direction": "USER_INITIATED",
        "startTime": 1733734738000,
        "endTime": 1733734771000,
        "duration": 33,
        "status": "COMPLETED"
      }
    }
    ```
  </Accordion>

  <Accordion title="WhatsApp 通话状态更新事件">
    WhatsApp 通话状态更新时的载荷示例

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_676e5ab57a9cb742d02d7646",
      "type": "whatsapp.call.status.updated",
      "apiVersion": "v2",
      "createTime": "2024-12-27T07:41:28.422Z",
      "callingStatusUpdated": {
        "wabaId": "188234691048809",
        "wacid": "wacid.HBgNNjI4MTM2MTkwNTEzMxUCABE",
        "status": "RINGING",
        "recipientPhone": "+6281361905133"
      }
    }
    ```
  </Accordion>
</AccordionGroup>

有关完整的 `Event` 规范和交互式载荷参考，请参阅 [Webhook 事件载荷](/zh/api-reference/webhooks/test-webhooks)。

## 轮换终端节点密钥

如果密钥泄露或根据安全策略的要求，请轮换密钥：

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request POST \
  https://api.ycloud.com/v2/webhookEndpoints/WEBHOOK_ENDPOINT_ID/rotateSecret \
  --header "X-API-Key: $YCLOUD_API_KEY"
```

轮换后立即将新密钥部署到您的接收端。

<Note>
  反复无法接收通知的终端节点可能会变为 `pending` 状态并停止接收事件。请监控 Webhook 失败情况和终端节点状态。
</Note>

有关签名验证代码、重试间隔和接收端实现，请参阅
[实现 Webhook 接收端](/zh/api-reference/guides/api-fundamentals/implement-a-webhook-receiver)。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.