> 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/api/api-reference/lian-luo-ren.md).

# 聯絡人

### 列出聯絡人 <a href="#undefined" id="undefined"></a>

GET `/api/v1/contacts/`

#### 參數

| 參數名稱       | 必填 | 類型      | 說明                                             |
| ---------- | -- | ------- | ---------------------------------------------- |
| `channels` | ❌  | array   | Multiple values may be separated by commas.    |
| `inbox`    | ❌  | string  | Deprecated: Use inboxes instead                |
| `inboxes`  | ❌  | string  | 對話平台 ID (用於過濾特定 inbox 的聯絡人)                    |
| `page`     | ❌  | integer | A page number within the paginated result set. |
| `pageSize` | ❌  | integer | Number of results to return per page.          |
| `query`    | ❌  | string  | 姓名或來源ID搜尋                                      |
| `search`   | ❌  | string  | 全文搜尋                                           |
| `tags`     | ❌  | array   | Multiple values may be separated by commas.    |

#### 程式碼範例

{% tabs %}
{% tab title="Shell/Bash" %}

```bash
# 呼叫 API 示例 (Shell)
curl -X GET "https://api.maiagent.ai/api/v1/contacts/?channels=example&inbox=550e8400-e29b-41d4-a716-446655440000&inboxes=example&page=1&pageSize=1&query=example&search=example&tags=example" \
  -H "Authorization: Api-Key YOUR_API_KEY"

# 請確認在執行前替換 YOUR_API_KEY 並核對請求資料。
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const axios = require('axios');

// 設定請求標頭
const config = {
  headers: {
    'Authorization': 'Api-Key YOUR_API_KEY'
  }
};

axios.get("https://api.maiagent.ai/api/v1/contacts/?channels=example&inbox=550e8400-e29b-41d4-a716-446655440000&inboxes=example&page=1&pageSize=1&query=example&search=example&tags=example", config)
  .then(response => {
    console.log('成功取得回應:');
    console.log(response.data);
  })
  .catch(error => {
    console.error('請求發生錯誤:');
    console.error(error.response?.data || error.message);
  });
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

url = "https://api.maiagent.ai/api/v1/contacts/?channels=example&inbox=550e8400-e29b-41d4-a716-446655440000&inboxes=example&page=1&pageSize=1&query=example&search=example&tags=example"
headers = {
    "Authorization": "Api-Key YOUR_API_KEY"
}


response = requests.get(url, headers=headers)
try:
    print("成功取得回應:")
    print(response.json())
except Exception as e:
    print("請求發生錯誤:", e)
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();

try {
    $response = $client->get("https://api.maiagent.ai/api/v1/contacts/?channels=example&inbox=550e8400-e29b-41d4-a716-446655440000&inboxes=example&page=1&pageSize=1&query=example&search=example&tags=example", [
        'headers' => [
            'Authorization' => 'Api-Key YOUR_API_KEY'
        ]
    ]);
    
    $data = json_decode($response->getBody(), true);
    echo "成功取得回應:\n";
    print_r($data);
} catch (Exception $e) {
    echo '請求發生錯誤: ' . $e->getMessage();
}
?>
```

{% endtab %}
{% endtabs %}

#### 回應內容

**狀態碼: 200**

**回應結構範例**

```typescript
{
  "count": integer
  "next"?: string (uri) // 非必填
  "previous"?: string (uri) // 非必填
  "results": [
    {
      "id": string (uuid)
      "inboxes"?: [ // 非必填
        {
          "id": string (uuid)
          "name": string
        }
      ]
      "inbox"?:  // 向前相容欄位：單一 inbox，若同時提供 inboxes 則忽略此欄位 (非必填)
      {
        "id": string (uuid)
        "name": string
      }
      "name": string
      "avatar"?: // 可能有不同的類型 (非必填)
      string (uri) // 聯絡人頭像 URL，支援完整 URL 或相對路徑 (非必填)
      "phoneNumber"?: string // 非必填
      "email"?: // 可能有不同的類型 (非必填)
      string (email) // 非必填
      "sourceId"?: string // 非必填
      "queryMetadata"?: { // 查詢元資料，控制可查詢的知識範圍；詳見各端點說明 (非必填)
      {
        "knowledgeBases"?: [ // 可查詢的知識庫清單；空陣列或 null＝全部不可查（無權限），未提供＝不限制 (非必填)
          {
            "knowledgeBaseId": string (uuid) // 知識庫 ID
            "chatbotFileIds"?: [ // 檔案 ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
              string (uuid)
            ]
            "knowledgeBaseFileIds"?: [ // 檔案 ID 清單（chatbotFileIds 的新名稱；兩者皆提供時以本欄位為準） (非必填)
              string (uuid)
            ]
            "faqIds"?: [ // FAQ ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
              string (uuid)
            ]
            "hasUserSelectedAll"?: boolean // true＝選取知識庫全部內容並排除清單中的項目；false＝僅選取清單中的項目 (非必填)
          }
        ]
        "labelRelations"?: { // 標籤過濾條件；conditions 為空陣列＝不做標籤過濾（並非無權限）。必須與 knowledgeBases 一併提供——單獨提供時知識庫檢索不會套用標籤過濾（等同不限制） (非必填)
        {
          "operator": string (enum: AND, OR) // 標籤條件的組合方式
          "conditions"?: [ // 標籤條件清單，支援巢狀 operator/conditions 組合 (非必填)
            object
          ]
        }
        }
      }
      }
      "metadata"?: object // 自訂的客戶資訊，會顯示在對話頁的客戶資訊區塊 (非必填)
      "mcpCredentials": [ // 聯絡人的 MCP 認證憑證列表
        object
      ]
      "apiCredentials": [ // 聯絡人的 API 認證憑證列表
        object
      ]
      "contactConnectors": [ // 聯絡人的 Connector OAuth 授權列表（不含 token 本體）
        object
      ]
      "tags": [
        {
          "id": string (uuid)
          "name": string
          "createdAt": string (timestamp)
          "updatedAt": string (timestamp)
        }
      ]
      "preChatFieldIndex": object // 來自此 Contact 所屬 inboxes 的 pre-chat form 欄位設定，mapping {field_id: {label: {locale: text}}}，前端用來把 metadata 的 UUID key 解析成顯示名稱
      "createdAt": string (timestamp)
      "updatedAt": string (timestamp)
    }
  ]
}
```

**回應範例值**

```json
{
  "count": 123,
  "next": "http://api.example.org/accounts/?page=4",
  "previous": "http://api.example.org/accounts/?page=2",
  "results": [
    [
      {
        "id": "user1_uuid",
        "inboxes": [
          {
            "id": "inbox_uuid",
            "name": "inbox_name"
          }
        ],
        "name": "user1",
        "avatar": "",
        "sourceId": null,
        "queryMetadata": null,
        "createdAt": "1751875361000",
        "updatedAt": "1751875361000"
      },
      {
        "id": "user2_uuid",
        "inboxes": [
          {
            "id": "inbox_uuid",
            "name": "inbox_name"
          }
        ],
        "name": "user2",
        "avatar": "avatar_url",
        "sourceId": "self defined source id",
        "queryMetadata": {
          "knowledgeBases": [
            {
              "knowledgeBaseId": "5f8c6a99-5515-43aa-8e83-fdeea327a3a2",
              "hasUserSelectedAll": true
            }
          ],
          "labelRelations": {
            "operator": "OR",
            "conditions": [
              {
                "labelId": "957998f9-1824-4872-becd-b7f8a7962896"
              }
            ]
          }
        },
        "createdAt": "1751875400000",
        "updatedAt": "1751875400000"
      }
    ]
  ]
}
```

***

### 建立聯絡人 <a href="#undefined" id="undefined"></a>

POST `/api/v1/contacts/`

#### 程式碼範例

{% tabs %}
{% tab title="Shell/Bash" %}

```bash
# 呼叫 API 示例 (Shell)
curl -X POST "https://api.maiagent.ai/api/v1/contacts/" \
  -H "Authorization: Api-Key YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "inboxes": [
      {
        "id": "inbox_uuid"
      }
    ],
    "name": "user1",
    "avatar": "",
    "phoneNumber": 912345678,
    "email": "user1@example.com",
    "sourceId": "self defined source id",
    "queryMetadata": {
      "knowledgeBases": [
        {
          "knowledgeBaseId": "5f8c6a99-5515-43aa-8e83-fdeea327a3a2",
          "hasUserSelectedAll": true
        }
      ],
      "labelRelations": {
        "operator": "OR",
        "conditions": [
          {
            "labelId": "957998f9-1824-4872-becd-b7f8a7962896"
          }
        ]
      }
    },
    "metadata": [
      {
        "key": "客戶等級",
        "value": "VIP"
      },
      {
        "key": "偏好語言",
        "value": "繁體中文"
      }
    ]
  }'

# 請確認在執行前替換 YOUR_API_KEY 並核對請求資料。
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const axios = require('axios');

// 設定請求標頭
const config = {
  headers: {
    'Authorization': 'Api-Key YOUR_API_KEY',
    'Content-Type': 'application/json'
  }
};

// 請求內容 (payload)
const data = {
    "inboxes": [
      {
        "id": "inbox_uuid"
      }
    ],
    "name": "user1",
    "avatar": "",
    "phoneNumber": 912345678,
    "email": "user1@example.com",
    "sourceId": "self defined source id",
    "queryMetadata": {
      "knowledgeBases": [
        {
          "knowledgeBaseId": "5f8c6a99-5515-43aa-8e83-fdeea327a3a2",
          "hasUserSelectedAll": true
        }
      ],
      "labelRelations": {
        "operator": "OR",
        "conditions": [
          {
            "labelId": "957998f9-1824-4872-becd-b7f8a7962896"
          }
        ]
      }
    },
    "metadata": [
      {
        "key": "客戶等級",
        "value": "VIP"
      },
      {
        "key": "偏好語言",
        "value": "繁體中文"
      }
    ]
  };

axios.post("https://api.maiagent.ai/api/v1/contacts/", data, config)
  .then(response => {
    console.log('成功取得回應:');
    console.log(response.data);
  })
  .catch(error => {
    console.error('請求發生錯誤:');
    console.error(error.response?.data || error.message);
  });
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

url = "https://api.maiagent.ai/api/v1/contacts/"
headers = {
    "Authorization": "Api-Key YOUR_API_KEY",
    "Content-Type": "application/json"
}

# 請求內容 (payload)
data = {
      "inboxes": [
        {
          "id": "inbox_uuid"
        }
      ],
      "name": "user1",
      "avatar": "",
      "phoneNumber": 912345678,
      "email": "user1@example.com",
      "sourceId": "self defined source id",
      "queryMetadata": {
        "knowledgeBases": [
          {
            "knowledgeBaseId": "5f8c6a99-5515-43aa-8e83-fdeea327a3a2",
            "hasUserSelectedAll": true
          }
        ],
        "labelRelations": {
          "operator": "OR",
          "conditions": [
            {
              "labelId": "957998f9-1824-4872-becd-b7f8a7962896"
            }
          ]
        }
      },
      "metadata": [
        {
          "key": "客戶等級",
          "value": "VIP"
        },
        {
          "key": "偏好語言",
          "value": "繁體中文"
        }
      ]
    }

response = requests.post(url, json=data, headers=headers)
try:
    print("成功取得回應:")
    print(response.json())
except Exception as e:
    print("請求發生錯誤:", e)
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();

try {
    $response = $client->post("https://api.maiagent.ai/api/v1/contacts/", [
        'headers' => [
            'Authorization' => 'Api-Key YOUR_API_KEY',
            'Content-Type' => 'application/json'
        ],
        'json' => {
            "inboxes": [
                {
                    "id": "inbox_uuid"
                }
            ],
            "name": "user1",
            "avatar": "",
            "phoneNumber": 912345678,
            "email": "user1@example.com",
            "sourceId": "self defined source id",
            "queryMetadata": {
                "knowledgeBases": [
                    {
                        "knowledgeBaseId": "5f8c6a99-5515-43aa-8e83-fdeea327a3a2",
                        "hasUserSelectedAll": true
                    }
                ],
                "labelRelations": {
                    "operator": "OR",
                    "conditions": [
                        {
                            "labelId": "957998f9-1824-4872-becd-b7f8a7962896"
                        }
                    ]
                }
            },
            "metadata": [
                {
                    "key": "客戶等級",
                    "value": "VIP"
                },
                {
                    "key": "偏好語言",
                    "value": "繁體中文"
                }
            ]
        }
    ]);
    
    $data = json_decode($response->getBody(), true);
    echo "成功取得回應:\n";
    print_r($data);
} catch (Exception $e) {
    echo '請求發生錯誤: ' . $e->getMessage();
}
?>
```

{% endtab %}
{% endtabs %}

#### 回應內容

**狀態碼: 201**

**回應結構範例**

```typescript
{
  "id": string (uuid)
  "inboxes"?: [ // 非必填
    {
      "id": string (uuid)
      "name": string
    }
  ]
  "inbox"?:  // 向前相容欄位：單一 inbox，若同時提供 inboxes 則忽略此欄位 (非必填)
  {
    "id": string (uuid)
    "name": string
  }
  "name": string
  "avatar"?: // 可能有不同的類型 (非必填)
  string (uri) // 聯絡人頭像 URL，支援完整 URL 或相對路徑 (非必填)
  "phoneNumber"?: string // 非必填
  "email"?: // 可能有不同的類型 (非必填)
  string (email) // 非必填
  "sourceId"?: string // 非必填
  "queryMetadata"?: { // 查詢元資料，控制可查詢的知識範圍；詳見各端點說明 (非必填)
  {
    "knowledgeBases"?: [ // 可查詢的知識庫清單；空陣列或 null＝全部不可查（無權限），未提供＝不限制 (非必填)
      {
        "knowledgeBaseId": string (uuid) // 知識庫 ID
        "chatbotFileIds"?: [ // 檔案 ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
          string (uuid)
        ]
        "knowledgeBaseFileIds"?: [ // 檔案 ID 清單（chatbotFileIds 的新名稱；兩者皆提供時以本欄位為準） (非必填)
          string (uuid)
        ]
        "faqIds"?: [ // FAQ ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
          string (uuid)
        ]
        "hasUserSelectedAll"?: boolean // true＝選取知識庫全部內容並排除清單中的項目；false＝僅選取清單中的項目 (非必填)
      }
    ]
    "labelRelations"?: { // 標籤過濾條件；conditions 為空陣列＝不做標籤過濾（並非無權限）。必須與 knowledgeBases 一併提供——單獨提供時知識庫檢索不會套用標籤過濾（等同不限制） (非必填)
    {
      "operator": string (enum: AND, OR) // 標籤條件的組合方式
      "conditions"?: [ // 標籤條件清單，支援巢狀 operator/conditions 組合 (非必填)
        object
      ]
    }
    }
  }
  }
  "metadata"?: object // 自訂的客戶資訊，會顯示在對話頁的客戶資訊區塊 (非必填)
  "mcpCredentials": [ // 聯絡人的 MCP 認證憑證列表
    object
  ]
  "apiCredentials": [ // 聯絡人的 API 認證憑證列表
    object
  ]
  "contactConnectors": [ // 聯絡人的 Connector OAuth 授權列表（不含 token 本體）
    object
  ]
  "tags": [
    {
      "id": string (uuid)
      "name": string
      "createdAt": string (timestamp)
      "updatedAt": string (timestamp)
    }
  ]
  "preChatFieldIndex": object // 來自此 Contact 所屬 inboxes 的 pre-chat form 欄位設定，mapping {field_id: {label: {locale: text}}}，前端用來把 metadata 的 UUID key 解析成顯示名稱
  "createdAt": string (timestamp)
  "updatedAt": string (timestamp)
}
```

**回應範例值**

```json
{
  "id": "user1_uuid",
  "inboxes": [
    {
      "id": "inbox_uuid",
      "name": "inbox_name"
    }
  ],
  "name": "user1",
  "avatar": "",
  "phoneNumber": 912345678,
  "email": "user1@example.com",
  "sourceId": null,
  "queryMetadata": null,
  "createdAt": "1751875361000",
  "updatedAt": "1751875361000"
}
```

***

### 取得聯絡人詳情 <a href="#undefined" id="undefined"></a>

GET `/api/v1/contacts/{id}/`

#### 參數

| 參數名稱 | 必填 | 類型     | 說明                                      |
| ---- | -- | ------ | --------------------------------------- |
| `id` | ✅  | string | A UUID string identifying this Contact. |

#### 程式碼範例

{% tabs %}
{% tab title="Shell/Bash" %}

```bash
# 呼叫 API 示例 (Shell)
curl -X GET "https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/" \
  -H "Authorization: Api-Key YOUR_API_KEY"

# 請確認在執行前替換 YOUR_API_KEY 並核對請求資料。
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const axios = require('axios');

// 設定請求標頭
const config = {
  headers: {
    'Authorization': 'Api-Key YOUR_API_KEY'
  }
};

axios.get("https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/", config)
  .then(response => {
    console.log('成功取得回應:');
    console.log(response.data);
  })
  .catch(error => {
    console.error('請求發生錯誤:');
    console.error(error.response?.data || error.message);
  });
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

url = "https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/"
headers = {
    "Authorization": "Api-Key YOUR_API_KEY"
}


response = requests.get(url, headers=headers)
try:
    print("成功取得回應:")
    print(response.json())
except Exception as e:
    print("請求發生錯誤:", e)
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();

try {
    $response = $client->get("https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/", [
        'headers' => [
            'Authorization' => 'Api-Key YOUR_API_KEY'
        ]
    ]);
    
    $data = json_decode($response->getBody(), true);
    echo "成功取得回應:\n";
    print_r($data);
} catch (Exception $e) {
    echo '請求發生錯誤: ' . $e->getMessage();
}
?>
```

{% endtab %}
{% endtabs %}

#### 回應內容

**狀態碼: 200**

**回應結構範例**

```typescript
{
  "id": string (uuid)
  "inboxes"?: [ // 非必填
    {
      "id": string (uuid)
      "name": string
    }
  ]
  "inbox"?:  // 向前相容欄位：單一 inbox，若同時提供 inboxes 則忽略此欄位 (非必填)
  {
    "id": string (uuid)
    "name": string
  }
  "name": string
  "avatar"?: // 可能有不同的類型 (非必填)
  string (uri) // 聯絡人頭像 URL，支援完整 URL 或相對路徑 (非必填)
  "phoneNumber"?: string // 非必填
  "email"?: // 可能有不同的類型 (非必填)
  string (email) // 非必填
  "sourceId"?: string // 非必填
  "queryMetadata"?: { // 查詢元資料，控制可查詢的知識範圍；詳見各端點說明 (非必填)
  {
    "knowledgeBases"?: [ // 可查詢的知識庫清單；空陣列或 null＝全部不可查（無權限），未提供＝不限制 (非必填)
      {
        "knowledgeBaseId": string (uuid) // 知識庫 ID
        "chatbotFileIds"?: [ // 檔案 ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
          string (uuid)
        ]
        "knowledgeBaseFileIds"?: [ // 檔案 ID 清單（chatbotFileIds 的新名稱；兩者皆提供時以本欄位為準） (非必填)
          string (uuid)
        ]
        "faqIds"?: [ // FAQ ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
          string (uuid)
        ]
        "hasUserSelectedAll"?: boolean // true＝選取知識庫全部內容並排除清單中的項目；false＝僅選取清單中的項目 (非必填)
      }
    ]
    "labelRelations"?: { // 標籤過濾條件；conditions 為空陣列＝不做標籤過濾（並非無權限）。必須與 knowledgeBases 一併提供——單獨提供時知識庫檢索不會套用標籤過濾（等同不限制） (非必填)
    {
      "operator": string (enum: AND, OR) // 標籤條件的組合方式
      "conditions"?: [ // 標籤條件清單，支援巢狀 operator/conditions 組合 (非必填)
        object
      ]
    }
    }
  }
  }
  "metadata"?: object // 自訂的客戶資訊，會顯示在對話頁的客戶資訊區塊 (非必填)
  "mcpCredentials": [ // 聯絡人的 MCP 認證憑證列表
    object
  ]
  "apiCredentials": [ // 聯絡人的 API 認證憑證列表
    object
  ]
  "contactConnectors": [ // 聯絡人的 Connector OAuth 授權列表（不含 token 本體）
    object
  ]
  "tags": [
    {
      "id": string (uuid)
      "name": string
      "createdAt": string (timestamp)
      "updatedAt": string (timestamp)
    }
  ]
  "preChatFieldIndex": object // 來自此 Contact 所屬 inboxes 的 pre-chat form 欄位設定，mapping {field_id: {label: {locale: text}}}，前端用來把 metadata 的 UUID key 解析成顯示名稱
  "createdAt": string (timestamp)
  "updatedAt": string (timestamp)
}
```

**回應範例值**

```json
{
  "id": "user1_uuid",
  "inboxes": [
    {
      "id": "inbox_uuid",
      "name": "inbox_name"
    }
  ],
  "name": "user1",
  "avatar": "",
  "phoneNumber": 912345678,
  "email": "user1@example.com",
  "sourceId": null,
  "queryMetadata": null,
  "createdAt": "1751875361000",
  "updatedAt": "1751875361000"
}
```

***

### 取得聯絡人詳情 <a href="#undefined" id="undefined"></a>

GET `/api/v1/contacts/bulk-import-template/`

#### 程式碼範例

{% tabs %}
{% tab title="Shell/Bash" %}

```bash
# 呼叫 API 示例 (Shell)
curl -X GET "https://api.maiagent.ai/api/v1/contacts/bulk-import-template/" \
  -H "Authorization: Api-Key YOUR_API_KEY"

# 請確認在執行前替換 YOUR_API_KEY 並核對請求資料。
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const axios = require('axios');

// 設定請求標頭
const config = {
  headers: {
    'Authorization': 'Api-Key YOUR_API_KEY'
  }
};

axios.get("https://api.maiagent.ai/api/v1/contacts/bulk-import-template/", config)
  .then(response => {
    console.log('成功取得回應:');
    console.log(response.data);
  })
  .catch(error => {
    console.error('請求發生錯誤:');
    console.error(error.response?.data || error.message);
  });
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

url = "https://api.maiagent.ai/api/v1/contacts/bulk-import-template/"
headers = {
    "Authorization": "Api-Key YOUR_API_KEY"
}


response = requests.get(url, headers=headers)
try:
    print("成功取得回應:")
    print(response.json())
except Exception as e:
    print("請求發生錯誤:", e)
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();

try {
    $response = $client->get("https://api.maiagent.ai/api/v1/contacts/bulk-import-template/", [
        'headers' => [
            'Authorization' => 'Api-Key YOUR_API_KEY'
        ]
    ]);
    
    $data = json_decode($response->getBody(), true);
    echo "成功取得回應:\n";
    print_r($data);
} catch (Exception $e) {
    echo '請求發生錯誤: ' . $e->getMessage();
}
?>
```

{% endtab %}
{% endtabs %}

#### 回應內容

**狀態碼: 200**

**回應結構範例**

```typescript
{
  "id": string (uuid)
  "inboxes"?: [ // 非必填
    {
      "id": string (uuid)
      "name": string
    }
  ]
  "inbox"?:  // 向前相容欄位：單一 inbox，若同時提供 inboxes 則忽略此欄位 (非必填)
  {
    "id": string (uuid)
    "name": string
  }
  "name": string
  "avatar"?: // 可能有不同的類型 (非必填)
  string (uri) // 聯絡人頭像 URL，支援完整 URL 或相對路徑 (非必填)
  "phoneNumber"?: string // 非必填
  "email"?: // 可能有不同的類型 (非必填)
  string (email) // 非必填
  "sourceId"?: string // 非必填
  "queryMetadata"?: { // 查詢元資料，控制可查詢的知識範圍；詳見各端點說明 (非必填)
  {
    "knowledgeBases"?: [ // 可查詢的知識庫清單；空陣列或 null＝全部不可查（無權限），未提供＝不限制 (非必填)
      {
        "knowledgeBaseId": string (uuid) // 知識庫 ID
        "chatbotFileIds"?: [ // 檔案 ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
          string (uuid)
        ]
        "knowledgeBaseFileIds"?: [ // 檔案 ID 清單（chatbotFileIds 的新名稱；兩者皆提供時以本欄位為準） (非必填)
          string (uuid)
        ]
        "faqIds"?: [ // FAQ ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
          string (uuid)
        ]
        "hasUserSelectedAll"?: boolean // true＝選取知識庫全部內容並排除清單中的項目；false＝僅選取清單中的項目 (非必填)
      }
    ]
    "labelRelations"?: { // 標籤過濾條件；conditions 為空陣列＝不做標籤過濾（並非無權限）。必須與 knowledgeBases 一併提供——單獨提供時知識庫檢索不會套用標籤過濾（等同不限制） (非必填)
    {
      "operator": string (enum: AND, OR) // 標籤條件的組合方式
      "conditions"?: [ // 標籤條件清單，支援巢狀 operator/conditions 組合 (非必填)
        object
      ]
    }
    }
  }
  }
  "metadata"?: object // 自訂的客戶資訊，會顯示在對話頁的客戶資訊區塊 (非必填)
  "mcpCredentials": [ // 聯絡人的 MCP 認證憑證列表
    object
  ]
  "apiCredentials": [ // 聯絡人的 API 認證憑證列表
    object
  ]
  "contactConnectors": [ // 聯絡人的 Connector OAuth 授權列表（不含 token 本體）
    object
  ]
  "tags": [
    {
      "id": string (uuid)
      "name": string
      "createdAt": string (timestamp)
      "updatedAt": string (timestamp)
    }
  ]
  "preChatFieldIndex": object // 來自此 Contact 所屬 inboxes 的 pre-chat form 欄位設定，mapping {field_id: {label: {locale: text}}}，前端用來把 metadata 的 UUID key 解析成顯示名稱
  "createdAt": string (timestamp)
  "updatedAt": string (timestamp)
}
```

**回應範例值**

```json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "inboxes": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "回應字串"
    }
  ],
  "inbox": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "回應字串"
  },
  "name": "回應字串",
  "avatar": "https://example.com/file.jpg",
  "phoneNumber": "回應字串",
  "email": "response@example.com",
  "sourceId": "回應字串",
  "queryMetadata": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "回應範例名稱",
    "description": "回應範例描述"
  },
  "metadata": null,
  "mcpCredentials": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "回應範例名稱",
      "description": "回應範例描述"
    }
  ],
  "apiCredentials": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "回應範例名稱",
      "description": "回應範例描述"
    }
  ],
  "contactConnectors": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "回應範例名稱",
      "description": "回應範例描述"
    }
  ],
  "tags": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "回應字串",
      "createdAt": "回應字串",
      "updatedAt": "回應字串"
    }
  ],
  "preChatFieldIndex": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "回應範例名稱",
    "description": "回應範例描述"
  },
  "createdAt": "回應字串",
  "updatedAt": "回應字串"
}
```

***

### 取得聯絡人詳情 <a href="#undefined" id="undefined"></a>

GET `/api/v1/contacts/connector-management/`

#### 程式碼範例

{% tabs %}
{% tab title="Shell/Bash" %}

```bash
# 呼叫 API 示例 (Shell)
curl -X GET "https://api.maiagent.ai/api/v1/contacts/connector-management/" \
  -H "Authorization: Api-Key YOUR_API_KEY"

# 請確認在執行前替換 YOUR_API_KEY 並核對請求資料。
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const axios = require('axios');

// 設定請求標頭
const config = {
  headers: {
    'Authorization': 'Api-Key YOUR_API_KEY'
  }
};

axios.get("https://api.maiagent.ai/api/v1/contacts/connector-management/", config)
  .then(response => {
    console.log('成功取得回應:');
    console.log(response.data);
  })
  .catch(error => {
    console.error('請求發生錯誤:');
    console.error(error.response?.data || error.message);
  });
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

url = "https://api.maiagent.ai/api/v1/contacts/connector-management/"
headers = {
    "Authorization": "Api-Key YOUR_API_KEY"
}


response = requests.get(url, headers=headers)
try:
    print("成功取得回應:")
    print(response.json())
except Exception as e:
    print("請求發生錯誤:", e)
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();

try {
    $response = $client->get("https://api.maiagent.ai/api/v1/contacts/connector-management/", [
        'headers' => [
            'Authorization' => 'Api-Key YOUR_API_KEY'
        ]
    ]);
    
    $data = json_decode($response->getBody(), true);
    echo "成功取得回應:\n";
    print_r($data);
} catch (Exception $e) {
    echo '請求發生錯誤: ' . $e->getMessage();
}
?>
```

{% endtab %}
{% endtabs %}

#### 回應內容

| 狀態碼 | 說明               |
| --- | ---------------- |
| 200 | No response body |

***

### 更新聯絡人 <a href="#undefined" id="undefined"></a>

PUT `/api/v1/contacts/{id}/`

#### 參數

| 參數名稱 | 必填 | 類型     | 說明                                      |
| ---- | -- | ------ | --------------------------------------- |
| `id` | ✅  | string | A UUID string identifying this Contact. |

#### 請求內容

**請求參數**

| 欄位                                      | 類型                     | 必填 | 說明                                                                                                                                                                    |
| --------------------------------------- | ---------------------- | -- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name                                    | string                 | 否  | 聯絡人姓名                                                                                                                                                                 |
| inboxes                                 | array\[object]         | 否  | 對話平台列表（新版格式）                                                                                                                                                          |
| inbox                                   | object                 | 否  | 單一對話平台（舊版格式，向前相容）                                                                                                                                                     |
| inbox.id                                | string (uuid)          | 是  | 對話平台 ID                                                                                                                                                               |
| avatar                                  | string                 | 否  | 頭像URL                                                                                                                                                                 |
| phoneNumber                             | string                 | 否  | 聯絡人電話號碼                                                                                                                                                               |
| email                                   | string (email)         | 否  | 聯絡人電子信箱                                                                                                                                                               |
| sourceId                                | string                 | 否  | 來源ID                                                                                                                                                                  |
| queryMetadata                           | object                 | 否  | 查詢元資料（Query Metadata），控制可查詢的知識範圍。未提供或 null＝未設定（不限制）；空物件 {}＝視同不限制（全選），並非無權限；knowledgeBases 為空陣列或 null＝全部不可查（無權限）；labelRelations.conditions 為空陣列＝不做標籤過濾（並非無權限）。詳見本端點說明。 |
| queryMetadata.knowledgeBases            | array\[object]         | 否  | 可查詢的知識庫清單；空陣列或 null＝全部不可查（無權限），未提供＝不限制                                                                                                                                |
| queryMetadata.labelRelations            | object                 | 否  | 標籤過濾條件；conditions 為空陣列＝不做標籤過濾（並非無權限）。必須與 knowledgeBases 一併提供——單獨提供時知識庫檢索不會套用標籤過濾（等同不限制）                                                                               |
| queryMetadata.labelRelations.operator   | string (enum: AND, OR) | 是  | 標籤條件的組合方式                                                                                                                                                             |
| queryMetadata.labelRelations.conditions | array\[any]            | 否  | 標籤條件清單，支援巢狀 operator/conditions 組合                                                                                                                                    |
| metadata                                | array\[object]         | 否  | 自訂聯絡人屬性列表                                                                                                                                                             |

**請求結構範例**

```typescript
{
  "name"?: string // 聯絡人姓名 (非必填)
  "inboxes"?: [ // 對話平台列表（新版格式） (非必填)
    {
      "id": string (uuid) // 對話平台 ID
    }
  ]
  "inbox"?: { // 單一對話平台（舊版格式，向前相容） (非必填)
  {
    "id": string (uuid) // 對話平台 ID
  }
  }
  "avatar"?: string // 頭像URL (非必填)
  "phoneNumber"?: string // 聯絡人電話號碼 (非必填)
  "email"?: string (email) // 聯絡人電子信箱 (非必填)
  "sourceId"?: string // 來源ID (非必填)
  "queryMetadata"?: { // 查詢元資料（Query Metadata），控制可查詢的知識範圍。未提供或 null＝未設定（不限制）；空物件 {}＝視同不限制（全選），並非無權限；knowledgeBases 為空陣列或 null＝全部不可查（無權限）；labelRelations.conditions 為空陣列＝不做標籤過濾（並非無權限）。詳見本端點說明。 (非必填)
  {
    "knowledgeBases"?: [ // 可查詢的知識庫清單；空陣列或 null＝全部不可查（無權限），未提供＝不限制 (非必填)
      {
        "knowledgeBaseId": string (uuid) // 知識庫 ID
        "chatbotFileIds"?: [ // 檔案 ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
          string (uuid)
        ]
        "knowledgeBaseFileIds"?: [ // 檔案 ID 清單（chatbotFileIds 的新名稱；兩者皆提供時以本欄位為準） (非必填)
          string (uuid)
        ]
        "faqIds"?: [ // FAQ ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
          string (uuid)
        ]
        "hasUserSelectedAll"?: boolean // true＝選取知識庫全部內容並排除清單中的項目；false＝僅選取清單中的項目 (非必填)
      }
    ]
    "labelRelations"?: { // 標籤過濾條件；conditions 為空陣列＝不做標籤過濾（並非無權限）。必須與 knowledgeBases 一併提供——單獨提供時知識庫檢索不會套用標籤過濾（等同不限制） (非必填)
    {
      "operator": string (enum: AND, OR) // 標籤條件的組合方式
      "conditions"?: [ // 標籤條件清單，支援巢狀 operator/conditions 組合 (非必填)
        object
      ]
    }
    }
  }
  }
  "metadata"?: [ // 自訂聯絡人屬性列表 (非必填)
    {
      "key": string // 屬性名稱
      "value": string // 屬性值
      "updatedAt"?: string // 更新時間（ISO 格式，可選，未提供則自動填入） (非必填)
    }
  ]
}
```

**請求範例值**

```json
{
  "inboxes": [
    {
      "id": "new_inbox_uuid"
    }
  ],
  "name": "updated_user_name",
  "avatar": "updated_avatar_url",
  "phoneNumber": 987654321,
  "email": "updated@example.com",
  "sourceId": "updated_source_id",
  "queryMetadata": {
    "knowledgeBases": []
  },
  "metadata": [
    {
      "key": "客戶等級",
      "value": "VVIP"
    },
    {
      "key": "偏好語言",
      "value": "日本語"
    }
  ]
}
```

#### 程式碼範例

{% tabs %}
{% tab title="Shell/Bash" %}

```bash
# 呼叫 API 示例 (Shell)
curl -X PUT "https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/" \
  -H "Authorization: Api-Key YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "inboxes": [
      {
        "id": "new_inbox_uuid"
      }
    ],
    "name": "updated_user_name",
    "avatar": "updated_avatar_url",
    "phoneNumber": 987654321,
    "email": "updated@example.com",
    "sourceId": "updated_source_id",
    "queryMetadata": {
      "knowledgeBases": []
    },
    "metadata": [
      {
        "key": "客戶等級",
        "value": "VVIP"
      },
      {
        "key": "偏好語言",
        "value": "日本語"
      }
    ]
  }'

# 請確認在執行前替換 YOUR_API_KEY 並核對請求資料。
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const axios = require('axios');

// 設定請求標頭
const config = {
  headers: {
    'Authorization': 'Api-Key YOUR_API_KEY',
    'Content-Type': 'application/json'
  }
};

// 請求內容 (payload)
const data = {
    "inboxes": [
      {
        "id": "new_inbox_uuid"
      }
    ],
    "name": "updated_user_name",
    "avatar": "updated_avatar_url",
    "phoneNumber": 987654321,
    "email": "updated@example.com",
    "sourceId": "updated_source_id",
    "queryMetadata": {
      "knowledgeBases": []
    },
    "metadata": [
      {
        "key": "客戶等級",
        "value": "VVIP"
      },
      {
        "key": "偏好語言",
        "value": "日本語"
      }
    ]
  };

axios.put("https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/", data, config)
  .then(response => {
    console.log('成功取得回應:');
    console.log(response.data);
  })
  .catch(error => {
    console.error('請求發生錯誤:');
    console.error(error.response?.data || error.message);
  });
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

url = "https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/"
headers = {
    "Authorization": "Api-Key YOUR_API_KEY",
    "Content-Type": "application/json"
}

# 請求內容 (payload)
data = {
      "inboxes": [
        {
          "id": "new_inbox_uuid"
        }
      ],
      "name": "updated_user_name",
      "avatar": "updated_avatar_url",
      "phoneNumber": 987654321,
      "email": "updated@example.com",
      "sourceId": "updated_source_id",
      "queryMetadata": {
        "knowledgeBases": []
      },
      "metadata": [
        {
          "key": "客戶等級",
          "value": "VVIP"
        },
        {
          "key": "偏好語言",
          "value": "日本語"
        }
      ]
    }

response = requests.put(url, json=data, headers=headers)
try:
    print("成功取得回應:")
    print(response.json())
except Exception as e:
    print("請求發生錯誤:", e)
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();

try {
    $response = $client->put("https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/", [
        'headers' => [
            'Authorization' => 'Api-Key YOUR_API_KEY',
            'Content-Type' => 'application/json'
        ],
        'json' => {
            "inboxes": [
                {
                    "id": "new_inbox_uuid"
                }
            ],
            "name": "updated_user_name",
            "avatar": "updated_avatar_url",
            "phoneNumber": 987654321,
            "email": "updated@example.com",
            "sourceId": "updated_source_id",
            "queryMetadata": {
                "knowledgeBases": []
            },
            "metadata": [
                {
                    "key": "客戶等級",
                    "value": "VVIP"
                },
                {
                    "key": "偏好語言",
                    "value": "日本語"
                }
            ]
        }
    ]);
    
    $data = json_decode($response->getBody(), true);
    echo "成功取得回應:\n";
    print_r($data);
} catch (Exception $e) {
    echo '請求發生錯誤: ' . $e->getMessage();
}
?>
```

{% endtab %}
{% endtabs %}

#### 回應內容

**狀態碼: 200**

**回應結構範例**

```typescript
{
  "id": string (uuid)
  "inboxes"?: [ // 非必填
    {
      "id": string (uuid)
      "name": string
    }
  ]
  "inbox"?:  // 向前相容欄位：單一 inbox，若同時提供 inboxes 則忽略此欄位 (非必填)
  {
    "id": string (uuid)
    "name": string
  }
  "name": string
  "avatar"?: // 可能有不同的類型 (非必填)
  string (uri) // 聯絡人頭像 URL，支援完整 URL 或相對路徑 (非必填)
  "phoneNumber"?: string // 非必填
  "email"?: // 可能有不同的類型 (非必填)
  string (email) // 非必填
  "sourceId"?: string // 非必填
  "queryMetadata"?: { // 查詢元資料，控制可查詢的知識範圍；詳見各端點說明 (非必填)
  {
    "knowledgeBases"?: [ // 可查詢的知識庫清單；空陣列或 null＝全部不可查（無權限），未提供＝不限制 (非必填)
      {
        "knowledgeBaseId": string (uuid) // 知識庫 ID
        "chatbotFileIds"?: [ // 檔案 ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
          string (uuid)
        ]
        "knowledgeBaseFileIds"?: [ // 檔案 ID 清單（chatbotFileIds 的新名稱；兩者皆提供時以本欄位為準） (非必填)
          string (uuid)
        ]
        "faqIds"?: [ // FAQ ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
          string (uuid)
        ]
        "hasUserSelectedAll"?: boolean // true＝選取知識庫全部內容並排除清單中的項目；false＝僅選取清單中的項目 (非必填)
      }
    ]
    "labelRelations"?: { // 標籤過濾條件；conditions 為空陣列＝不做標籤過濾（並非無權限）。必須與 knowledgeBases 一併提供——單獨提供時知識庫檢索不會套用標籤過濾（等同不限制） (非必填)
    {
      "operator": string (enum: AND, OR) // 標籤條件的組合方式
      "conditions"?: [ // 標籤條件清單，支援巢狀 operator/conditions 組合 (非必填)
        object
      ]
    }
    }
  }
  }
  "metadata"?: object // 自訂的客戶資訊，會顯示在對話頁的客戶資訊區塊 (非必填)
  "mcpCredentials": [ // 聯絡人的 MCP 認證憑證列表
    object
  ]
  "apiCredentials": [ // 聯絡人的 API 認證憑證列表
    object
  ]
  "contactConnectors": [ // 聯絡人的 Connector OAuth 授權列表（不含 token 本體）
    object
  ]
  "tags": [
    {
      "id": string (uuid)
      "name": string
      "createdAt": string (timestamp)
      "updatedAt": string (timestamp)
    }
  ]
  "preChatFieldIndex": object // 來自此 Contact 所屬 inboxes 的 pre-chat form 欄位設定，mapping {field_id: {label: {locale: text}}}，前端用來把 metadata 的 UUID key 解析成顯示名稱
  "createdAt": string (timestamp)
  "updatedAt": string (timestamp)
}
```

**回應範例值**

```json
{
  "id": "user1_uuid",
  "inboxes": [
    {
      "id": "inbox_uuid",
      "name": "inbox_name"
    }
  ],
  "name": "user1",
  "avatar": "",
  "phoneNumber": 912345678,
  "email": "user1@example.com",
  "sourceId": null,
  "queryMetadata": null,
  "createdAt": "1751875361000",
  "updatedAt": "1751875361000"
}
```

***

### 部分更新聯絡人 <a href="#undefined" id="undefined"></a>

PATCH `/api/v1/contacts/{id}/`

#### 參數

| 參數名稱 | 必填 | 類型     | 說明                                      |
| ---- | -- | ------ | --------------------------------------- |
| `id` | ✅  | string | A UUID string identifying this Contact. |

#### 請求內容

**請求參數**

| 欄位                                      | 類型                     | 必填 | 說明                                                                                                                                                                    |
| --------------------------------------- | ---------------------- | -- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name                                    | string                 | 否  | 聯絡人姓名                                                                                                                                                                 |
| inboxes                                 | array\[object]         | 否  | 對話平台列表（新版格式）                                                                                                                                                          |
| inbox                                   | object                 | 否  | 單一對話平台（舊版格式，向前相容）                                                                                                                                                     |
| inbox.id                                | string (uuid)          | 是  | 對話平台 ID                                                                                                                                                               |
| avatar                                  | string                 | 否  | 頭像URL                                                                                                                                                                 |
| phoneNumber                             | string                 | 否  | 聯絡人電話號碼                                                                                                                                                               |
| email                                   | string (email)         | 否  | 聯絡人電子信箱                                                                                                                                                               |
| sourceId                                | string                 | 否  | 來源ID                                                                                                                                                                  |
| queryMetadata                           | object                 | 否  | 查詢元資料（Query Metadata），控制可查詢的知識範圍。未提供或 null＝未設定（不限制）；空物件 {}＝視同不限制（全選），並非無權限；knowledgeBases 為空陣列或 null＝全部不可查（無權限）；labelRelations.conditions 為空陣列＝不做標籤過濾（並非無權限）。詳見本端點說明。 |
| queryMetadata.knowledgeBases            | array\[object]         | 否  | 可查詢的知識庫清單；空陣列或 null＝全部不可查（無權限），未提供＝不限制                                                                                                                                |
| queryMetadata.labelRelations            | object                 | 否  | 標籤過濾條件；conditions 為空陣列＝不做標籤過濾（並非無權限）。必須與 knowledgeBases 一併提供——單獨提供時知識庫檢索不會套用標籤過濾（等同不限制）                                                                               |
| queryMetadata.labelRelations.operator   | string (enum: AND, OR) | 是  | 標籤條件的組合方式                                                                                                                                                             |
| queryMetadata.labelRelations.conditions | array\[any]            | 否  | 標籤條件清單，支援巢狀 operator/conditions 組合                                                                                                                                    |
| metadata                                | array\[object]         | 否  | 自訂聯絡人屬性列表                                                                                                                                                             |

**請求結構範例**

```typescript
{
  "name"?: string // 聯絡人姓名 (非必填)
  "inboxes"?: [ // 對話平台列表（新版格式） (非必填)
    {
      "id": string (uuid) // 對話平台 ID
    }
  ]
  "inbox"?: { // 單一對話平台（舊版格式，向前相容） (非必填)
  {
    "id": string (uuid) // 對話平台 ID
  }
  }
  "avatar"?: string // 頭像URL (非必填)
  "phoneNumber"?: string // 聯絡人電話號碼 (非必填)
  "email"?: string (email) // 聯絡人電子信箱 (非必填)
  "sourceId"?: string // 來源ID (非必填)
  "queryMetadata"?: { // 查詢元資料（Query Metadata），控制可查詢的知識範圍。未提供或 null＝未設定（不限制）；空物件 {}＝視同不限制（全選），並非無權限；knowledgeBases 為空陣列或 null＝全部不可查（無權限）；labelRelations.conditions 為空陣列＝不做標籤過濾（並非無權限）。詳見本端點說明。 (非必填)
  {
    "knowledgeBases"?: [ // 可查詢的知識庫清單；空陣列或 null＝全部不可查（無權限），未提供＝不限制 (非必填)
      {
        "knowledgeBaseId": string (uuid) // 知識庫 ID
        "chatbotFileIds"?: [ // 檔案 ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
          string (uuid)
        ]
        "knowledgeBaseFileIds"?: [ // 檔案 ID 清單（chatbotFileIds 的新名稱；兩者皆提供時以本欄位為準） (非必填)
          string (uuid)
        ]
        "faqIds"?: [ // FAQ ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
          string (uuid)
        ]
        "hasUserSelectedAll"?: boolean // true＝選取知識庫全部內容並排除清單中的項目；false＝僅選取清單中的項目 (非必填)
      }
    ]
    "labelRelations"?: { // 標籤過濾條件；conditions 為空陣列＝不做標籤過濾（並非無權限）。必須與 knowledgeBases 一併提供——單獨提供時知識庫檢索不會套用標籤過濾（等同不限制） (非必填)
    {
      "operator": string (enum: AND, OR) // 標籤條件的組合方式
      "conditions"?: [ // 標籤條件清單，支援巢狀 operator/conditions 組合 (非必填)
        object
      ]
    }
    }
  }
  }
  "metadata"?: [ // 自訂聯絡人屬性列表 (非必填)
    {
      "key": string // 屬性名稱
      "value": string // 屬性值
      "updatedAt"?: string // 更新時間（ISO 格式，可選，未提供則自動填入） (非必填)
    }
  ]
}
```

**請求範例值**

```json
{
  "inboxes": [
    {
      "id": "new_inbox_uuid"
    }
  ],
  "name": "updated_user_name",
  "avatar": "updated_avatar_url",
  "phoneNumber": 987654321,
  "email": "updated@example.com",
  "sourceId": "updated_source_id",
  "queryMetadata": {
    "knowledgeBases": []
  },
  "metadata": [
    {
      "key": "客戶等級",
      "value": "VVIP"
    },
    {
      "key": "偏好語言",
      "value": "日本語"
    }
  ]
}
```

#### 程式碼範例

{% tabs %}
{% tab title="Shell/Bash" %}

```bash
# 呼叫 API 示例 (Shell)
curl -X PATCH "https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/" \
  -H "Authorization: Api-Key YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "inboxes": [
      {
        "id": "new_inbox_uuid"
      }
    ],
    "name": "updated_user_name",
    "avatar": "updated_avatar_url",
    "phoneNumber": 987654321,
    "email": "updated@example.com",
    "sourceId": "updated_source_id",
    "queryMetadata": {
      "knowledgeBases": []
    },
    "metadata": [
      {
        "key": "客戶等級",
        "value": "VVIP"
      },
      {
        "key": "偏好語言",
        "value": "日本語"
      }
    ]
  }'

# 請確認在執行前替換 YOUR_API_KEY 並核對請求資料。
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const axios = require('axios');

// 設定請求標頭
const config = {
  headers: {
    'Authorization': 'Api-Key YOUR_API_KEY',
    'Content-Type': 'application/json'
  }
};

// 請求內容 (payload)
const data = {
    "inboxes": [
      {
        "id": "new_inbox_uuid"
      }
    ],
    "name": "updated_user_name",
    "avatar": "updated_avatar_url",
    "phoneNumber": 987654321,
    "email": "updated@example.com",
    "sourceId": "updated_source_id",
    "queryMetadata": {
      "knowledgeBases": []
    },
    "metadata": [
      {
        "key": "客戶等級",
        "value": "VVIP"
      },
      {
        "key": "偏好語言",
        "value": "日本語"
      }
    ]
  };

axios.patch("https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/", data, config)
  .then(response => {
    console.log('成功取得回應:');
    console.log(response.data);
  })
  .catch(error => {
    console.error('請求發生錯誤:');
    console.error(error.response?.data || error.message);
  });
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

url = "https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/"
headers = {
    "Authorization": "Api-Key YOUR_API_KEY",
    "Content-Type": "application/json"
}

# 請求內容 (payload)
data = {
      "inboxes": [
        {
          "id": "new_inbox_uuid"
        }
      ],
      "name": "updated_user_name",
      "avatar": "updated_avatar_url",
      "phoneNumber": 987654321,
      "email": "updated@example.com",
      "sourceId": "updated_source_id",
      "queryMetadata": {
        "knowledgeBases": []
      },
      "metadata": [
        {
          "key": "客戶等級",
          "value": "VVIP"
        },
        {
          "key": "偏好語言",
          "value": "日本語"
        }
      ]
    }

response = requests.patch(url, json=data, headers=headers)
try:
    print("成功取得回應:")
    print(response.json())
except Exception as e:
    print("請求發生錯誤:", e)
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();

try {
    $response = $client->patch("https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/", [
        'headers' => [
            'Authorization' => 'Api-Key YOUR_API_KEY',
            'Content-Type' => 'application/json'
        ],
        'json' => {
            "inboxes": [
                {
                    "id": "new_inbox_uuid"
                }
            ],
            "name": "updated_user_name",
            "avatar": "updated_avatar_url",
            "phoneNumber": 987654321,
            "email": "updated@example.com",
            "sourceId": "updated_source_id",
            "queryMetadata": {
                "knowledgeBases": []
            },
            "metadata": [
                {
                    "key": "客戶等級",
                    "value": "VVIP"
                },
                {
                    "key": "偏好語言",
                    "value": "日本語"
                }
            ]
        }
    ]);
    
    $data = json_decode($response->getBody(), true);
    echo "成功取得回應:\n";
    print_r($data);
} catch (Exception $e) {
    echo '請求發生錯誤: ' . $e->getMessage();
}
?>
```

{% endtab %}
{% endtabs %}

#### 回應內容

**狀態碼: 200**

**回應結構範例**

```typescript
{
  "id": string (uuid)
  "inboxes"?: [ // 非必填
    {
      "id": string (uuid)
      "name": string
    }
  ]
  "inbox"?:  // 向前相容欄位：單一 inbox，若同時提供 inboxes 則忽略此欄位 (非必填)
  {
    "id": string (uuid)
    "name": string
  }
  "name": string
  "avatar"?: // 可能有不同的類型 (非必填)
  string (uri) // 聯絡人頭像 URL，支援完整 URL 或相對路徑 (非必填)
  "phoneNumber"?: string // 非必填
  "email"?: // 可能有不同的類型 (非必填)
  string (email) // 非必填
  "sourceId"?: string // 非必填
  "queryMetadata"?: { // 查詢元資料，控制可查詢的知識範圍；詳見各端點說明 (非必填)
  {
    "knowledgeBases"?: [ // 可查詢的知識庫清單；空陣列或 null＝全部不可查（無權限），未提供＝不限制 (非必填)
      {
        "knowledgeBaseId": string (uuid) // 知識庫 ID
        "chatbotFileIds"?: [ // 檔案 ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
          string (uuid)
        ]
        "knowledgeBaseFileIds"?: [ // 檔案 ID 清單（chatbotFileIds 的新名稱；兩者皆提供時以本欄位為準） (非必填)
          string (uuid)
        ]
        "faqIds"?: [ // FAQ ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
          string (uuid)
        ]
        "hasUserSelectedAll"?: boolean // true＝選取知識庫全部內容並排除清單中的項目；false＝僅選取清單中的項目 (非必填)
      }
    ]
    "labelRelations"?: { // 標籤過濾條件；conditions 為空陣列＝不做標籤過濾（並非無權限）。必須與 knowledgeBases 一併提供——單獨提供時知識庫檢索不會套用標籤過濾（等同不限制） (非必填)
    {
      "operator": string (enum: AND, OR) // 標籤條件的組合方式
      "conditions"?: [ // 標籤條件清單，支援巢狀 operator/conditions 組合 (非必填)
        object
      ]
    }
    }
  }
  }
  "metadata"?: object // 自訂的客戶資訊，會顯示在對話頁的客戶資訊區塊 (非必填)
  "mcpCredentials": [ // 聯絡人的 MCP 認證憑證列表
    object
  ]
  "apiCredentials": [ // 聯絡人的 API 認證憑證列表
    object
  ]
  "contactConnectors": [ // 聯絡人的 Connector OAuth 授權列表（不含 token 本體）
    object
  ]
  "tags": [
    {
      "id": string (uuid)
      "name": string
      "createdAt": string (timestamp)
      "updatedAt": string (timestamp)
    }
  ]
  "preChatFieldIndex": object // 來自此 Contact 所屬 inboxes 的 pre-chat form 欄位設定，mapping {field_id: {label: {locale: text}}}，前端用來把 metadata 的 UUID key 解析成顯示名稱
  "createdAt": string (timestamp)
  "updatedAt": string (timestamp)
}
```

**回應範例值**

```json
{
  "id": "user1_uuid",
  "inboxes": [
    {
      "id": "inbox_uuid",
      "name": "inbox_name"
    }
  ],
  "name": "user1",
  "avatar": "",
  "phoneNumber": 912345678,
  "email": "user1@example.com",
  "sourceId": null,
  "queryMetadata": null,
  "createdAt": "1751875361000",
  "updatedAt": "1751875361000"
}
```

***

### 刪除聯絡人 <a href="#undefined" id="undefined"></a>

DELETE `/api/v1/contacts/{id}/`

#### 參數

| 參數名稱 | 必填 | 類型     | 說明                                      |
| ---- | -- | ------ | --------------------------------------- |
| `id` | ✅  | string | A UUID string identifying this Contact. |

#### 程式碼範例

{% tabs %}
{% tab title="Shell/Bash" %}

```bash
# 呼叫 API 示例 (Shell)
curl -X DELETE "https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/" \
  -H "Authorization: Api-Key YOUR_API_KEY"

# 請確認在執行前替換 YOUR_API_KEY 並核對請求資料。
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const axios = require('axios');

// 設定請求標頭
const config = {
  headers: {
    'Authorization': 'Api-Key YOUR_API_KEY'
  }
};

// 請求內容 (payload)
const data = null;

axios.delete("https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/", data, config)
  .then(response => {
    console.log('成功取得回應:');
    console.log(response.data);
  })
  .catch(error => {
    console.error('請求發生錯誤:');
    console.error(error.response?.data || error.message);
  });
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

url = "https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/"
headers = {
    "Authorization": "Api-Key YOUR_API_KEY"
}


response = requests.delete(url, headers=headers)
try:
    print("成功取得回應:")
    print(response.json())
except Exception as e:
    print("請求發生錯誤:", e)
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();

try {
    $response = $client->delete("https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/", [
        'headers' => [
            'Authorization' => 'Api-Key YOUR_API_KEY'
        ]
    ]);
    
    $data = json_decode($response->getBody(), true);
    echo "成功取得回應:\n";
    print_r($data);
} catch (Exception $e) {
    echo '請求發生錯誤: ' . $e->getMessage();
}
?>
```

{% endtab %}
{% endtabs %}

#### 回應內容

| 狀態碼 | 說明               |
| --- | ---------------- |
| 204 | No response body |
| 400 | 聯絡人還有關聯的對話，無法刪除  |

***

### 取得聯絡人的對話列表 <a href="#undefined" id="undefined"></a>

GET `/api/v1/contacts/{id}/conversations/`

#### 參數

| 參數名稱       | 必填 | 類型      | 說明                                                    |
| ---------- | -- | ------- | ----------------------------------------------------- |
| `id`       | ✅  | string  | A UUID string identifying this Contact.               |
| `channels` | ❌  | array   | Multiple values may be separated by commas.           |
| `inbox`    | ❌  | string  | 按單一 inbox ID 過濾（UUID 格式）                              |
| `inboxes`  | ❌  | string  | 按多個 inbox IDs 過濾（逗號分隔，如：uuid1,uuid2 或使用多個 inboxes 參數） |
| `keyword`  | ❌  | string  | 搜尋對話中的訊息內容（不區分大小寫）                                    |
| `page`     | ❌  | integer | A page number within the paginated result set.        |
| `pageSize` | ❌  | integer | Number of results to return per page.                 |
| `query`    | ❌  | string  |                                                       |
| `tags`     | ❌  | array   | Multiple values may be separated by commas.           |

#### 程式碼範例

{% tabs %}
{% tab title="Shell/Bash" %}

```bash
# 呼叫 API 示例 (Shell)
curl -X GET "https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/conversations/?channels=example&inbox=example&inboxes=example&keyword=example&page=1&pageSize=1&query=example&tags=example" \
  -H "Authorization: Api-Key YOUR_API_KEY"

# 請確認在執行前替換 YOUR_API_KEY 並核對請求資料。
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const axios = require('axios');

// 設定請求標頭
const config = {
  headers: {
    'Authorization': 'Api-Key YOUR_API_KEY'
  }
};

axios.get("https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/conversations/?channels=example&inbox=example&inboxes=example&keyword=example&page=1&pageSize=1&query=example&tags=example", config)
  .then(response => {
    console.log('成功取得回應:');
    console.log(response.data);
  })
  .catch(error => {
    console.error('請求發生錯誤:');
    console.error(error.response?.data || error.message);
  });
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

url = "https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/conversations/?channels=example&inbox=example&inboxes=example&keyword=example&page=1&pageSize=1&query=example&tags=example"
headers = {
    "Authorization": "Api-Key YOUR_API_KEY"
}


response = requests.get(url, headers=headers)
try:
    print("成功取得回應:")
    print(response.json())
except Exception as e:
    print("請求發生錯誤:", e)
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();

try {
    $response = $client->get("https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/conversations/?channels=example&inbox=example&inboxes=example&keyword=example&page=1&pageSize=1&query=example&tags=example", [
        'headers' => [
            'Authorization' => 'Api-Key YOUR_API_KEY'
        ]
    ]);
    
    $data = json_decode($response->getBody(), true);
    echo "成功取得回應:\n";
    print_r($data);
} catch (Exception $e) {
    echo '請求發生錯誤: ' . $e->getMessage();
}
?>
```

{% endtab %}
{% endtabs %}

#### 回應內容

**狀態碼: 200**

**回應結構範例**

```typescript
{
  "count": integer
  "next"?: string (uri) // 非必填
  "previous"?: string (uri) // 非必填
  "results": [
    {
      "id": string (uuid)
      "contact": { // 輕量級 Contact Serializer，用於 Conversation List view

只包含 List view 必要的欄位，移除 inboxes、mcp_credentials 和 api_credentials
以避免 N+1 查詢問題。email / phone_number / metadata 為 Contact 自身的純量欄位，
前端對話側欄需要顯示，無 N+1 成本。
      {
        "id": string (uuid)
        "name": string
        "avatar"?: string // Stores our own media as a relative storage key, or an external CDN URL as-is. (非必填)
        "email"?: // 可能有不同的類型 (非必填)
        string (email) // 非必填
        "phoneNumber"?: string // 非必填
        "metadata"?: object // 自訂的客戶資訊，會顯示在對話頁的客戶資訊區塊 (非必填)
        "sourceId"?: string // 非必填
        "tags": [
          {
            "id": string (uuid)
            "name": string
          }
        ]
      }
      }
      "inbox": {
      {
        "id": string (uuid)
        "name": string
        "channelType": string (enum: line, telegram, teams, web, messenger, instagram, email, whatsapp, slack, team_plus, line_works, viber) // * `line` - LINE
* `telegram` - Telegram
* `teams` - Teams
* `web` - Web
* `messenger` - Messenger
* `instagram` - Instagram
* `email` - Email
* `whatsapp` - WhatsApp
* `slack` - Slack
* `team_plus` - Team+
* `line_works` - LINE WORKS
* `viber` - Viber
        "unreadConversationsCount"?: integer // 非必填
        "signAuth"?:  // 非必填
        {
          "id": string (uuid)
          "signSource": string (uuid)
          "signParams": {
          {
            "keycloak": 
            {
              "clientId": string
              "url": string
              "realm": string
            }
            "line": 
            {
              "liffId": string
            }
            "ad": 
            {
              "saml": string
            }
            "google"?:  // 非必填
            {
              "enabled": boolean
            }
          }
          }
          "sourceIdAccessEnabled"?: boolean // When enabled, embedded visitors presenting a Source ID (verified per the verify mode below) may chat without going through the login flow. Disabled keeps every existing behavior unchanged. (非必填)
          "sourceIdVerifyMode"?:  // "Require signature verification": the embedding site must send an HMAC signature computed on its backend. "Source ID only": anyone knowing a Source ID can act as that contact; suitable only for testing or closed networks.

* `signature` - Require signature verification
* `raw` - Source ID only (非必填)
          {
          }
          "sourceIdSignatureTtlMinutes"?:  // How long a signature can be used to obtain the contact identity. Not a session lifetime: once exchanged, the session follows the existing WebChat mechanism.

* `1` - 1
* `5` - 5
* `15` - 15 (非必填)
          {
          }
        }
        "enableAnalysis"?: boolean // 非必填
      }
      }
      "chatbot": object // Chatbot (Agent) summary from the conversation's inbox, already eager-loaded.

``is_maigpt`` lets the client tell the default MaiGPT agent apart (icon, feature
gate) without comparing against the organization's ``maigpt_inbox`` id.
      "title": string
      "lastMessage"?: { // 非必填
      {
        "id": string (uuid)
        "type"?: string // 非必填
        "content"?: string // 非必填
        "createdAt": string (timestamp)
      }
      }
      "callRecord": 
      {
        "id": string (uuid)
        "status"?: string (enum: initiated, ringing, in-progress, completed, failed, busy, no-answer, canceled) // * `initiated` - Initiated
* `ringing` - Ringing
* `in-progress` - In Progress
* `completed` - Completed
* `failed` - Failed
* `busy` - Busy
* `no-answer` - No Answer
* `canceled` - Canceled (非必填)
        "direction": string (enum: inbound, outbound) // * `inbound` - Inbound
* `outbound` - Outbound
        "isActive": boolean
        "canHangup": boolean
      }
      "lastMessageCreatedAt": string (timestamp)
      "unreadMessagesCount": integer
      "autoReplyEnabled": boolean
      "isAutoReplyNow": boolean
      "lastReadAt": string (timestamp)
      "createdAt": string (timestamp)
      "isGroupChat": boolean
      "enableGroupMention"?: boolean // 非必填
      "queryMetadata"?: { // 查詢元資料，控制可查詢的知識範圍；詳見各端點說明 (非必填)
      {
        "knowledgeBases"?: [ // 可查詢的知識庫清單；空陣列或 null＝全部不可查（無權限），未提供＝不限制 (非必填)
          {
            "knowledgeBaseId": string (uuid) // 知識庫 ID
            "chatbotFileIds"?: [ // 檔案 ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
              string (uuid)
            ]
            "knowledgeBaseFileIds"?: [ // 檔案 ID 清單（chatbotFileIds 的新名稱；兩者皆提供時以本欄位為準） (非必填)
              string (uuid)
            ]
            "faqIds"?: [ // FAQ ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
              string (uuid)
            ]
            "hasUserSelectedAll"?: boolean // true＝選取知識庫全部內容並排除清單中的項目；false＝僅選取清單中的項目 (非必填)
          }
        ]
        "labelRelations"?: { // 標籤過濾條件；conditions 為空陣列＝不做標籤過濾（並非無權限）。必須與 knowledgeBases 一併提供——單獨提供時知識庫檢索不會套用標籤過濾（等同不限制） (非必填)
        {
          "operator": string (enum: AND, OR) // 標籤條件的組合方式
          "conditions"?: [ // 標籤條件清單，支援巢狀 operator/conditions 組合 (非必填)
            object
          ]
        }
        }
      }
      }
      "toolMask"?: object // 記錄每個工具的啟用/停用狀態 {tool_id: bool} (非必填)
      "connectorMask"?: object // 記錄每個連接器的啟用/停用狀態 {connector_id: bool} (非必填)
      "thinkingConfig"?: object // None=未設定(使用 chatbot 設定), {}=明確關閉, {...}=自訂覆寫 (非必填)
      "thinkingConfigSchema": object
      "effectiveThinkingConfig": object // Return the effective thinking config after applying the priority chain:
conversation override > chatbot config > LLM metadata.

This allows the frontend to display the actual thinking config in use,
even when the conversation has no explicit override.

Returns None when nothing is configured at any level, so the frontend
can distinguish "Default" (None = use model/assistant default) from
"Off" ({} = explicitly disabled). Collapsing the unconfigured case to
{} would make a fresh conversation display as Off instead of Default.
      "llm": string (uuid)
      "deepResearchStatus":  // Status of deep research for this conversation

* `not_used` - Not Used
* `started` - Started
* `running` - Running
* `completed` - Completed
* `failed` - Failed
      {
      }
      "deepResearchOutputFormat": // 可能有不同的類型
      string (enum: canvas, chat, file) // Chosen delivery form for the finished report. Set only when the user clicks a format in the pre-research choice card; reset to NULL each time Deep Research is (re-)armed. NULL means no explicit choice (or a plan-skipping request) and falls back to Canvas at render time, but stays distinct from an explicit canvas pick so the frontend can lock the card only after a real selection. To roll back to fixed-Canvas behavior, force this to NULL/canvas — no redeploy needed.

* `canvas` - Canvas
* `chat` - Chat reply
* `file` - Downloadable file
      "ipAddress": string
      "ipCountryCode": string
      "ipRecordedAt": string (timestamp)
      "assignee": 
      {
        "id": string (uuid)
        "name": string
        "userId": string (uuid)
      }
      "status"?: string (enum: open, resolved, queued) // * `open` - Open
* `resolved` - Resolved
* `queued` - Queued (非必填)
      "tags": [
        {
          "id": string (uuid)
          "name": string
          "memberIds"?: [ // 非必填
            string (uuid)
          ]
        }
      ]
      "progressStatus": string
      "firstResponseAt"?: string (timestamp) // 非必填
      "queuedAt"?: string (timestamp) // 非必填
      "assignedAt"?: string (timestamp) // 非必填
      "transferReason"?: string // 非必填
      "satisfactionScore": integer // Conversation satisfaction rating on a 5-point scale (1=very dissatisfied, 5=very satisfied)
      "satisfactionComment": string
      "satisfactionSubmittedAt": string (timestamp)
      "latestAnalysisSummary": string // The conversation's current analysis summary (its active summary revision).

Reads the `latest_analysis_summary` annotation added by `setup_eager_loading`
to avoid an N+1 query. All read paths (list / retrieve / create) eager-load,
so the annotation is present; it falls back to '' only for instances built
outside `setup_eager_loading`.
      "clientPlatform":  // Client platform that created this conversation (web, desktop)

* `web` - Web
* `desktop` - Desktop
      {
      }
      "workingDirectory": string // Absolute path of the local folder bound to a desktop conversation. Only set for desktop conversations; null for web conversations.
      "slideProjectId": string
      "matchedField": string // Cached per instance: ``get_matched_message_id`` / ``get_matched_snippet``
both read this, so resolving it once avoids recomputing the keyword and
title-match logic three times per serialized conversation.
      "matchedSnippet": string // Keyword-centred excerpt of the matched message, with ellipses.

Reads the ``matched_message_content`` annotation added by
``ConversationViewSet._annotate_keyword_match``; no extra query.
      "matchedMessageId": string
      "pinnedAt": string (timestamp) // When the conversation was pinned. Null means unpinned.
      "hasActiveBrowserSession": boolean // Whether a browser_use session snapshot exists to resume.

Lets the frontend know it should proactively re-request the browser
panel (emit ``browser:start``) after a page reload, instead of only
ever showing the panel when a live ``browser:frame`` push happens to
arrive first.
      "callerOrganizationId": string // Bound caller organization (stamped at conversation start); null when unbound
    }
  ]
}
```

**回應範例值**

```json
{
  "count": 123,
  "next": "http://api.example.org/accounts/?page=4",
  "previous": "http://api.example.org/accounts/?page=2",
  "results": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "contact": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "name": "回應字串",
        "avatar": "回應字串",
        "email": "response@example.com",
        "phoneNumber": "回應字串",
        "metadata": null,
        "sourceId": "回應字串",
        "tags": [
          {
            "id": "550e8400-e29b-41d4-a716-446655440000",
            "name": "回應字串"
          }
        ]
      },
      "inbox": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "name": "回應字串",
        "channelType": "line",
        "unreadConversationsCount": 456,
        "signAuth": {
          "id": "550e8400-e29b-41d4-a716-446655440000",
          "signSource": "550e8400-e29b-41d4-a716-446655440000",
          "signParams": {
            "keycloak": {
              "clientId": "回應字串",
              "url": "回應字串",
              "realm": "回應字串"
            },
            "line": {
              "liffId": "回應字串"
            },
            "ad": {
              "saml": "回應字串"
            },
            "google": {
              "enabled": false
            }
          },
          "sourceIdAccessEnabled": false,
          "sourceIdVerifyMode": {},
          "sourceIdSignatureTtlMinutes": {}
        },
        "enableAnalysis": false
      },
      "chatbot": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "name": "回應範例名稱",
        "description": "回應範例描述"
      },
      "title": "回應字串",
      "lastMessage": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "type": "回應字串",
        "content": "回應字串",
        "createdAt": "回應字串"
      },
      "callRecord": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "status": "initiated",
        "direction": "inbound",
        "isActive": false,
        "canHangup": false
      },
      "lastMessageCreatedAt": "回應字串",
      "unreadMessagesCount": 456,
      "autoReplyEnabled": false,
      "isAutoReplyNow": false,
      "lastReadAt": "回應字串",
      "createdAt": "回應字串",
      "isGroupChat": false,
      "enableGroupMention": false,
      "queryMetadata": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "name": "回應範例名稱",
        "description": "回應範例描述"
      },
      "toolMask": null,
      "connectorMask": null,
      "thinkingConfig": null,
      "thinkingConfigSchema": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "name": "回應範例名稱",
        "description": "回應範例描述"
      },
      "effectiveThinkingConfig": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "name": "回應範例名稱",
        "description": "回應範例描述"
      },
      "llm": "550e8400-e29b-41d4-a716-446655440000",
      "deepResearchStatus": {},
      "deepResearchOutputFormat": "canvas",
      "ipAddress": "回應字串",
      "ipCountryCode": "回應字串",
      "ipRecordedAt": "回應字串",
      "assignee": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "name": "回應字串",
        "userId": "550e8400-e29b-41d4-a716-446655440000"
      },
      "status": "open",
      "tags": [
        {
          "id": "550e8400-e29b-41d4-a716-446655440000",
          "name": "回應字串",
          "memberIds": [
            "550e8400-e29b-41d4-a716-446655440000"
          ]
        }
      ],
      "progressStatus": "回應字串",
      "firstResponseAt": "回應字串",
      "queuedAt": "回應字串",
      "assignedAt": "回應字串",
      "transferReason": "回應字串",
      "satisfactionScore": 456,
      "satisfactionComment": "回應字串",
      "satisfactionSubmittedAt": "回應字串",
      "latestAnalysisSummary": "回應字串",
      "clientPlatform": {},
      "workingDirectory": "回應字串",
      "slideProjectId": "回應字串",
      "matchedField": "回應字串",
      "matchedSnippet": "回應字串",
      "matchedMessageId": "回應字串",
      "pinnedAt": "回應字串",
      "hasActiveBrowserSession": false,
      "callerOrganizationId": "回應字串"
    }
  ]
}
```

***

### 取得聯絡人最新對話 <a href="#undefined" id="undefined"></a>

GET `/api/v1/contacts/{id}/conversations/latest/`

#### 參數

| 參數名稱      | 必填 | 類型     | 說明                                                    |
| --------- | -- | ------ | ----------------------------------------------------- |
| `id`      | ✅  | string | A UUID string identifying this Contact.               |
| `inbox`   | ❌  | string | 按單一 inbox ID 過濾（UUID 格式）                              |
| `inboxes` | ❌  | string | 按多個 inbox IDs 過濾（逗號分隔，如：uuid1,uuid2 或使用多個 inboxes 參數） |
| `keyword` | ❌  | string | 搜尋對話中的訊息內容（不區分大小寫）                                    |

#### 程式碼範例

{% tabs %}
{% tab title="Shell/Bash" %}

```bash
# 呼叫 API 示例 (Shell)
curl -X GET "https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/conversations/latest/?inbox=example&inboxes=example&keyword=example" \
  -H "Authorization: Api-Key YOUR_API_KEY"

# 請確認在執行前替換 YOUR_API_KEY 並核對請求資料。
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const axios = require('axios');

// 設定請求標頭
const config = {
  headers: {
    'Authorization': 'Api-Key YOUR_API_KEY'
  }
};

axios.get("https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/conversations/latest/?inbox=example&inboxes=example&keyword=example", config)
  .then(response => {
    console.log('成功取得回應:');
    console.log(response.data);
  })
  .catch(error => {
    console.error('請求發生錯誤:');
    console.error(error.response?.data || error.message);
  });
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

url = "https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/conversations/latest/?inbox=example&inboxes=example&keyword=example"
headers = {
    "Authorization": "Api-Key YOUR_API_KEY"
}


response = requests.get(url, headers=headers)
try:
    print("成功取得回應:")
    print(response.json())
except Exception as e:
    print("請求發生錯誤:", e)
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();

try {
    $response = $client->get("https://api.maiagent.ai/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000/conversations/latest/?inbox=example&inboxes=example&keyword=example", [
        'headers' => [
            'Authorization' => 'Api-Key YOUR_API_KEY'
        ]
    ]);
    
    $data = json_decode($response->getBody(), true);
    echo "成功取得回應:\n";
    print_r($data);
} catch (Exception $e) {
    echo '請求發生錯誤: ' . $e->getMessage();
}
?>
```

{% endtab %}
{% endtabs %}

#### 回應內容

**狀態碼: 200**

**回應結構範例**

```typescript
{
  "id": string (uuid)
  "contact": { // 輕量級 Contact Serializer，用於 Conversation List view

只包含 List view 必要的欄位，移除 inboxes、mcp_credentials 和 api_credentials
以避免 N+1 查詢問題。email / phone_number / metadata 為 Contact 自身的純量欄位，
前端對話側欄需要顯示，無 N+1 成本。
  {
    "id": string (uuid)
    "name": string
    "avatar"?: string // Stores our own media as a relative storage key, or an external CDN URL as-is. (非必填)
    "email"?: // 可能有不同的類型 (非必填)
    string (email) // 非必填
    "phoneNumber"?: string // 非必填
    "metadata"?: object // 自訂的客戶資訊，會顯示在對話頁的客戶資訊區塊 (非必填)
    "sourceId"?: string // 非必填
    "tags": [
      {
        "id": string (uuid)
        "name": string
      }
    ]
  }
  }
  "inbox": {
  {
    "id": string (uuid)
    "name": string
    "channelType": string (enum: line, telegram, teams, web, messenger, instagram, email, whatsapp, slack, team_plus, line_works, viber) // * `line` - LINE
* `telegram` - Telegram
* `teams` - Teams
* `web` - Web
* `messenger` - Messenger
* `instagram` - Instagram
* `email` - Email
* `whatsapp` - WhatsApp
* `slack` - Slack
* `team_plus` - Team+
* `line_works` - LINE WORKS
* `viber` - Viber
    "unreadConversationsCount"?: integer // 非必填
    "signAuth"?:  // 非必填
    {
      "id": string (uuid)
      "signSource": string (uuid)
      "signParams": {
      {
        "keycloak": 
        {
          "clientId": string
          "url": string
          "realm": string
        }
        "line": 
        {
          "liffId": string
        }
        "ad": 
        {
          "saml": string
        }
        "google"?:  // 非必填
        {
          "enabled": boolean
        }
      }
      }
      "sourceIdAccessEnabled"?: boolean // When enabled, embedded visitors presenting a Source ID (verified per the verify mode below) may chat without going through the login flow. Disabled keeps every existing behavior unchanged. (非必填)
      "sourceIdVerifyMode"?:  // "Require signature verification": the embedding site must send an HMAC signature computed on its backend. "Source ID only": anyone knowing a Source ID can act as that contact; suitable only for testing or closed networks.

* `signature` - Require signature verification
* `raw` - Source ID only (非必填)
      {
      }
      "sourceIdSignatureTtlMinutes"?:  // How long a signature can be used to obtain the contact identity. Not a session lifetime: once exchanged, the session follows the existing WebChat mechanism.

* `1` - 1
* `5` - 5
* `15` - 15 (非必填)
      {
      }
    }
    "enableAnalysis"?: boolean // 非必填
  }
  }
  "chatbot": object // Chatbot (Agent) summary from the conversation's inbox, already eager-loaded.

``is_maigpt`` lets the client tell the default MaiGPT agent apart (icon, feature
gate) without comparing against the organization's ``maigpt_inbox`` id.
  "title": string
  "lastMessage"?: { // 非必填
  {
    "id": string (uuid)
    "type"?: string // 非必填
    "content"?: string // 非必填
    "createdAt": string (timestamp)
  }
  }
  "callRecord": 
  {
    "id": string (uuid)
    "status"?: string (enum: initiated, ringing, in-progress, completed, failed, busy, no-answer, canceled) // * `initiated` - Initiated
* `ringing` - Ringing
* `in-progress` - In Progress
* `completed` - Completed
* `failed` - Failed
* `busy` - Busy
* `no-answer` - No Answer
* `canceled` - Canceled (非必填)
    "direction": string (enum: inbound, outbound) // * `inbound` - Inbound
* `outbound` - Outbound
    "isActive": boolean
    "canHangup": boolean
  }
  "lastMessageCreatedAt": string (timestamp)
  "unreadMessagesCount": integer
  "autoReplyEnabled": boolean
  "isAutoReplyNow": boolean
  "lastReadAt": string (timestamp)
  "createdAt": string (timestamp)
  "isGroupChat": boolean
  "enableGroupMention"?: boolean // 非必填
  "queryMetadata"?: { // 查詢元資料，控制可查詢的知識範圍；詳見各端點說明 (非必填)
  {
    "knowledgeBases"?: [ // 可查詢的知識庫清單；空陣列或 null＝全部不可查（無權限），未提供＝不限制 (非必填)
      {
        "knowledgeBaseId": string (uuid) // 知識庫 ID
        "chatbotFileIds"?: [ // 檔案 ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
          string (uuid)
        ]
        "knowledgeBaseFileIds"?: [ // 檔案 ID 清單（chatbotFileIds 的新名稱；兩者皆提供時以本欄位為準） (非必填)
          string (uuid)
        ]
        "faqIds"?: [ // FAQ ID 清單（依 hasUserSelectedAll 決定為排除或僅選取） (非必填)
          string (uuid)
        ]
        "hasUserSelectedAll"?: boolean // true＝選取知識庫全部內容並排除清單中的項目；false＝僅選取清單中的項目 (非必填)
      }
    ]
    "labelRelations"?: { // 標籤過濾條件；conditions 為空陣列＝不做標籤過濾（並非無權限）。必須與 knowledgeBases 一併提供——單獨提供時知識庫檢索不會套用標籤過濾（等同不限制） (非必填)
    {
      "operator": string (enum: AND, OR) // 標籤條件的組合方式
      "conditions"?: [ // 標籤條件清單，支援巢狀 operator/conditions 組合 (非必填)
        object
      ]
    }
    }
  }
  }
  "toolMask"?: object // 記錄每個工具的啟用/停用狀態 {tool_id: bool} (非必填)
  "connectorMask"?: object // 記錄每個連接器的啟用/停用狀態 {connector_id: bool} (非必填)
  "thinkingConfig"?: object // None=未設定(使用 chatbot 設定), {}=明確關閉, {...}=自訂覆寫 (非必填)
  "thinkingConfigSchema": object
  "effectiveThinkingConfig": object // Return the effective thinking config after applying the priority chain:
conversation override > chatbot config > LLM metadata.

This allows the frontend to display the actual thinking config in use,
even when the conversation has no explicit override.

Returns None when nothing is configured at any level, so the frontend
can distinguish "Default" (None = use model/assistant default) from
"Off" ({} = explicitly disabled). Collapsing the unconfigured case to
{} would make a fresh conversation display as Off instead of Default.
  "llm": string (uuid)
  "deepResearchStatus":  // Status of deep research for this conversation

* `not_used` - Not Used
* `started` - Started
* `running` - Running
* `completed` - Completed
* `failed` - Failed
  {
  }
  "deepResearchOutputFormat": // 可能有不同的類型
  string (enum: canvas, chat, file) // Chosen delivery form for the finished report. Set only when the user clicks a format in the pre-research choice card; reset to NULL each time Deep Research is (re-)armed. NULL means no explicit choice (or a plan-skipping request) and falls back to Canvas at render time, but stays distinct from an explicit canvas pick so the frontend can lock the card only after a real selection. To roll back to fixed-Canvas behavior, force this to NULL/canvas — no redeploy needed.

* `canvas` - Canvas
* `chat` - Chat reply
* `file` - Downloadable file
  "ipAddress": string
  "ipCountryCode": string
  "ipRecordedAt": string (timestamp)
  "assignee": 
  {
    "id": string (uuid)
    "name": string
    "userId": string (uuid)
  }
  "status"?: string (enum: open, resolved, queued) // * `open` - Open
* `resolved` - Resolved
* `queued` - Queued (非必填)
  "tags": [
    {
      "id": string (uuid)
      "name": string
      "memberIds"?: [ // 非必填
        string (uuid)
      ]
    }
  ]
  "progressStatus": string
  "firstResponseAt"?: string (timestamp) // 非必填
  "queuedAt"?: string (timestamp) // 非必填
  "assignedAt"?: string (timestamp) // 非必填
  "transferReason"?: string // 非必填
  "satisfactionScore": integer // Conversation satisfaction rating on a 5-point scale (1=very dissatisfied, 5=very satisfied)
  "satisfactionComment": string
  "satisfactionSubmittedAt": string (timestamp)
  "latestAnalysisSummary": string // The conversation's current analysis summary (its active summary revision).

Reads the `latest_analysis_summary` annotation added by `setup_eager_loading`
to avoid an N+1 query. All read paths (list / retrieve / create) eager-load,
so the annotation is present; it falls back to '' only for instances built
outside `setup_eager_loading`.
  "clientPlatform":  // Client platform that created this conversation (web, desktop)

* `web` - Web
* `desktop` - Desktop
  {
  }
  "workingDirectory": string // Absolute path of the local folder bound to a desktop conversation. Only set for desktop conversations; null for web conversations.
  "slideProjectId": string
  "matchedField": string // Cached per instance: ``get_matched_message_id`` / ``get_matched_snippet``
both read this, so resolving it once avoids recomputing the keyword and
title-match logic three times per serialized conversation.
  "matchedSnippet": string // Keyword-centred excerpt of the matched message, with ellipses.

Reads the ``matched_message_content`` annotation added by
``ConversationViewSet._annotate_keyword_match``; no extra query.
  "matchedMessageId": string
  "pinnedAt": string (timestamp) // When the conversation was pinned. Null means unpinned.
  "hasActiveBrowserSession": boolean // Whether a browser_use session snapshot exists to resume.

Lets the frontend know it should proactively re-request the browser
panel (emit ``browser:start``) after a page reload, instead of only
ever showing the panel when a live ``browser:frame`` push happens to
arrive first.
  "callerOrganizationId": string // Bound caller organization (stamped at conversation start); null when unbound
}
```

**回應範例值**

```json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "contact": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "回應字串",
    "avatar": "回應字串",
    "email": "response@example.com",
    "phoneNumber": "回應字串",
    "metadata": null,
    "sourceId": "回應字串",
    "tags": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "name": "回應字串"
      }
    ]
  },
  "inbox": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "回應字串",
    "channelType": "line",
    "unreadConversationsCount": 456,
    "signAuth": {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "signSource": "550e8400-e29b-41d4-a716-446655440000",
      "signParams": {
        "keycloak": {
          "clientId": "回應字串",
          "url": "回應字串",
          "realm": "回應字串"
        },
        "line": {
          "liffId": "回應字串"
        },
        "ad": {
          "saml": "回應字串"
        },
        "google": {
          "enabled": false
        }
      },
      "sourceIdAccessEnabled": false,
      "sourceIdVerifyMode": {},
      "sourceIdSignatureTtlMinutes": {}
    },
    "enableAnalysis": false
  },
  "chatbot": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "回應範例名稱",
    "description": "回應範例描述"
  },
  "title": "回應字串",
  "lastMessage": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "type": "回應字串",
    "content": "回應字串",
    "createdAt": "回應字串"
  },
  "callRecord": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "initiated",
    "direction": "inbound",
    "isActive": false,
    "canHangup": false
  },
  "lastMessageCreatedAt": "回應字串",
  "unreadMessagesCount": 456,
  "autoReplyEnabled": false,
  "isAutoReplyNow": false,
  "lastReadAt": "回應字串",
  "createdAt": "回應字串",
  "isGroupChat": false,
  "enableGroupMention": false,
  "queryMetadata": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "回應範例名稱",
    "description": "回應範例描述"
  },
  "toolMask": null,
  "connectorMask": null,
  "thinkingConfig": null,
  "thinkingConfigSchema": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "回應範例名稱",
    "description": "回應範例描述"
  },
  "effectiveThinkingConfig": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "回應範例名稱",
    "description": "回應範例描述"
  },
  "llm": "550e8400-e29b-41d4-a716-446655440000",
  "deepResearchStatus": {},
  "deepResearchOutputFormat": "canvas",
  "ipAddress": "回應字串",
  "ipCountryCode": "回應字串",
  "ipRecordedAt": "回應字串",
  "assignee": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "回應字串",
    "userId": "550e8400-e29b-41d4-a716-446655440000"
  },
  "status": "open",
  "tags": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "回應字串",
      "memberIds": [
        "550e8400-e29b-41d4-a716-446655440000"
      ]
    }
  ],
  "progressStatus": "回應字串",
  "firstResponseAt": "回應字串",
  "queuedAt": "回應字串",
  "assignedAt": "回應字串",
  "transferReason": "回應字串",
  "satisfactionScore": 456,
  "satisfactionComment": "回應字串",
  "satisfactionSubmittedAt": "回應字串",
  "latestAnalysisSummary": "回應字串",
  "clientPlatform": {},
  "workingDirectory": "回應字串",
  "slideProjectId": "回應字串",
  "matchedField": "回應字串",
  "matchedSnippet": "回應字串",
  "matchedMessageId": "回應字串",
  "pinnedAt": "回應字串",
  "hasActiveBrowserSession": false,
  "callerOrganizationId": "回應字串"
}
```

**狀態碼: 404 - No response body**

***

### 群發訊息 <a href="#undefined" id="undefined"></a>

POST `/api/v1/contacts/broadcast-message/`

#### 請求內容

**請求參數**

| 欄位                | 類型             | 必填 | 說明                                                |
| ----------------- | -------------- | -- | ------------------------------------------------- |
| contactIds        | array\[string] | 否  | \[正向指定模式] 要發送訊息的 contact ID 列表                    |
| inboxId           | string (uuid)  | 否  | \[反向排除/全部發送模式] Inbox ID，會發送給該 inbox 下的所有 contacts |
| excludeContactIds | array\[string] | 否  | \[反向排除模式] 要排除的 contact ID 列表，需配合 inbox\_id 使用     |
| message           | string         | 是  | 要發送的訊息內容                                          |

**請求結構範例**

```typescript
{
  "contactIds"?: [ // [正向指定模式] 要發送訊息的 contact ID 列表 (非必填)
    string (uuid)
  ]
  "inboxId"?: string (uuid) // [反向排除/全部發送模式] Inbox ID，會發送給該 inbox 下的所有 contacts (非必填)
  "excludeContactIds"?: [ // [反向排除模式] 要排除的 contact ID 列表，需配合 inbox_id 使用 (非必填)
    string (uuid)
  ]
  "message": string // 要發送的訊息內容
}
```

**請求範例值**

```json
{
  "contactIds": [
    "550e8400-e29b-41d4-a716-446655440000"
  ],
  "inboxId": "550e8400-e29b-41d4-a716-446655440000",
  "excludeContactIds": [
    "550e8400-e29b-41d4-a716-446655440000"
  ],
  "message": "這是一個範例訊息"
}
```

#### 程式碼範例

{% tabs %}
{% tab title="Shell/Bash" %}

```bash
# 呼叫 API 示例 (Shell)
curl -X POST "https://api.maiagent.ai/api/v1/contacts/broadcast-message/" \
  -H "Authorization: Api-Key YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contactIds": [
      "550e8400-e29b-41d4-a716-446655440000"
    ],
    "inboxId": "550e8400-e29b-41d4-a716-446655440000",
    "excludeContactIds": [
      "550e8400-e29b-41d4-a716-446655440000"
    ],
    "message": "這是一個範例訊息"
  }'

# 請確認在執行前替換 YOUR_API_KEY 並核對請求資料。
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const axios = require('axios');

// 設定請求標頭
const config = {
  headers: {
    'Authorization': 'Api-Key YOUR_API_KEY',
    'Content-Type': 'application/json'
  }
};

// 請求內容 (payload)
const data = {
    "contactIds": [
      "550e8400-e29b-41d4-a716-446655440000"
    ],
    "inboxId": "550e8400-e29b-41d4-a716-446655440000",
    "excludeContactIds": [
      "550e8400-e29b-41d4-a716-446655440000"
    ],
    "message": "這是一個範例訊息"
  };

axios.post("https://api.maiagent.ai/api/v1/contacts/broadcast-message/", data, config)
  .then(response => {
    console.log('成功取得回應:');
    console.log(response.data);
  })
  .catch(error => {
    console.error('請求發生錯誤:');
    console.error(error.response?.data || error.message);
  });
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

url = "https://api.maiagent.ai/api/v1/contacts/broadcast-message/"
headers = {
    "Authorization": "Api-Key YOUR_API_KEY",
    "Content-Type": "application/json"
}

# 請求內容 (payload)
data = {
      "contactIds": [
        "550e8400-e29b-41d4-a716-446655440000"
      ],
      "inboxId": "550e8400-e29b-41d4-a716-446655440000",
      "excludeContactIds": [
        "550e8400-e29b-41d4-a716-446655440000"
      ],
      "message": "這是一個範例訊息"
    }

response = requests.post(url, json=data, headers=headers)
try:
    print("成功取得回應:")
    print(response.json())
except Exception as e:
    print("請求發生錯誤:", e)
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();

try {
    $response = $client->post("https://api.maiagent.ai/api/v1/contacts/broadcast-message/", [
        'headers' => [
            'Authorization' => 'Api-Key YOUR_API_KEY',
            'Content-Type' => 'application/json'
        ],
        'json' => {
            "contactIds": [
                "550e8400-e29b-41d4-a716-446655440000"
            ],
            "inboxId": "550e8400-e29b-41d4-a716-446655440000",
            "excludeContactIds": [
                "550e8400-e29b-41d4-a716-446655440000"
            ],
            "message": "這是一個範例訊息"
        }
    ]);
    
    $data = json_decode($response->getBody(), true);
    echo "成功取得回應:\n";
    print_r($data);
} catch (Exception $e) {
    echo '請求發生錯誤: ' . $e->getMessage();
}
?>
```

{% endtab %}
{% endtabs %}

#### 回應內容

**狀態碼: 200**

**回應結構範例**

```typescript
{
  "results"?: [ // 非必填
    {
      "contact_id"?: string (uuid) // 非必填
      "conversation_id"?: string (uuid) // 非必填
      "message_id"?: string (uuid) // 非必填
      "status"?: string // 非必填
    }
  ]
  "errors"?: [ // 非必填
    {
      "contact_id"?: string (uuid) // 非必填
      "error"?: string // 非必填
    }
  ]
  "total_contacts"?: integer // 非必填
  "success_count"?: integer // 非必填
  "error_count"?: integer // 非必填
}
```

**回應範例值**

```json
{
  "results": [
    {
      "contact_id": "550e8400-e29b-41d4-a716-446655440000",
      "conversation_id": "550e8400-e29b-41d4-a716-446655440000",
      "message_id": "550e8400-e29b-41d4-a716-446655440000",
      "status": "success"
    }
  ],
  "errors": [
    {
      "contact_id": "550e8400-e29b-41d4-a716-446655440000",
      "error": "回應字串"
    }
  ],
  "total_contacts": 456,
  "success_count": 456,
  "error_count": 456
}
```

***


---

# 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/api/api-reference/lian-luo-ren.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.
