← Все статьи
Руководство

TikTok Data Portability не заменяет живые личные сообщения: как собрать входящую очередь для поддержки

Поверхность TikTok для разработчиков становится точнее, но точная документация не всегда решает задачу, которая стоит перед командой поддержки.

4 июня TikTok указал в Data Portability API changelog, что документация Data Types обновлена под текущие поддерживаемые категории и поля. На странице продукта Data Portability API сказано, что API позволяет пользователям TikTok из Европейской экономической зоны и Великобритании авторизовать передачу своей информации в другое приложение. Текущая страница data types включает Direct Messages как категорию экспорта, с такими полями, как дата, отправитель и содержимое.

Это полезно для переносимости данных, архивов, резервных копий и compliance-процессов. Но это не живой inbox для поддержки клиентов.

Если команда работает с TikTok Shop, кампаниями с авторами или продажами во время live-сессий, ей нужен другой процесс: новое сообщение должно попасть в очередь за секунды, пройти дедупликацию, запустить поиск в CRM и уйти оператору или AI-ассистенту. Пользовательский экспорт истории не создает такой событийный цикл. Подписанный входящий webhook создает.

Сначала опишите работу, которую должна выполнить интеграция

Перед выбором API сформулируйте задачу простым языком:

  1. Клиент отправляет личное сообщение в TikTok.
  2. Backend получает сообщение за несколько секунд.
  3. Доставка подписана, поэтому сервер может доверять источнику.
  4. Сообщение сохраняется, потому что пропущенные события нельзя восстановить позже.
  5. Та же очередь затем принимает WhatsApp, LINE, Zalo, Telegram или X.

TikTok Data Portability API не построен вокруг этой последовательности. Это продукт для передачи данных по согласию пользователя. Заявитель должен обслуживать пользователей в EEA или UK, пройти проверку privacy и security, а также запросить определенные data scopes. Модель данных ориентирована на экспорт: posts and profile, activity, direct messages или full archive.

Для поддержки это неправильная модель времени. Поддержка спрашивает не «может ли пользователь экспортировать вчерашний архив», а «можем ли мы обработать сообщение, которое пришло десять секунд назад».

Форма webhook в UnifyPort

TikTok unofficial interface в UnifyPort подходит для второй модели. Вы подключаете TikTok-аккаунт, регистрируете webhook endpoint и подписываетесь на message.received. Когда приходит сообщение клиента, UnifyPort отправляет стандартный envelope в ваш 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": "Черная сумка еще доступна до сегодняшнего эфира?",
      "direction": "inbound",
      "sent_at": "2026-07-05T03:18:41Z"
    }
  }
}

Важна сама оболочка: id, type, provider, account_id, occurred_at и data. Один и тот же обработчик может сегодня принять provider: "tiktok", а завтра provider: "zalo". В routing layer стоит делать ветвление только там, где поведение платформы действительно отличается.

Сначала зарегистрируйте endpoint

Перед подключением к очереди создайте webhook. Endpoint хранит URL, подписанные события, состояние подписи и retry policy. Укажите 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 подписывает timestamp, точку и raw request body через HMAC-SHA256. Проверяйте подпись по raw bytes до JSON parsing. Не парсите и не сериализуйте body заново перед проверкой, потому что bytes изменятся.

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);

Этого достаточно для входящей границы. В production можно отправлять событие дальше в очередь, но граница остается той же: подписанная доставка входит, проверенное событие выходит.

Сначала сохраняйте, потом маршрутизируйте

В документации UnifyPort прямо сказано, что webhook events являются единственной записью входящего трафика. Нет message read API и нет backfill-пути для пропущенных payload. Это должно определять дизайн очереди.

Первая запись должна сохранить событие по id, вместе с raw body или parsed JSON, provider, account ID и occurred_at. После успешной записи routing может выполняться асинхронно:

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; workflow ответа решает, нужно ли что-то отправлять.

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 года

Обновление документации TikTok от 4 июня напоминает: API платформ часто привязаны к конкретной policy surface или product surface. Data portability отвечает за передачу данных под контролем пользователя. Content Posting отвечает за публикацию. Display API отвечает за creator content. Ни одно из этих названий автоматически не означает «живой inbox личных сообщений для поддержки».

Малые команды теряют время, когда воспринимают каждую новую документированную категорию API как поток customer-service events. Более надежный путь: сначала назвать workflow, затем выбрать interface с подходящей временной моделью.

Если workflow про экспорт, используйте экспортные инструменты. Если workflow про поддержку, используйте webhook. Если сегодня это TikTok, а через месяц Zalo или LINE, держите envelope нормализованным с самого начала.

Практическое разделение простое: TikTok Data Portability помогает пользователям переносить свои данные. UnifyPort помогает вашей системе поддержки получать сообщения клиентов в момент их появления.