WhatsApp 聊天跨標籤交接:安全的 API 操作流程
透過 UnifyPort 將 WhatsApp 聊天從一個工作流程標籤移至另一個,需要兩次成員關係操作:先新增目標標籤,確認結果,再移除來源標籤。公開文件沒有承諾原子轉移。請保留無關標籤,讓未完成的交接持續可見;不要刪除整個標籤,也不要把請求逾時當作「一定沒有變更」。
重點
action: "remove"是替選定對話移除標籤;刪除標籤是另一項操作。- 多個標籤可以並存,不能強制唯一負責人或唯一工作階段。
- 先新增再移除有助於維持可見性,但中途會暫時保留兩個標籤。
- 正式的指派紀錄與交接進度應存於應用程式,不宜僅從標籤推斷。
定義交接,不是取代全部標籤
WhatsApp 的標籤說明介紹以標籤整理聊天,以及為同一聊天套用多個標籤。頁面也指出標籤正逐步轉換為清單。這項介面用語變化不代表 UnifyPort 的 label_id 欄位已更名,也不保證應用程式內每種清單都有對應 API。
以下是假設情境:聊天已有「待處理」與「VIP」,客服希望移至「處理中」。預期操作是新增「處理中」、移除「待處理」,保留「VIP」,而非將全部標籤替換成「處理中」。
六月 API 更新介紹過標籤端點。交接時,請先分清操作對象:
| 意圖 | 操作 | 對象 |
|---|---|---|
| 建立或重新命名分類 | 建立或更新標籤 | 標籤定義 |
| 新增目標標籤 | 成員關係 action: "add" | 該標籤下選定的對話 |
| 移除來源標籤 | 成員關係 action: "remove" | 該標籤下選定的對話 |
| 停用一個分類 | 刪除標籤 | 標籤本身,不是單一對話的歸屬 |
不要用刪除標籤代替替單一對話移除標籤;其他聊天可能還在使用這個分類。
準備兩次操作
在選定訊息帳號下讀取標籤目錄,取得來源及目標 ID,並完成分頁。名稱是顯示文字,不是穩定的識別鍵。若需要建立目標標籤,使用建立或更新標籤,保留回傳的 data.id。
在同一帳號下確認聊天的 conversation_id。不要把標籤名稱、聯絡人顯示名稱或訊息 ID 當作對話 ID。先查看操作支援矩陣:這些標籤操作目前支援 whatsapp,不支援 LINE、Telegram、Zalo,亦不支援獨立的 whatsapp-protocol 渠道。
標籤成員關係參考定義 POST /v1/accounts/{account_id}/conversations/labels,請求包含 label_id、action 及非空的 conversation_ids 陣列。
以下伺服器端 JavaScript 函式只執行一次操作,不會自動完成整個交接。請傳入後端實際選取的 ID 與安全保存的 API key。這是示意程式碼,不是已驗證的正式環境用戶端。
async function changeLabelMembership({
apiKey, accountId, labelId, conversationIds, action
}) {
const validId = value => typeof value === 'string' && value.trim() !== '';
if (!validId(accountId) || !validId(labelId) ||
!Array.isArray(conversationIds) || conversationIds.length === 0 ||
!conversationIds.every(validId) || !['add', 'remove'].includes(action)) {
throw new Error('Select an account, label, conversations, and action');
}
const response = await fetch(
`https://api.unifyport.ai/v1/accounts/${encodeURIComponent(accountId)}/conversations/labels`,
{
method: 'POST',
headers: { 'X-Api-Key': apiKey, 'Content-Type': 'application/json' },
body: JSON.stringify({
label_id: labelId,
action,
conversation_ids: [...new Set(conversationIds)]
})
}
);
const result = await response.json();
return { httpStatus: response.status, result };
}
第一次呼叫使用目標 ID 與 add;後續呼叫改用來源 ID 與 remove,對話保持相同。在本地拒絕來源和目標 ID 相同的交接。請檢查 HTTP 狀態及回應內容;fetch 正常回傳未必代表成功。文件中的成功回應會標識受影響的 label_id、action 和 conversation_ids。
在新增與移除之間加入確認關卡
以下是應用程式設計建議,不是 UnifyPort 提供的交易保證:
- 在本地儲存預定帳號、對話、來源及目標標籤,確認操作人員有權變更指派。
- 新增目標標籤,記錄回應與
request_id,不記錄 API key。 - 使用明確的
label_id呼叫對話清單,讀取目標標籤檢視。確認選定聊天出現後,再移除來源標籤。 - 只移除來源成員關係,保留 VIP 等獨立標籤。
- 核對兩個檢視;觀察結果不符預期時,顯示尚未完成的工作。
不要用未指定標籤的清單驗證目標。文件規定,WhatsApp 省略 label_id 時只回傳特別關注的對話。聊天缺漏與標籤篩選排查說明了這項邊界與分頁方式。第一頁找不到某聊天,不代表它不存在;讀取失敗也不等於空結果。即時分頁讀取沒有不可變快照的保證。
| 觀察到的歸屬 | 本次交接的解讀 | 建議動作 |
|---|---|---|
| 只有來源 | 尚未觀察到目標 | 保留來源,調查新增操作 |
| 來源與目標皆有 | 中間狀態,或其他編輯者的變更 | 確認目前意圖,再移除來源 |
| 只有目標 | 已觀察到預期歸屬模式 | 本地指派仍一致時記錄完成 |
| 皆無,或讀取不完整 | 狀態未釐清 | 保留本地工作並調查,不猜測完成 |
復原時避免重送過期意圖
在應用程式中循序處理同一對話的變更,送出前拒絕過期的佇列工作。如果其他客服已修改指派,不要盲目完成舊交接。本地循序處理無法鎖住所有連結的用戶端,因此必須核對外部變更,不能宣稱獨占控制。
新增逾時時,保留來源,先查看目標再決定下一步。移除結果不確定時,先確認兩個檢視再考慮重送。不要自動移除目標來「回復」:其他人可能已經依賴該標籤。
公開參考未承諾兩次呼叫之間的原子性、整批全部成功或失敗、版本前置條件,或專用的標籤變更 webhook。批次處理請逐對話保留進度,不要把整批當成一個已完成的指派。set_label_members_failed 對應文件所述的伺服器端或上游失敗;unsupported_by_provider 是功能支援邊界,不應無限重試。
常見問題
新增標籤會自動移除舊標籤嗎?
不會。API 分別提供新增與移除動作,請獨立處理各個標籤成員關係。
標籤能強制只有一位客服負責嗎?
此契約沒有這種保證。負責人與權限應存於應用程式,標籤只是渠道端的投影。
conversation.updated 能確認交接嗎?
不要如此假設。文件中的設定包括靜音、封存、置頂及已讀狀態,並非保證提供標籤歸屬回執。
這是 WhatsApp Cloud API 的官方操作嗎?
不是。這些是 UnifyPort 面向已連結帳號的非官方介面端點。WhatsApp 應用程式說明僅解釋使用者端概念,不定義這份 API 契約。
下一步與參考資料
先閱讀為對話新增或移除標籤。在受控帳號測試正常交接、新增失敗、移除逾時、競爭編輯、分頁及保留無關標籤,再啟用批次轉移。這些是建議驗收項目,不是已執行的測試成果。
資料核對日期:2026-10-14。
讓訊息接入變成一條穩定的產品管線。
先用統一 API 跑通傳送,再用標準事件把所有入站訊息接回業務系統。