TikTok 数据可携带不等于实时私信:搭建客服真正需要的入站队列
TikTok 的开发者接口越来越清晰,但接口文档更清晰,并不代表它刚好解决客服团队眼前的问题。
6 月 4 日,TikTok 在 Data Portability API changelog 中说明,Data Types 文档已更新,用来反映当前支持的数据类别和字段。Data Portability API 产品页说明,这个 API 面向欧洲经济区和英国的 TikTok 用户,允许用户授权把自己的信息传输到另一个应用。当前 data types 页面 也列出了 Direct Messages 作为可导出的类别,字段包括日期、发送方和内容。
这对数据可携带、归档、备份和合规流程有价值。但它不是实时客服收件箱。
如果你的团队做 TikTok Shop、达人营销或直播销售,真正需要的是另一件事:每一条新私信都应该进入队列,被去重,触发 CRM 查询,然后分配给同事或 AI 助手。用户授权的历史导出无法提供这个事件循环。带签名的入站 webhook 可以。
先定义集成要完成的工作
选 API 之前,先把工作流写成普通语言:
- 客户发送一条 TikTok 私信。
- 后端在几秒内收到这条消息。
- 投递带签名,服务端可以确认来源可信。
- 消息被存储,因为错过的事件之后无法补回。
- 同一个队列以后还能接收 WhatsApp、LINE、Zalo、Telegram 或 X 消息。
TikTok Data Portability API 不是围绕这个顺序设计的。它是用户授权的数据传输产品。申请方需要服务欧洲经济区或英国用户,通过隐私和安全审核,并请求明确的数据范围。它的数据模型围绕导出展开:帖子和资料、活动、私信或完整归档。
这不是客服需要的时间模型。客服问的不是“这个用户能不能导出昨天的归档”,而是“十秒前来的那条消息,我们能不能马上处理”。
UnifyPort 的 webhook 结构
UnifyPort 的 TikTok 非官方接口面向第二种模型。你连接 TikTok 账号,注册 webhook endpoint,并订阅 message.received。客户消息到达后,UnifyPort 会向你的后端发送一个标准事件包:
{
"id": "evt_7a4d2c91b6",
"type": "message.received",
"provider": "tiktok",
"account_id": "acc_8c21d0",
"occurred_at": "2026-07-05T03:18:42Z",
"data": {
"conversation": { "id": "tt_conv_9172", "type": "user", "title": "Mai Nguyen" },
"sender": { "id": "tt_user_4839", "name": "Mai Nguyen", "type": "user" },
"message": {
"id": "tt_msg_20260705_001",
"type": "text",
"text": "今晚直播前黑色托特包还有货吗?",
"direction": "inbound",
"sent_at": "2026-07-05T03:18:41Z"
}
}
}
关键是这个事件包:id、type、provider、account_id、occurred_at 和 data。同一个处理器今天可以处理 provider: "tiktok",明天可以处理 provider: "zalo"。路由层只在平台行为确实不同时再分支。
先注册 endpoint
连接队列之前,先创建 webhook。endpoint 会保存 URL、订阅事件、签名状态和重试策略。设置 signing_secret 后,每次投递都会带上 X-Device-Timestamp 和 X-Device-Signature。
curl -X POST https://api.unifyport.ai/v1/webhook-endpoints \
-H "X-Api-Key: <YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhook",
"status": "active",
"subscribed_events": ["message.received"],
"signing_secret": "<WEBHOOK_SIGNING_SECRET>"
}'
UnifyPort 使用 HMAC-SHA256 对时间戳、一个点和原始请求体进行签名。必须在解析 JSON 前用原始字节校验。不要先解析再重新序列化,因为那会改变被校验的字节。
import crypto from "crypto";
import express from "express";
const app = express();
const signingSecret = process.env.WEBHOOK_SIGNING_SECRET;
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
const timestamp = req.get("X-Device-Timestamp");
const signature = req.get("X-Device-Signature");
const hmac = crypto.createHmac("sha256", signingSecret);
hmac.update(timestamp);
hmac.update(".");
hmac.update(req.body);
const expected = hmac.digest("hex");
const valid =
signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
if (!valid) {
res.status(401).end();
return;
}
const event = JSON.parse(req.body.toString("utf8"));
if (event.type === "message.received") {
console.log(event.provider, event.data.sender.id, event.data.message.text);
}
res.status(200).end();
});
app.listen(3000);
这已经足够作为入站边界。生产环境可以把事件写入队列,但边界不变:带签名的投递进来,校验后的事件出去。
先存储,再路由
UnifyPort 文档明确说明,webhook 事件是入站流量的唯一记录。没有消息读取 API,也没有错过 payload 后的回补路径。因此队列设计要先围绕存储展开。
第一步写入应按 id 保存事件,同时保存原始请求体或解析后的 JSON、provider、account ID 和 occurred_at。写入成功后,再异步路由:
TikTok message
-> UnifyPort message.received webhook
-> Signature verification
-> Event store keyed by id
-> Routing queue
-> CRM lookup, Slack alert, helpdesk ticket, or AI triage
这里也能看清 Data Portability API 应该放在什么位置。导出适合用户授权的数据迁移。实时客服队列适合运营处理。两者可以共存,但不能混为一谈。
只有需要回复时再加入发送流程
有些团队只需要入站分流。有些团队希望队列在人工或 AI 助手决策后生成回复。把回复作为明确的第二步。
发送消息时,UnifyPort 使用 POST /v1/messages,并传入账号、接收人和标准消息体。入站事件会给你 provider、account、sender、conversation 和 message text;回复流程再决定是否发送。
curl -X POST https://api.unifyport.ai/v1/messages \
-H "X-Api-Key: <YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"account_id": "acc_8c21d0",
"to": { "id": "tt_user_4839", "type": "user" },
"message": { "type": "text", "text": "黑色托特包还有货,可以在今晚直播前下单。" }
}'
入站和出站应该在代码中保持分离。第一条路径负责捕获和保存客户消息。第二条路径只在业务逻辑决定后发送响应。
为什么 2026 年 7 月要重新区分这件事
TikTok 6 月 4 日的文档更新提醒我们:平台 API 往往只服务某个政策或产品面。Data portability 是用户控制的数据传输。Content Posting 是发布。Display API 是创作者内容展示。这些名字都不自动等于“实时客服私信收件箱”。
小团队常见的时间浪费,是把每一个新文档化的 API 类别都当成客服事件流。更稳的做法是先命名工作流,再选择匹配它时间模型的接口。
如果工作流是导出,就用导出工具。如果工作流是客服,就用 webhook。如果工作流今天覆盖 TikTok、下个月还要覆盖 Zalo 或 LINE,就从一开始保持标准化事件包。
这就是实际分工:TikTok Data Portability 帮用户移动自己的数据;UnifyPort 帮你的客服系统在消息到达时收到它们。