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

# Webhook 端点

> 使用每个端点独立的密钥和事件筛选器管理多个 webhook URL。

基于端点的 webhook 系统允许您为每个组织注册**多个**目标地址，每个目标地址都有自己的密钥、状态以及对部分事件类型的订阅。这是所有新集成推荐使用的模式。

与[旧版单 URL webhook](/api-reference/organizations#legacy-single-url-webhook)相比，后者仅为向后兼容而保留，且每个组织仅支持一个 URL。

## 端点

| 方法       | 路径                                                   | 所需角色     | 描述                   |
| -------- | ---------------------------------------------------- | -------- | -------------------- |
| `GET`    | `/v1/developer/webhook-endpoints`                    | `admin+` | 列出端点                 |
| `POST`   | `/v1/developer/webhook-endpoints`                    | `admin+` | 创建端点                 |
| `PATCH`  | `/v1/developer/webhook-endpoints/{endpoint_id}`      | `admin+` | 更新标签 / URL / 事件 / 状态 |
| `DELETE` | `/v1/developer/webhook-endpoints/{endpoint_id}`      | `admin+` | 删除端点                 |
| `POST`   | `/v1/developer/webhook-endpoints/{endpoint_id}/test` | `admin+` | 发送已签名的测试投递           |

## 端点对象

```json theme={null}
{
  "id": "c4d5e6f7-...",
  "label": "Production — Call events",
  "url": "https://example.com/thunderphone/hook",
  "events": ["telephony.incoming", "telephony.complete"],
  "status": "active",
  "secret_hint": "a1b2…9f0e",
  "created_at": "2026-04-20T18:24:10.113Z",
  "updated_at": "2026-04-20T18:24:10.113Z"
}
```

| 字段                         | 类型        | 描述                                                                            |
| -------------------------- | --------- | ----------------------------------------------------------------------------- |
| `id`                       | UUID      | 端点 ID                                                                         |
| `label`                    | string    | 显示名称，1–120 个字符                                                                |
| `url`                      | string    | HTTPS URL；开发环境允许使用 `http://localhost`                                         |
| `events`                   | string 数组 | 订阅的事件类型（请参阅[有效值](#valid-event-types)）。空数组表示订阅所有事件                             |
| `status`                   | string    | `active`、`disabled`（手动暂停）或 `failing`（当一次投递在 24 小时重试计划内耗尽重试次数且未获得任何 2xx 时自动设置） |
| `secret_hint`              | string    | 签名密钥的前 4 个和后 4 个字符，以省略号分隔（`a1b2…9f0e`）——足以让您与本地保存的密钥进行交叉核对，同时不会暴露完整值          |
| `created_at`, `updated_at` | timestamp |                                                                               |

<Note>
  端点完整的 `secret` 仅会在创建时**返回一次**，之后不会再次返回。请妥善保存——如果丢失，请删除该端点并重新创建。
</Note>

### 有效事件类型

`events` 会根据以下精确集合进行验证——列表外的值将返回 `400`。有关每种类型的负载结构，请参阅[事件目录](/zh/webhooks/events)。

* `telephony.incoming`, `telephony.complete`, `telephony.tool`
* `web.incoming`, `web.complete`, `web.tool`
* `call.graded`
* `issue.reported`
* `test-call.completed`
* `alert.triggered`

### 端点状态

* `active` ——投递正常进行。
* `disabled` ——通过 `PATCH` 手动暂停。不会发送任何请求。我们绝不会更改 `disabled` 端点的状态；是否将其切换回 `active` 始终由您决定。
* `failing` ——当向端点投递时耗尽整个重试计划（24 小时内尝试 8 次）且始终未获得 2xx，系统会自动设置此状态。处于失败状态的端点不会再接收流量。修复端点后，通过 `PATCH` 将其状态改回 `active`；尚未耗尽重试计划的投递将从中断处继续。

***

## 列出端点

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.thunderphone.com/v1/developer/webhook-endpoints \
    -H "Authorization: Bearer sk_live_YOUR_API_KEY"
  ```
</CodeGroup>

返回一个[端点对象](#endpoint-object)数组。

***

## 创建端点

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.thunderphone.com/v1/developer/webhook-endpoints \
    -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "label":  "Production — Call events",
      "url":    "https://example.com/thunderphone/hook",
      "events": ["telephony.incoming", "telephony.complete"]
    }'
  ```

  ```python Python theme={null}
  result = requests.post(
      "https://api.thunderphone.com/v1/developer/webhook-endpoints",
      headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
      json={
          "label":  "Production — Call events",
          "url":    "https://example.com/thunderphone/hook",
          "events": ["telephony.incoming", "telephony.complete"],
      },
  ).json()
  secret = result["secret"]
  endpoint_id = result["id"]
  ```
</CodeGroup>

### 请求字段

| 字段       | 类型  | 必填 | 说明                                                         |
| -------- | --- | -- | ---------------------------------------------------------- |
| `label`  | 字符串 | 是  | 1–120 个字符                                                  |
| `url`    | 字符串 | 是  | HTTPS URL（仅 `localhost` / `127.0.0.1` 允许使用 `http`）         |
| `events` | 数组  | 否  | 为空或省略时订阅所有事件。必须使用[有效事件类型](#valid-event-types)中列出的值；重复项将被移除 |

返回 `201 Created` 以及[端点对象](#endpoint-object)，并额外包含一个顶级 `secret` 字段，其中包含原始签名密钥——一个 48 字符的十六进制字符串：

```json theme={null}
{
  "id": "c4d5e6f7-…",
  "label": "Production — Call events",
  "url": "https://example.com/thunderphone/hook",
  "events": ["telephony.incoming", "telephony.complete"],
  "status": "active",
  "secret_hint": "a1b2…9f0e",
  "created_at": "2026-04-20T18:24:10.113Z",
  "updated_at": "2026-04-20T18:24:10.113Z",
  "secret": "a1b2c37e08d94f5b16a2c8d90e7f3a4b5c6d7e8f90a19f0e"
}
```

<Warning>
  `secret` **仅在创建时**返回。后续的 `GET` 响应仅包含 `secret_hint`。请在关闭响应前，将完整值复制到您的密钥管理器中。
</Warning>

***

## 更新端点

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PATCH https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-... \
    -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "label":  "Production — Call + Grade events",
      "events": ["telephony.incoming", "telephony.complete", "call.graded"]
    }'
  ```
</CodeGroup>

| 字段       | 类型  | 说明                                                             |
| -------- | --- | -------------------------------------------------------------- |
| `label`  | 字符串 |                                                                |
| `url`    | 字符串 |                                                                |
| `events` | 数组  |                                                                |
| `status` | 字符串 | `active` 或 `disabled`。要重新启用被服务器标记为 `failing` 的端点，请设置为 `active` |

返回 `200 OK` 以及更新后的[端点对象](#endpoint-object)。

***

## 发送测试投递

使用常规投递管道向一个端点发送合成的 `webhook.test` 事件，其中包括规范化 JSON 序列化、`X-ThunderPhone-Signature`、投递记录和重试记录。无论端点的 `events` 过滤条件如何，测试都会以所选端点为目标。

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-.../test \
    -H "Authorization: Bearer sk_live_YOUR_API_KEY"
  ```
</CodeGroup>

端点会收到如下封装对象：

```json theme={null}
{
  "data": {
    "message": "ThunderPhone webhook test",
    "sent_at": "2026-07-17T20:12:34.567890+00:00"
  },
  "event_id": "2ad6507c-7d19-4498-9b2d-7e8f944ab5a1",
  "type": "webhook.test"
}
```

API 会在首次尝试后返回 `200 OK`，即使目标地址返回错误也是如此。请检查 `success`、`status`、`response_code` 和 `error` 以了解投递结果：

```json theme={null}
{
  "success": true,
  "event_id": "2ad6507c-7d19-4498-9b2d-7e8f944ab5a1",
  "event_type": "webhook.test",
  "status": "delivered",
  "response_code": 204,
  "error": ""
}
```

`webhook.test` 是合成事件，无法添加到端点的 `events` 订阅中。如果首次尝试失败，投递将遵循与常规事件投递相同的重试计划。

***

## 删除端点

<CodeGroup>
  ```bash cURL theme={null}
  curl -X DELETE https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-... \
    -H "Authorization: Bearer sk_live_YOUR_API_KEY"
  ```
</CodeGroup>

返回 `204 No Content`。将立即停止向该 URL 发送事件；
正在进行中的重试将被放弃。

***

## 相关内容

<CardGroup cols={2}>
  <Card title="事件目录" icon="list" href="/zh/webhooks/events">
    您可以订阅的完整 `events` 值列表。
  </Card>

  <Card title="Webhook 概览" icon="bolt" href="/zh/webhooks/overview">
    签名验证和投递语义。
  </Card>
</CardGroup>
