← 所有文章
教程

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 的事务保证:

  1. 在本地保存目标账号、会话、来源及目标标签,确认操作员有权修改该工作流分配。
  2. 添加目标标签,记录响应和 request_id,不记录 API key。
  3. 使用显式 label_id 调用会话列表,读取目标标签视图。确认选定会话已出现,再移除来源标签。
  4. 只移除来源成员关系,保留 VIP 等独立标签。
  5. 复核两个视图;观察结果与预期状态不符时,显示尚未完成的工作。

不要用不带标签筛选的列表验证目标。文档规定,WhatsApp 省略 label_id 时返回特别关注会话。会话缺失与标签筛选排查解释了这一边界和分页规则。第一页没有某个会话,不等于它不存在;读取失败也不是空结果。实时分页查询没有不可变快照保证。

观察到的标签归属对本次交接的含义建议处理
只有来源尚未观察到目标保留来源,调查添加操作
来源和目标都存在中间状态,或其他编辑者的变更确认当前意图,再移除来源
只有目标已观察到预期归属模式本地分配仍一致时记录完成
都没有,或读取不完整状态未解决保留本地工作并调查,不猜测完成

恢复时不要重放过期意图

在应用中串行处理同一会话的变更,发出请求前拒绝过期任务。如果另一位客服已经更改分配,不要盲目完成旧交接。本地串行化不能锁住所有关联客户端,因此要核对外部变更,而不是声称独占控制。

添加超时后,保留来源,先检查目标再决定下一步。移除结果不确定时,先检查两个视图再考虑重复请求。不要自动移除目标来“回滚”:其他操作员可能已经依赖该标签。

公开参考没有承诺两次调用之间的原子性、整批全成全败、版本前置条件或专门的标签变更 webhook。批量处理时,逐会话保存进度,不要将整批请求当作一个已经完成的分配。set_label_members_failed 表示文档所述的服务端或上游失败;unsupported_by_provider 是能力边界,不是无限重试的理由。

常见问题

添加新标签会自动移除旧标签吗?

不会。API 提供明确的添加和移除动作,应独立处理每个标签成员关系。

标签能保证只有一个客服负责人吗?

此契约不提供这种保证。在应用中保存负责人和权限,让标签作为渠道侧的展示投影。

conversation.updated 会确认交接完成吗?

不要这样假设。该事件记录的设置包括静音、归档、置顶和已读状态,并未承诺标签成员关系回执。

这是 WhatsApp Cloud API 官方操作吗?

不是。这些是面向已连接账号的 UnifyPort 非官方接口端点。WhatsApp 应用帮助只解释用户侧概念,不定义此 API 契约。

下一步与参考资料

从为会话添加或移除标签开始。在受控账号中测试正常交接、目标添加失败、移除超时、并发编辑、分页和无关标签保留,再开放批量操作。这些是建议的验收项,不是已执行的测试结果。

资料核对日期:2026-10-14。

UnifyPort API

让消息接入变成一条稳定的产品管线。

先用统一 API 跑通发送,再用标准事件把所有入站消息接回业务系统。