---
title: "Webhook 端點"
description: "使用各端點專屬密鑰與事件篩選條件，管理多個 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}/rotate-secret` | `admin+` | 替換簽署密鑰 |
| `POST` | `/v1/developer/webhook-endpoints/{endpoint_id}/test` | `admin+` | 傳送已簽署的測試傳遞 |
| `GET` | `/v1/developer/webhook-deliveries` | `admin+` | 檢查近期端點與舊版傳遞結果 |

## 端點物件

```json
{
  "id": "c4d5e6f7-...",
  "label": "Production — Call events",
  "url": "https://example.com/thunderphone/hook",
  "events": ["telephony.incoming", "telephony.complete"],
  "status": "active",
  "agent_id": 42,
  "agent_name": "Support Agent",
  "secret_hint": "a1b2…9f0e",
  "paused_at": null,
  "pause_last_error": "",
  "pause_undelivered_count": null,
  "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` | array of string | 訂閱的事件類型（請參閱[有效值](#valid-event-types)）。空陣列會訂閱所有事件，但明確指定才會訂閱的逐回合事件（`telephony.turn` / `web.turn`）除外 |
| `status` | string | `active`、`disabled`（手動暫停）或 `failing`（當一次傳遞在 24 小時重試排程中未獲得任何 2xx 回應時自動設定） |
| `agent_id` | integer \| null | 此端點限定的智慧體；`null` 表示適用於整個組織 |
| `agent_name` | string \| null | 限定智慧體的名稱；若端點適用於整個組織則為 `null` |
| `secret_hint` | string | 簽署密鑰的前 4 個及後 4 個字元，並以省略號表示（`a1b2…9f0e`）——足以讓你與本機儲存的密鑰交叉核對，同時不會暴露完整值 |
| `paused_at` | timestamp \| null | ThunderPhone 將端點設為 `failing` 的時間。在端點為 `active` 或 `disabled` 時為 `null` |
| `pause_last_error` | string | 端點暫停時的最後一次傳遞錯誤，例如 `HTTP 503: Service Unavailable`。除非為 `failing`，否則為空白 |
| `pause_undelivered_count` | integer \| null | 端點上次成功傳遞後未能傳遞的事件數，於端點暫停時統計 |
| `created_at`, `updated_at` | timestamp | |

<Note>
  端點的完整 `secret` 僅會在建立時回傳**一次**，
  之後不會再次提供。請安全儲存它——若遺失，
  [輪替它](#rotate-the-signing-secret)以取得新的密鑰。
</Note>

### 有效事件類型

系統會依據以下精確集合驗證 `events`——清單外的值
會傳回 `400`。各類型的承載資料結構請參閱[事件目錄](/zh-Hant/webhooks/events)。

- `telephony.incoming`, `telephony.complete`, `telephony.tool`, `telephony.turn`
- `web.incoming`, `web.complete`, `web.tool`, `web.turn`
- `sms.sent`, `sms.failed`
- `sms.received`（保留；尚未發送）
- `call.graded`, `call.data_extracted`, `call.transfer_completed`
- `campaign.completed`
- `issue.reported`, `issue.escalated`
- `test-call.completed`
- `alert.triggered`

`issue.escalated` 不含智慧體內容，且僅會遞送至
全組織範圍端點。

無法明確選取 `voice.ready` 和 `voice.failed`。如要接收
這些事件，請建立一個設定 `events: []` 的全組織範圍端點。空事件
清單會接收所有支援的事件，但 `telephony.turn` 和 `web.turn` 除外，
這兩者必須明確選取。

### 端點狀態

- `active` ——傳送正常進行。
- `disabled` ——透過 `PATCH` 手動暫停。不會傳送任何請求。我們
  不會變更 `disabled` 端點的狀態；是否將其切回
  `active` 一律由你決定。
- `failing` ——當傳送至端點的作業耗盡整個重試排程（24 小時內嘗試 8 次），
  仍未取得 2xx 回應時，會自動設定為此狀態。失敗中的端點不會再收到任何流量。
  發生此情況時，我們會寄送電子郵件通知你組織的擁有者與管理員，且
  控制台會顯示已暫停的端點及「重新啟用」按鈕。
  修正端點後，透過 `PATCH` 將其狀態改回 `active`；
  尚未耗盡重試排程的傳送作業會從中斷處繼續。

---

## 列出端點

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

傳回一個[端點物件](#endpoint-object)陣列。
傳入 `?agent_id=42`，即可僅傳回限定於該智慧體的端點。

### 智慧體限定端點

全組織範圍端點會接收所有相符事件。具有
`agent_id` 的端點僅會接收由該智慧體處理之通話的相符事件；
不含智慧體內容的事件（例如 `alert.triggered`）絕不會傳送至該端點。你
也可以在智慧體建立工具的
**Webhook** 區段建立及管理這些端點。

---

## 建立端點

<CodeGroup>
```bash cURL
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
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` | 陣列 | 否 | 空白或省略時會訂閱除 `telephony.turn` / `web.turn` 外的所有事件，這兩種事件需要明確訂閱。必須使用[有效事件類型](#valid-event-types)中列出的值；重複項目會被移除 |
| `agent_id` | 整數 \| null | 否 | 將傳送範圍限定於此組織中的某個智慧體；省略或使用 `null` 則為組織層級端點 |

傳回 `201 Created`，包含[端點物件](#endpoint-object)以及額外的頂層 `secret` 欄位，其中包含原始簽章金鑰——一個 48 個字元的十六進位字串：

```json
{
  "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
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`，即可重新啟用 |
| `agent_id` | 整數 \| null | 設定智慧體 ID 以限定端點範圍，或設為 `null` 使其成為組織層級端點 |

傳回 `200 OK`，包含更新後的[端點物件](#endpoint-object)。

---

## 輪替簽署密鑰

更換端點的簽署密鑰，例如密鑰遺失或可能外洩時。對於限定智慧體範圍的端點，你也可以使用
控制台：開啟智慧體的 **Webhook** 區段，然後在端點上選擇
**重新產生密鑰**。組織範圍的端點需透過 API 輪替。

<CodeGroup>
```bash cURL
curl -X POST https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-.../rotate-secret \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
```
</CodeGroup>

| 欄位 | 類型 | 必填 | 說明 |
|-------|------|----------|-------------|
| `include_copies` | 布林值 | 否 | 預設為 `true`。也會將新密鑰提供給組織中具有相同 URL 與相同目前密鑰的其他端點，例如此端點在其他智慧體上的副本，讓單一接收端可持續使用同一個密鑰進行驗證 |

回傳 `200 OK`：

```json
{
  "endpoint": { "id": "c4d5e6f7-...", "secret_hint": "7f3a…c21d", "...": "..." },
  "secret": "7f3a90b2c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5c21d",
  "rotated_endpoint_ids": ["c4d5e6f7-..."]
}
```

| 欄位 | 類型 | 說明 |
|-------|------|-------------|
| `endpoint` | 物件 | 具有新 `secret_hint` 的 [端點物件](#endpoint-object) |
| `secret` | 字串 | 新的簽署密鑰。僅在此回應中回傳 |
| `rotated_endpoint_ids` | UUID 陣列 | 現在使用新密鑰的每個端點 |

<Warning>
  舊密鑰會立即停止使用：下一次傳送作業，
  包含重試在內，將使用新密鑰簽署。在你的接收端取得
  新密鑰之前，傳送作業會無法通過其簽章檢查；若接收端對
  這些作業回應非 2xx 狀態，系統會依一般的 24 小時
  排程重試，因此請立即更新接收端。若你的接收端採分階段
  部署，請讓它在部署期間接受兩組密鑰——SDK
  驗證輔助工具可接受密鑰清單（請參閱
  [驗證 Webhook 簽章](/zh-Hant/guides/verify-webhook-signatures)）。
</Warning>

---

## 傳送測試傳遞

使用一般傳送流程，將合成的 `webhook.test` 事件傳送至單一端點，其中包括標準 JSON 序列化、兩個簽章標頭、傳送紀錄與重試管理。
無論所選端點的 `events` 篩選條件為何，測試都會以該端點為目標。

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

端點會收到如下的封裝：

```json
{
  "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
{
  "success": true,
  "event_id": "2ad6507c-7d19-4498-9b2d-7e8f944ab5a1",
  "event_type": "webhook.test",
  "status": "delivered",
  "response_code": 204,
  "error": ""
}
```

`webhook.test` 為模擬事件，無法加入端點的 `events`
訂閱。若第一次嘗試失敗，ThunderPhone 約一分鐘後會重試一次，
之後便停止；傳遞將在[偵錯傳遞](#debug-deliveries)下顯示
`status: "failed"`。測試傳遞絕不會將端點標示為 `failing`。

若要針對真實事件結構設定觸發條件，請傳入選用的
`event_type`。傳遞仍為模擬傳遞，並包含 `"sample": true`；
與通話相關的範例會使用 `call_id: 0` 與 `agent_id: 0`。

```bash
curl -X POST https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-.../test \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"event_type":"call.graded"}'
```

`event_type` 可接受[有效事件類型](#valid-event-types)中的任何值。
省略此欄位會保留通用的 `webhook.test` 行為。

---

## 刪除端點

<CodeGroup>
```bash cURL
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；
進行中的重試會被取消。

---

## 偵錯傳遞

在判定 Webhook 未送出前，請查看
[`GET /v1/developer/webhook-deliveries`](/api-reference/webhook-deliveries)。
此端點會顯示兩個 Webhook 系統最近的嘗試紀錄，包括通話 ID、
URL 來源、HTTP 狀態、嘗試次數、允許清單中的失敗類別，以及下次
重試時間。它絕不會回傳事件承載資料、逐字稿、儲存的錯誤文字、
回應主體或 URL 路徑。

你也可以在 **智慧體 → 選取智慧體 → Webhook →
最近傳遞紀錄** 中查看相同的近期紀錄。各列會顯示端點標籤，以及最新
嘗試所使用的 URL 來源。這是操作狀態，而非不可變更的稽核紀錄：刪除端點
也會刪除其傳遞資料列。

若 n8n 出現 `404`，請先確認工作流程已啟用、接受 `POST`，且使用的是
正式環境 Webhook URL，而非測試 URL。`401` 或 `403` 表示可能是
驗證或簽章驗證問題；逾時表示目標端延遲或無法使用；TLS 錯誤則表示
憑證鏈、主機名稱或到期日有問題。

---

## 相關內容

<CardGroup cols={2}>
  <Card title="事件目錄" icon="list" href="/zh-Hant/webhooks/events">
    你可訂閱的完整 `events` 值清單。
  </Card>
  <Card title="Webhook 概覽" icon="bolt" href="/zh-Hant/webhooks/overview">
    簽章驗證與傳遞語意。
  </Card>
</CardGroup>
