> 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/authorization-integration/contact-credentials-sync.md).

# 聯絡人身份同步與 Token 更新

企業系統將 Web Chat（含 [MaiGPT 模式](/tech/api-integration/web-chat-sdk/web-chat-maigpt-mode.md)）嵌入自家產品後，需要讓 AI 知道「誰在問」：AI 才能回溯該使用者的對話歷史，並在呼叫 MCP 工具時以**該使用者的權限**存取企業系統的 API。

`setup-contact-credentials` 這支 API 用一次呼叫完成兩件事：

1. **建立或更新**「企業系統帳號 ↔ MaiAgent 聯絡人（Contact）」的對應關係
2. 將該使用者的 Access Token 寫入**聯絡人 MCP 憑證**，讓 AI 助理能以他的身份呼叫工具

{% hint style="info" %}
聯絡人（Contact）的概念與整體串接流程請先參考[聯絡人 (Contact) 介紹及串接](/tech/authorization-integration/contacts.md)。若您不使用 MCP 工具、只需要建立聯絡人對應，也可以走該頁的 `POST /api/v1/contacts/` 流程；本頁的 API 適合「登入時要同步更新 Token」的場景。
{% endhint %}

### 前端 auth 與後端串接怎麼選 <a href="#frontend-vs-backend" id="frontend-vs-backend"></a>

這支 API 也有前端版：embed SDK 的 `auth` 設定（見 [Web Chat 嵌入與 SDK](/tech/api-integration/web-chat-sdk.md#identify-users)）底層就是由聊天視窗自動呼叫同一支 API。兩條路建立的是同一套聯絡人（`sourceId` 相同即同一人），差別只在誰來呼叫：

|           | 前端 auth（SDK 自動）                               | 後端串接（本頁）                       |
| --------- | --------------------------------------------- | ------------------------------ |
| 呼叫者       | 使用者的瀏覽器                                       | 您的後端伺服器                        |
| 整合成本      | 低：config 加一個 `auth` 物件                        | 中：登入流程加一次 API 呼叫＋存 `contactId` |
| Token 保密性 | `mcpCredentials` 會出現在前端頁面，使用者可在原始碼看到自己的 token | Token 不經過前端                    |
| 適合        | 只需識別使用者、保留跨裝置對話                               | 要綁 MCP 憑證讓 AI 以使用者權限呼叫 API     |

## 一、呼叫時機 <a href="#when-to-call" id="when-to-call"></a>

| 情境                | 做法                                                                               |
| ----------------- | -------------------------------------------------------------------------------- |
| **新增使用者**         | 建立帳號流程中呼叫本 API，取得 `contactId` 存入會員資料表                                            |
| **每次登入**          | 登入成功、產生 Access Token 後、回傳給前端之前呼叫本 API，帶入**新的 Token**（同一 `sourceId` 會自動更新，不會重複建立） |
| **既有系統補建（回填）**    | 對既有使用者逐筆呼叫本 API 補建聯絡人，見[既有使用者批次補建](#backfill)                                    |
| **Token 過期 / 刷新** | 再次呼叫本 API 帶入新 Token 即可                                                           |
| **登出**            | 前端呼叫 SDK `signOut()` 回到匿名；後端刪除該聯絡人的工具憑證，見[登出與憑證註銷](#logout-revoke)               |

## 二、API 規格 <a href="#api-spec" id="api-spec"></a>

| 項目           | 值                                                                                 |
| ------------ | --------------------------------------------------------------------------------- |
| Method       | `POST`                                                                            |
| URL          | `https://api.maiagent.ai/api/v1/web-chats/{webChatId}/setup-contact-credentials/` |
| 認證           | 無需 API Key（公開端點，僅需知道 WebChat ID）                                                  |
| Content-Type | `application/json`                                                                |
| 速率限制         | 每 IP 每分鐘 30 次                                                                     |

{% hint style="info" %}
URL 以 SaaS 環境（`api.maiagent.ai`）為例；私有雲 / 地端部署請換成您環境的 API 網域。
{% endhint %}

### Request Body <a href="#request-body" id="request-body"></a>

```json
{
  "sourceId": "user-12345",
  "name": "王小明",
  "mcpCredentials": {
    "toolId": "your-mcp-tool-id",
    "headers": {
      "Authorization": "Bearer <<使用者的 Access Token>>"
    }
  }
}
```

| 欄位                       | 必填 | 說明                                                                                                                                |
| ------------------------ | -- | --------------------------------------------------------------------------------------------------------------------------------- |
| `sourceId`               | ✅  | 企業系統中使用者的唯一識別碼。**同一個 `sourceId` 重複呼叫會更新而非重複建立。** 請使用不可猜測的值（如 UUID），見下方安全提醒                                                        |
| `name`                   |    | 使用者顯示名稱，會顯示在 MaiAgent 後台的聯絡人列表；不帶時預設為 `Anonymous`。**只在首次建立聯絡人時生效**，後續更新姓名請用[同步聯絡人資料](#sync-contact-profile)                       |
| `mcpCredentials.toolId`  |    | 要綁定憑證的 **MCP 工具** ID（不使用 MCP 工具時整個 `mcpCredentials` 可省略）。只接受 MCP 類型的工具，帶 API 工具 ID 會回 400；API 工具憑證見[工具憑證的兩種類型](#credential-types) |
| `mcpCredentials.headers` |    | 要帶給 MCP Server 的 HTTP headers，讓 AI 以該使用者身份呼叫工具                                                                                    |
| `embedOrigin`            |    | 嵌入頁面的 Origin。WebChat 有設定「允許嵌入網域」時，**伺服器對伺服器**的呼叫（沒有瀏覽器 Origin header）需帶此欄位通過驗證                                                    |

### Response（200 OK） <a href="#response" id="response"></a>

```json
{
  "contactId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
```

回傳的 `contactId` 需要**儲存在企業系統的會員資料中**，前端初始化 Web Chat 時帶入。

{% hint style="danger" %}
**`sourceId` 與 `contactId` 都應視為身份憑證**：本 API 是公開端點，知道 `webChatId` 與某人的 `sourceId` 就能取得他的 `contactId`；而拿到 `contactId` 就能以該使用者身份對話、看到他的對話歷史。因此：

* `sourceId` 使用**不可猜測、不可枚舉**的值（如 UUID），不要用流水號、Email 或手機號碼
* `contactId` 只在**登入後**的頁面輸出給該使用者本人，不放進公開頁面原始碼
* 為 Web Chat 設定**允許嵌入網域**清單（提供網域清單給 MaiAgent 對接窗口），縮小可呼叫本 API 的來源（見 [Web Chat 嵌入與 SDK](/tech/api-integration/web-chat-sdk.md#embed-origin-allowlist)）
  {% endhint %}

### curl 範例 <a href="#curl-example" id="curl-example"></a>

```bash
curl -X POST \
  'https://api.maiagent.ai/api/v1/web-chats/{webChatId}/setup-contact-credentials/' \
  -H 'Content-Type: application/json' \
  -d '{
    "sourceId": "user-12345",
    "name": "王小明",
    "mcpCredentials": {
      "toolId": "your-mcp-tool-id",
      "headers": {
        "Authorization": "Bearer eyJhbGciOiJIUzI1NiIs..."
      }
    }
  }'
```

## 三、登入流程整合位置 <a href="#login-flow" id="login-flow"></a>

### 首次登入 <a href="#first-login" id="first-login"></a>

```mermaid
sequenceDiagram
    actor U as 使用者
    participant FE as 企業系統前端
    participant BE as 企業系統後端
    participant MA as MaiAgent

    U->>FE: 登入
    FE->>BE: 帳號密碼
    BE->>BE: 驗證成功，產生 Access Token
    rect rgb(230, 242, 255)
        Note over BE,MA: 新增的整合步驟
        BE->>MA: POST setup-contact-credentials<br/>（sourceId＋name＋mcpCredentials）
        MA-->>BE: contactId
        BE->>BE: contactId 存入會員資料表
    end
    BE-->>FE: 登入結果（含 contactId）
    FE->>MA: 載入 Web Chat（config 帶 contactId）
    MA-->>U: AI 助理以使用者身份服務
```

### 後續登入／Token 刷新 <a href="#subsequent-login" id="subsequent-login"></a>

```mermaid
sequenceDiagram
    actor U as 使用者
    participant BE as 企業系統後端
    participant MA as MaiAgent

    U->>BE: 登入
    BE->>BE: 產生新的 Access Token
    BE->>MA: POST setup-contact-credentials<br/>（同 sourceId＋新 Token）
    Note over MA: 辨識為同一聯絡人<br/>僅更新憑證，不重複建立
    MA-->>BE: contactId（同一值）
    BE-->>U: 登入結果（沿用既有 contactId）
```

會員資料表建議新增一個欄位：

| 欄位名稱                  | 型別                          | 說明                          |
| --------------------- | --------------------------- | --------------------------- |
| `maiagent_contact_id` | UUID / VARCHAR(36)，nullable | 對應的 MaiAgent 聯絡人 ID，首次呼叫後儲存 |

{% hint style="success" %}
**Token 過期處理：** 當 Token 過期或刷新時，只需再次呼叫同一支 API、帶入新的 Token。同一個 `sourceId` 會自動更新既有聯絡人的憑證，不會重複建立。
{% endhint %}

{% hint style="warning" %}
**失敗不應阻擋登入：** 本 API 呼叫失敗時，不應阻擋使用者登入企業系統。建議設為非同步呼叫，失敗時記錄 log 並在下次登入時重試。
{% endhint %}

## 四、既有使用者批次補建 <a href="#backfill" id="backfill"></a>

{% hint style="success" %}
**大量補建建議改用批次匯入**：後台與 API 都支援以 Excel 一次匯入（上限 10,000 列），可同時帶入 query\_metadata 與 API 工具憑證，見[聯絡人批次匯入](/tech/authorization-integration/contacts.md#bulk-import)。以下逐筆呼叫的方式適合順著登入流程漸進補建。
{% endhint %}

既有系統首次串接時，可對現有使用者逐筆呼叫本 API 補建聯絡人對應：

```mermaid
flowchart TD
    A[撈出既有使用者清單] --> B["POST setup-contact-credentials<br/>（sourceId＋name，暫不帶 mcpCredentials）"]
    B --> C[contactId 寫回會員資料表]
    C --> D{還有下一筆？}
    D -->|有| E["控制節奏<br/>（每 IP 每分鐘 30 次）"]
    E --> B
    D -->|無| F[補建完成]
    F -.-> G["各使用者下次登入時<br/>由登入流程補上 Token 憑證"]
```

* 逐筆帶入各使用者的 `sourceId` 與 `name`，把回傳的 `contactId` 寫回會員資料表
* `sourceId` 是冪等的：補建腳本可以安全重跑，不會產生重複聯絡人
* 補建當下若拿不到使用者的 Access Token，可先不帶 `mcpCredentials`，待該使用者下次登入時再由登入流程補上
* 注意速率限制（每 IP 每分鐘 30 次），大量補建請控制節奏

## 五、同步聯絡人資料（選用） <a href="#sync-contact-profile" id="sync-contact-profile"></a>

若要將使用者的部門、角色、服務等級等資訊同步給 MaiAgent（AI 助理會自動讀取這些資訊、提供個人化回應），請使用聯絡人 API：

| 項目           | 值                                                      |
| ------------ | ------------------------------------------------------ |
| Method       | `PATCH`                                                |
| URL          | `https://api.maiagent.ai/api/v1/contacts/{contactId}/` |
| 認證           | `Authorization: Api-Key <<您的 API Key>>`                |
| Content-Type | `application/json`                                     |

```json
{
  "name": "王小明",
  "email": "xiaoming.wang@example.com",
  "metadata": [
    {"key": "部門", "value": "技術支援部"},
    {"key": "角色", "value": "資深工程師"},
    {"key": "服務等級", "value": "Premium"}
  ]
}
```

* 所有欄位皆為選填，PATCH 只更新有傳入的欄位，未傳入的不會被清空
* `metadata` 欄位本身是**全量替換**：傳入的陣列會完整覆蓋舊的，請帶入完整的 metadata 陣列
* 可以每次登入時呼叫（確保資料最新），也可以只在使用者修改個人資料時呼叫

<details>

<summary>為什麼身份同步免認證、資料同步要 API Key？</summary>

`setup-contact-credentials` 是公開端點，它只回傳一個 UUID；即使被惡意呼叫，最多只會寫入錯誤的憑證——企業系統本身的驗證機制會擋下無效的 Token。

但聯絡人資料（姓名、部門、屬性）會被 AI 讀取並帶入回答。如果放在公開端點，惡意者可以把姓名改成任意內容、直接送進 LLM。因此聯絡人資料更新需要 **API Key 認證**，確保只有授權的後端才能修改。

</details>

## 六、登出與憑證註銷 <a href="#logout-revoke" id="logout-revoke"></a>

登出時有前端、後端兩件事，作用範圍不同：

|      | 前端 `MaiAgent.auth.signOut()`                                            | 後端刪除工具憑證（本節）                    |
| ---- | ----------------------------------------------------------------------- | ------------------------------- |
| 作用   | 聊天視窗回到匿名狀態、清除 `contextData`                                             | 從 MaiAgent 移除該聯絡人的 MCP／API 工具憑證 |
| 工具憑證 | **不會**動到已寫入的憑證                                                          | 憑證即刻刪除，AI 無法再以該使用者身份呼叫工具        |
| 呼叫時機 | 使用者在頁面上登出時（見 [SDK API](/tech/api-integration/web-chat-sdk.md#api-auth)） | 登出流程中由您的後端呼叫                    |

若您的系統登出時已在自家認證伺服器註銷該 Access Token，MaiAgent 儲存的憑證即已失效；後端刪除憑證屬於縱深防禦，建議一併執行，避免失效 Token 殘留在系統中。

```mermaid
sequenceDiagram
    actor U as 使用者
    participant FE as 企業系統前端
    participant BE as 企業系統後端
    participant MA as MaiAgent

    U->>FE: 登出
    FE->>MA: MaiAgent.auth.signOut()
    Note over FE,MA: 聊天視窗回到匿名狀態
    FE->>BE: 登出請求
    BE->>BE: 註銷自家 Access Token
    BE->>MA: DELETE 該聯絡人的 mcp-credentials／api-credentials
    MA-->>BE: 204 No Content
    Note over MA: 憑證移除；聯絡人與對話歷史保留<br/>下次登入由身份同步 API 重建
```

### 刪除憑證 API <a href="#delete-credentials" id="delete-credentials"></a>

| 憑證類型   | Method / URL                                                          |
| ------ | --------------------------------------------------------------------- |
| MCP 工具 | `DELETE /api/v1/contacts/{contactId}/mcp-credentials/{credentialId}/` |
| API 工具 | `DELETE /api/v1/contacts/{contactId}/api-credentials/{credentialId}/` |

認證方式為 `Authorization: Api-Key <<您的 API Key>>`（與聯絡人 API 相同），成功回 `204 No Content`：

```bash
curl -X DELETE \
  'https://api.maiagent.ai/api/v1/contacts/{contactId}/mcp-credentials/{credentialId}/' \
  -H 'Authorization: Api-Key <<您的 API Key>>'
```

刪除後聯絡人本身、對話歷史與自訂屬性都保留；使用者下次登入時，登入流程呼叫 `setup-contact-credentials` 即會重建憑證（同一組聯絡人與工具為更新／重建，不會重複）。

### 取得 credentialId <a href="#get-credential-id" id="get-credential-id"></a>

`setup-contact-credentials` 只回傳 `contactId`，不包含憑證 ID。取得 `credentialId` 的方式：

* `GET /api/v1/contacts/{contactId}/`（`Api-Key` 認證）回應中的 `mcpCredentials` 與 `apiCredentials` 陣列，每筆含 `id` 與 `tool` 資訊，依 `tool.id` 找到目標憑證的 `id`
* 透過[聯絡人 API 建立憑證](#credential-types)時，回應是完整的聯絡人物件，可在建立當下就把憑證 `id` 存起來

回應中的憑證 `headers` 依呼叫者身份可能以遮罩形式顯示；註銷流程只需要 `id`，不受影響。

## 七、工具憑證的兩種類型 <a href="#credential-types" id="credential-types"></a>

聯絡人可以綁定兩種工具的專屬憑證，設定入口不同：

|         | MCP 工具憑證                                                                                | API 工具憑證                                                                                       |
| ------- | --------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| 用途      | AI 以使用者身份呼叫 MCP Server                                                                  | AI 以使用者身份呼叫 API 工具                                                                             |
| 登入時同步   | ✅ 本頁的 `setup-contact-credentials`（免 API Key）                                            | ✖ 不支援（帶 API 工具 ID 會 400）                                                                       |
| 聯絡人 API | `POST /api/v1/contacts/{contactId}/mcp-credentials/`                                    | `POST /api/v1/contacts/{contactId}/api-credentials/`                                           |
| 單筆更新／刪除 | `PATCH`／`DELETE /api/v1/contacts/{contactId}/mcp-credentials/{credentialId}/`           | `PATCH`／`DELETE /api/v1/contacts/{contactId}/api-credentials/{credentialId}/`                  |
| 批次匯入    | ✖                                                                                       | ✅ Excel 的 `API Credentials` 欄，見[批次匯入](/tech/authorization-integration/contacts.md#bulk-import) |
| 後台 UI   | 聯絡人編輯 → MCP 憑證（見[使用者手冊](https://docs.maiagent.ai/tools/setup-contacts-mcp-credentials)） | —                                                                                              |

聯絡人 API 的兩個憑證端點都需要 `Api-Key` 認證，body 格式相同：

```json
{
  "tool": "<<工具 ID>>",
  "headers": { "Authorization": "Bearer <<使用者的 Token>>" }
}
```

同一組（聯絡人、工具）重複呼叫為更新，不會重複建立。單筆更新／刪除端點以 `credentialId` 指定目標憑證，取得方式見[取得 credentialId](#get-credential-id)。

## 八、錯誤處理 <a href="#error-handling" id="error-handling"></a>

| HTTP 狀態碼 | 可能原因                                                     | 建議處理                         |
| -------- | -------------------------------------------------------- | ---------------------------- |
| `400`    | 必填欄位缺失（如 `sourceId`）；Origin 不在允許嵌入網域清單內；`toolId` 不存在或不可用 | 檢查 request body 與 WebChat 設定 |
| `404`    | WebChat ID 不存在                                           | 確認 `webChatId` 正確            |
| `429`    | 超過速率限制（每 IP 每分鐘 30 次）                                    | 降低呼叫頻率後重試                    |
| `500`    | 伺服器異常                                                    | 稍後重試，若持續發生請聯繫 MaiAgent 團隊    |

## 九、常見問題 <a href="#faq" id="faq"></a>

<details>

<summary>同一個使用者重複呼叫會建立多個聯絡人嗎？</summary>

不會。只要 `sourceId` 相同，MaiAgent 會辨識為同一個聯絡人，僅更新憑證。

</details>

<details>

<summary>contactId 需要每次登入都重新取得嗎？</summary>

`contactId` 建立後不會變，可以持久儲存在會員資料表中。但每次登入仍建議呼叫本 API，以更新 Token 憑證。

</details>

<details>

<summary>前端不帶 contactId 會怎樣？</summary>

Web Chat 仍可運作，但 AI 助理無法辨識使用者身份、無法以個人權限呼叫工具，對話歷史也只能以瀏覽器為單位保留（匿名）。

</details>

<details>

<summary>登出後聯絡人與對話歷史會被刪除嗎？</summary>

不會。[登出時刪除憑證](#logout-revoke)只移除工具憑證；聯絡人本身、對話歷史與自訂屬性都保留，下次登入呼叫本 API 即恢復完整功能。

</details>

<details>

<summary>聯絡人的自訂屬性（metadata）跟 MCP 憑證有什麼差別？</summary>

MCP 憑證是「工具的金鑰」——讓 AI 能以使用者身份存取企業系統的 API。自訂屬性是「使用者的背景資料」——讓 AI 知道誰在問、提供更個人化的回答。兩者透過不同的 API 設定，互不影響。

</details>


---

# 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/authorization-integration/contact-credentials-sync.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.
