TikTok Data Portability không phải luồng tin nhắn trực tiếp: xây hàng đợi inbound cho đội hỗ trợ
Bề mặt API dành cho nhà phát triển của TikTok ngày càng rõ hơn, nhưng tài liệu rõ hơn không có nghĩa là nó giải quyết đúng bài toán vận hành của đội hỗ trợ.
Ngày 4 tháng 6, TikTok ghi trong Data Portability API changelog rằng tài liệu Data Types đã được cập nhật để phản ánh các danh mục và trường hiện được hỗ trợ. Trang sản phẩm Data Portability API nói API này cho phép người dùng TikTok ở Khu vực Kinh tế Châu Âu và Vương quốc Anh ủy quyền chuyển thông tin của họ sang ứng dụng khác. Trang data types hiện cũng liệt kê Direct Messages là một danh mục xuất dữ liệu, với các trường như ngày, người gửi và nội dung.
Điều đó hữu ích cho data portability, lưu trữ, sao lưu và quy trình tuân thủ. Nhưng nó không phải inbox chăm sóc khách hàng theo thời gian thực.
Nếu đội của bạn bán hàng qua TikTok Shop, chạy chiến dịch creator hoặc nhận câu hỏi trong livestream, nhu cầu vận hành là tức thời: mỗi tin nhắn mới phải vào hàng đợi, được khử trùng lặp, kích hoạt tra cứu CRM, rồi chuyển cho nhân sự hoặc AI assistant. Một bản xuất lịch sử do người dùng ủy quyền không tạo được vòng lặp sự kiện đó. Một inbound webhook có chữ ký thì có.
Trước tiên hãy định nghĩa việc tích hợp cần làm
Trước khi chọn API, hãy viết workflow bằng ngôn ngữ đơn giản:
- Khách hàng gửi tin nhắn trực tiếp trên TikTok.
- Backend nhận được tin nhắn trong vài giây.
- Delivery có chữ ký để server tin được nguồn gửi.
- Tin nhắn được lưu lại vì event bỏ lỡ không thể backfill sau.
- Cùng hàng đợi đó sau này có thể nhận WhatsApp, LINE, Zalo, Telegram hoặc X.
TikTok Data Portability API không được thiết kế cho chuỗi đó. Đây là sản phẩm chuyển dữ liệu dựa trên sự đồng ý của người dùng. Ứng viên cần phục vụ người dùng ở EEA hoặc UK, vượt qua đánh giá privacy và security, rồi xin các data scope cụ thể. Mô hình dữ liệu xoay quanh export: posts and profile, activity, direct messages hoặc full archive.
Đó là mô hình thời gian sai cho support. Support không hỏi “người dùng này có xuất được archive hôm qua không”. Support hỏi “tin nhắn vừa đến mười giây trước có được xử lý ngay không”.
Hình dạng webhook của UnifyPort
TikTok unofficial interface của UnifyPort phục vụ mô hình thứ hai. Bạn kết nối tài khoản TikTok, đăng ký webhook endpoint và subscribe message.received. Khi khách hàng gửi tin nhắn, UnifyPort gửi một envelope chuẩn về backend:
{
"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": "Túi tote màu đen còn hàng trước buổi live tối nay không?",
"direction": "inbound",
"sent_at": "2026-07-05T03:18:41Z"
}
}
}
Điểm quan trọng là envelope: id, type, provider, account_id, occurred_at và data. Cùng một handler hôm nay xử lý provider: "tiktok", ngày mai xử lý provider: "zalo". Với thị trường Việt Nam, Zalo và WhatsApp thường cùng nằm trong support stack, nên giữ schema thống nhất ngay từ đầu sẽ giảm rất nhiều công việc sau này.
Đăng ký endpoint trước
Trước khi nối vào hàng đợi, hãy tạo webhook. Endpoint lưu URL, subscribed events, trạng thái chữ ký và retry policy. Dùng signing_secret để mỗi delivery có X-Device-Timestamp và 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 ký timestamp, một dấu chấm và raw request body bằng HMAC-SHA256. Hãy verify trên raw bytes trước khi parse JSON. Đừng parse rồi serialize lại body trước khi kiểm tra, vì bytes sẽ thay đổi.
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);
Như vậy là đủ cho lớp intake. Production có thể đẩy event vào queue, nhưng ranh giới vẫn vậy: signed delivery đi vào, verified event đi ra.
Lưu trước, route sau
Tài liệu UnifyPort nói rõ webhook events là bản ghi duy nhất của inbound traffic. Không có message read API và không có đường backfill payload đã bỏ lỡ. Vì vậy queue nên được thiết kế với bước lưu trữ đầu tiên.
Write đầu tiên nên lưu event theo id, cùng raw body hoặc parsed JSON, provider, account ID và occurred_at. Khi write thành công, routing có thể chạy bất đồng bộ:
TikTok message
-> UnifyPort message.received webhook
-> Signature verification
-> Event store keyed by id
-> Routing queue
-> CRM lookup, Slack alert, helpdesk ticket, or AI triage
Đây cũng là nơi Data Portability API nằm đúng trong mô hình. Export hữu ích cho chuyển dữ liệu có sự đồng ý của người dùng. Live support queue hữu ích cho vận hành. Hai thứ có thể cùng tồn tại, nhưng không nên bị nhầm với nhau.
Chỉ thêm reply khi workflow cần
Một số đội chỉ cần inbound triage. Một số đội muốn queue tạo reply sau khi nhân sự hoặc AI assistant quyết định nội dung. Hãy giữ reply là bước thứ hai rõ ràng.
Để gửi outbound, UnifyPort dùng POST /v1/messages với account, recipient và message body đã chuẩn hóa. Inbound event cung cấp provider, account, sender, conversation và message text; workflow reply quyết định có gửi lại hay không.
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": "Có, túi tote màu đen vẫn còn hàng." }
}'
Inbound và outbound nên tách riêng trong codebase. Đường đầu tiên bắt và lưu tin nhắn khách gửi. Đường thứ hai chỉ gửi phản hồi sau khi business logic đưa ra quyết định.
Vì sao điều này quan trọng trong tháng 7 năm 2026
Cập nhật tài liệu ngày 4 tháng 6 của TikTok nhắc rằng platform APIs thường phục vụ một policy surface hoặc product surface cụ thể. Data portability là chuyển dữ liệu do người dùng kiểm soát. Content Posting là đăng nội dung. Display API là hiển thị nội dung creator. Không cái tên nào tự động có nghĩa là “live inbox cho support”.
Đội nhỏ thường mất thời gian khi xem mọi danh mục API mới được document là customer-service event stream. Cách tốt hơn là đặt tên workflow trước, rồi chọn interface khớp với timing của workflow đó.
Nếu workflow là export, dùng export tooling. Nếu workflow là support, dùng webhook. Nếu hôm nay là TikTok và tháng sau thêm Zalo hoặc LINE, hãy giữ webhook envelope chuẩn hóa ngay từ đầu.
Phân tách thực tế là: TikTok Data Portability giúp người dùng chuyển dữ liệu của họ. UnifyPort giúp hệ thống hỗ trợ của bạn nhận tin nhắn khách hàng ngay khi chúng đến.