> For the complete documentation index, see [llms.txt](https://docs.maiagent.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.maiagent.ai/tech/api-integration/webhook.md).

# Webhook

對話平台 Webhook：把訪客訊息與 AI／真人回覆即時推送到您的系統，支援 MaiAgent 標準格式、Genesys Cloud 與自訂 Jinja2 範本

Webhook 設定在\*\*對話平台（Inbox）\*\*上：每當該平台的對話有新訊息建立，MaiAgent 就會把訊息以 HTTP 請求推送到您指定的端點。一個對話平台可以設定多個 Webhook，各自決定要推送哪個方向的訊息、用什麼格式。

設定位置：<mark style="color:blue;">設定</mark> → <mark style="color:blue;">對話平台</mark> → 選擇平台 → <mark style="color:blue;">Webhooks</mark> 分頁 → <mark style="color:blue;">新增 Webhook</mark>。

{% hint style="info" %}
透過 [建立對話與訊息](/tech/api-integration/dui-hua-yu-xun-xi.md) API 送出訊息時，回應只代表訊息已建立；**AI 助理的回覆是非同步產生的，會以 Outgoing Webhook 推送給您**。這是 API 串接取得回覆的標準方式。
{% endhint %}

## 運作方式 <a href="#how-it-works" id="how-it-works"></a>

```mermaid
sequenceDiagram
    participant C as 您的系統
    participant M as MaiAgent
    participant AI as AI 助理

    C->>M: POST /api/v1/messages/（訪客訊息）
    M-->>C: 201 已建立（不含回覆）
    M-)C: Incoming Webhook（訪客訊息）
    M->>AI: 產生回覆
    AI-->>M: 回覆訊息建立
    M-)C: Outgoing Webhook（AI 回覆）
```

真人客服在後台回覆時，該則回覆同樣是一則 Outgoing 訊息，也會推送到 Outgoing Webhook；payload 的 `sender.type` 可分辨是 AI 還是真人。

## Webhook 類型 <a href="#directions" id="directions"></a>

| 類型           | 觸發時機                               | 典型用途                                             |
| ------------ | ---------------------------------- | ------------------------------------------------ |
| **Outgoing** | AI 助理或真人客服的回覆建立時                   | 取得 AI 回覆、把回覆轉發到您自己的前台或通訊軟體                       |
| **Incoming** | 訪客訊息建立時（含 API、Web Chat、LINE 等所有通道） | 同步對話紀錄到客服系統、資料倉儲、稽核                              |
| **Receive**  | 由外部平台呼叫 MaiAgent                   | 接收外部客服平台送回的訊息（目前支援 Genesys Cloud Open Messaging） |

本頁說明 Outgoing 與 Incoming。

## 設定欄位 <a href="#fields" id="fields"></a>

| 欄位                                            | 說明                                                   |
| --------------------------------------------- | ---------------------------------------------------- |
| <mark style="color:blue;">名稱</mark>           | 自訂識別名稱                                               |
| <mark style="color:blue;">類型</mark>           | Outgoing／Incoming／Receive                            |
| <mark style="color:blue;">端點 URL</mark>       | 接收推送的網址                                              |
| <mark style="color:blue;">HTTP Method</mark>  | `POST`（預設）／`PUT`／`PATCH`                             |
| <mark style="color:blue;">Headers</mark>      | 附加在每次請求的自訂標頭（例如您系統的 API 金鑰）                          |
| <mark style="color:blue;">Payload 格式</mark>   | **MaiAgent 標準格式**／**Genesys Cloud**／**自訂範本**（Jinja2） |
| <mark style="color:blue;">Secret Token</mark> | 設定後，每次請求會帶 `X-Webhook-Secret: <token>` 標頭，供您的端點驗證來源  |
| <mark style="color:blue;">啟用狀態</mark>         | 關閉時不推送，設定保留                                          |

## MaiAgent 標準格式 <a href="#standard-payload" id="standard-payload"></a>

`Content-Type: application/json`，內容如下（Outgoing 與 Incoming 結構相同，以 `type` 區分方向）：

```json
{
  "id": "2491074a-6d23-4289-af45-caa12531420e",
  "type": "outgoing",
  "content": "您好，請問需要什麼協助？",
  "created_at": "2026-09-09T10:15:30.123456+00:00",
  "conversation": {
    "id": "8e44604a-8278-4c96-96b5-3e5a0548d738",
    "title": "詢問退貨流程",
    "type": "individual",
    "status": "open",
    "progress_status": "ai_processing",
    "auto_reply_enabled": true,
    "assignee": null
  },
  "inbox": {
    "id": "1f9c1c1e-4d1a-4b1e-9d0e-7b2f4a5c6d7e",
    "name": "官網客服",
    "channel_type": "web"
  },
  "contact": {
    "id": "c0ffee00-1111-2222-3333-444455556666",
    "name": "王小明",
    "email": null,
    "phone_number": null
  },
  "sender": {
    "id": "5c1d3e2a-0000-4b1e-9d0e-7b2f4a5c6d7e",
    "name": "AI 智能客服",
    "type": "chatbot"
  },
  "attachments": [
    {
      "id": "a1b2c3d4-0000-4b1e-9d0e-7b2f4a5c6d7e",
      "type": "image",
      "filename": "photo.jpg",
      "source_url": "https://example.com/photo.jpg"
    }
  ],
  "metadata": {}
}
```

### 欄位說明 <a href="#standard-fields" id="standard-fields"></a>

| 欄位                                | 類型             | 說明                                                                                                                  |
| --------------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------- |
| `id`                              | string         | 訊息 ID（UUID）                                                                                                         |
| `type`                            | string         | `incoming`（訪客訊息）／`outgoing`（AI 或真人回覆）                                                                               |
| `content`                         | string         | 訊息文字                                                                                                                |
| `created_at`                      | string         | ISO 8601 時間                                                                                                         |
| `conversation.id`                 | string         | 對話 ID                                                                                                               |
| `conversation.title`              | string         | 對話標題                                                                                                                |
| `conversation.type`               | string         | `individual`／`group`                                                                                                |
| `conversation.status`             | string         | `open`／`queued`（排隊等候真人）／`resolved`                                                                                  |
| `conversation.progress_status`    | string         | 目前由誰處理：`ai_processing`／`waiting_for_human`／`human_serving`／`resolved`／`open`                                        |
| `conversation.auto_reply_enabled` | boolean        | `false` 表示 AI 已停止自動回覆（轉真人中）                                                                                         |
| `conversation.assignee`           | object \| null | 接手的客服成員 `{ id, name }`；未指派為 `null`                                                                                  |
| `inbox.id` / `inbox.name`         | string         | 對話平台 ID 與名稱                                                                                                         |
| `inbox.channel_type`              | string         | `web`／`line`／`messenger`／`instagram`／`telegram`／`teams`／`email`／`whatsapp`／`slack`／`team_plus`／`line_works`／`viber` |
| `contact`                         | object \| null | 訪客（聯絡人）`{ id, name, email, phone_number }`                                                                          |
| `sender.type`                     | string         | `chatbot`（AI 助理）／`user`（真人客服）／`contact`（訪客）                                                                         |
| `attachments[]`                   | array          | 附件 `{ id, type, filename, source_url }`；`type` 為 `image`／`video`／`audio`／`sticker`／`other`                          |
| `metadata`                        | object         | 訊息附加資料                                                                                                              |

{% hint style="warning" %}
`attachments[].source_url` 是附件的**來源網址**（外部平台帶入的原始連結）。由 MaiAgent 儲存的檔案（例如 API 上傳、AI 產生的檔案）此欄可能為空；若您需要可下載的網址，請改用自訂範本並取 `attachment.file.url`（見下方範例），或以訊息 ID 呼叫訊息 API 取得附件。
{% endhint %}

## 自訂範本（Jinja2） <a href="#custom-template" id="custom-template"></a>

當您的系統要求特定 JSON 結構時，選擇 <mark style="color:blue;">自訂範本</mark>，以 Jinja2 語法撰寫 payload。範本渲染結果必須是合法 JSON；儲存時會以測試資料驗證一次。

### 可用變數 <a href="#template-variables" id="template-variables"></a>

| 變數             | 內容                                                                                                                               |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `message`      | `id`、`type`、`content`、`created_at`（datetime）、`metadata`                                                                          |
| `conversation` | `id`、`title`、`type`、`status`、`progress_status`、`auto_reply_enabled`、`assignee`（可為 `None`；有值時 `assignee.id`、`assignee.user.name`） |
| `inbox`        | `id`、`name`、`channel_type`                                                                                                       |
| `contact`      | `id`、`name`、`email`、`phone_number`、`source_id`（您以身份同步 API 帶入的 `sourceId`）；可為 `None`                                              |
| `sender`       | `id`、`name`；`sender_type` 為 `chatbot`／`user`／`contact`                                                                           |
| `attachments`  | 附件列表，每筆有 `id`、`type`、`filename`、`source_url`、`file`（`file.url` 為可下載網址）                                                           |
| `now`          | 渲染當下時間（datetime）                                                                                                                 |

字串請一律經過 `| tojson` 過濾器輸出，才會正確跳脫引號與換行。

### 範例：回傳您系統的使用者 ID 與可下載附件網址 <a href="#template-example" id="template-example"></a>

```jinja
{
  "external_user_id": {{ (contact.source_id if contact else "") | tojson }},
  "conversation_id": "{{ conversation.id }}",
  "direction": "{{ message.type }}",
  "from_human_agent": {{ (sender_type == "user") | tojson }},
  "text": {{ message.content | tojson }},
  "attachments": [{% for a in attachments %}{
    "type": "{{ a.type }}",
    "url": {{ (a.file.url if a.file else a.source_url) | tojson }}
  }{% if not loop.last %},{% endif %}{% endfor %}],
  "sent_at": "{{ message.created_at.isoformat() }}"
}
```

## 傳送行為 <a href="#delivery" id="delivery"></a>

* 每則訊息、每個啟用中的 Webhook 各推送一次；請求逾時 **30 秒**。
* 回應 **2xx** 視為成功；非 2xx 或逾時會記錄為失敗，**不會自動重試**。若您的系統需要可靠交付，請在端點內先落地再回應 2xx，並利用訊息 `id` 去重。
* 端點 URL 會經過 SSRF 防護：私有網段、內網位址的目的地會被拒絕。
* 每次推送的請求內容、回應與狀態碼可在 AI 助理頁面的 <mark style="color:blue;">Webhook</mark> 分頁檢視，用於排查。

## 以 API 管理 Webhook <a href="#manage-by-api" id="manage-by-api"></a>

除了後台介面，也可以用 API 建立與維護 Webhook（欄位對應後台設定）。認證方式見 [快速上手](/tech/api-integration/quickstart.md)。

```bash
# 列出 / 新增
GET  https://api.maiagent.ai/api/v1/inboxes/{inboxId}/webhooks/
POST https://api.maiagent.ai/api/v1/inboxes/{inboxId}/webhooks/

# 修改 / 刪除
PATCH  https://api.maiagent.ai/api/v1/inboxes/{inboxId}/webhooks/{webhookId}/
DELETE https://api.maiagent.ai/api/v1/inboxes/{inboxId}/webhooks/{webhookId}/
```

```json
{
  "name": "回覆同步到客服系統",
  "direction": "outgoing",
  "isEnabled": true,
  "url": "https://your-system.example.com/maiagent/reply",
  "method": "POST",
  "headers": { "X-Api-Key": "your-key" },
  "templatePreset": "maiagent_standard",
  "customTemplate": null,
  "secretToken": "shared-secret"
}
```

`inboxId` 可從 [建立對話](/tech/api-integration/dui-hua-yu-xun-xi.md) 回應的 `inbox.id` 取得，或於後台對話平台設定頁查看。

## 與「轉真人 Webhook」的差別 <a href="#vs-handoff-webhook" id="vs-handoff-webhook"></a>

本頁的 Webhook 以**訊息**為單位推送。若您的系統需要知道對話**何時轉給真人、何時回到 AI**（例如由您的客服系統接手服務），請使用另一組以對話生命週期為單位的轉真人 Webhook，見 [第三方客服系統串接（含轉真人）](/tech/api-integration/customer-service-system-integration.md)。

{% hint style="warning" %}
**發布狀態：待正式上線。** 上述連結描述新版四事件轉真人契約與 `id`／`occurred_at` 巢狀 payload，目前尚未在正式環境發布。請勿依連結中的新契約啟用正式串接；請先向 MaiAgent 團隊確認您的環境已完成更新。此發布狀態僅適用於連結中的新版轉真人契約；本頁介紹的訊息 Webhook 可正常使用。
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.maiagent.ai/tech/api-integration/webhook.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
