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

Как загрузить старые сообщения WhatsApp по запросу

Чтобы загрузить более старые сообщения WhatsApp через UnifyPort, сначала подпишитесь на conversation.history, затем отправьте запрос с сохранённым сообщением в качестве якоря before. HTTP-ответ не содержит сообщений: 202 и status: accepted означают только принятие запроса. Доступная история поступает асинхронно. Поэтому реализуйте кнопку «Загрузить более ранние сообщения» с ограниченными гарантиями, а не экспорт полного архива или цикл пагинации, который якобы определяет конец истории.

Главное

  • Операция поддерживает личные чаты provider=whatsapp, но не группы, каналы или whatsapp-protocol.
  • Подписка и надёжное хранение входящих данных должны быть готовы до запроса.
  • Для следующего якоря нужны ID, время отправки и направление реального сообщения с контентом.
  • Пакеты могут приходить повторно, с задержкой, несколькими частями или не приходить вовсе. Отсутствие callback не означает завершение.
  • История дополняет ленту переписки, но не должна запускать автоответы для новых сообщений.

Разделяйте ответ на запрос и результат загрузки

Справочник запроса истории описывает POST /v1/accounts/{account_id}/conversations/history/request. Операция инициирует асинхронную доставку, а не читает сохранённые сообщения с их возвратом в REST-ответе.

НаблюдениеЧто подтверждаетЧего не подтверждает
HTTP 202, data.status: acceptedЗапрос принятСообщения доставлены или операция завершена
HTTP request_idИдентификатор для диагностики HTTP-запросаID задачи или ключ связи с callback
conversation.history с data.history.source: on_demandПолучен пакет истории по запросуЭто единственный или последний пакет
Пустой или небольшой пакетСостав конкретного пакетаДостигнут конец доступной истории
Тайм-аут HTTPКлиент не получил определённый ответЗапрос не имел эффекта

Инструкция по восстановлению runtime аккаунта решает другую задачу — восстановление подключения. Ни переподключение, ни запрос истории не гарантируют возврат всех сообщений, пропущенных во время сбоя.

Подготовьте приёмник до включения кнопки

Добавьте conversation.history в подписку endpoint, сохранив события, которые уже нужны вашему inbox. Для текущего потока оставьте message.received. При изменении существующего endpoint используйте справочник настройки webhook и не очищайте случайно signing_secret.

Следуйте контракту доставки: проверяйте X-Device-Signature через HMAC-SHA256 от X-Device-Timestamp, точки и исходных байтов тела запроса. Проверяйте свежесть временной метки, затем надёжно сохраняйте аутентифицированную доставку и только после этого отвечайте 2xx.

Для истории нужна отдельная ветка дедупликации. Разные фрагменты WhatsApp HistorySync могут использовать один верхнеуровневый ID события. Нельзя отбрасывать весь пакет лишь потому, что такой ID уже встречался. В пределах workspace объединяйте сообщения по provider, account_id, data.conversation.id и каждому data.messages[].id.

Не передавайте исторические сообщения в триггер автоматического ответа на новые. Старый вопрос, полученный сегодня, не доказывает, что клиент задал его повторно.

Сформируйте корректный якорь before

Выберите наблюдавшееся сообщение из того же аккаунта обмена сообщениями и того же личного чата. Для якоря нужны message_id, sent_at и direction. Не выводите их из названия переписки, времени получения события или номера телефона.

Ниже — пример тела запроса по документированному формату. Замените примерные идентификаторы фактическими сохранёнными значениями:

{
  "conversation_id": "100000000000002@lid",
  "before": {
    "message_id": "MSG_HISTORY_ANCHOR_001",
    "sent_at": "2026-09-28T03:00:00Z",
    "direction": "inbound"
  },
  "limit": 50
}

Отправьте тело в указанную POST-операцию с X-Api-Key, хранящимся на сервере. account_id должен занимать один непустой сегмент пути без пробельных символов и слешей, включая закодированные слеши. Не помещайте идентификатор переписки в сегмент пути для аккаунта.

Для продолжения выберите самое раннее из полученных нативных сообщений с контентом, у которого заполнены все поля якоря. Исключите синтетические записи type: call. Следующий JavaScript только строит якорь из уже выбранного и проверенного сообщения; это не приёмник и не автоматический обработчик пагинации:

function beforeFromMessage(message) {
  if (!message || message.type === 'call' ||
      typeof message.id !== 'string' || !message.id ||
      typeof message.sent_at !== 'string' ||
      !Number.isFinite(Date.parse(message.sent_at)) ||
      !['inbound', 'outbound'].includes(message.direction)) {
    throw new Error('Select a native content message with complete anchor fields');
  }
  return {
    message_id: message.id,
    sent_at: message.sent_at,
    direction: message.direction
  };
}

Обратите внимание: type не копируется в before. Если подходящего якоря нет, отключите запрос и объясните причину. Не подставляйте синтетическую запись звонка и не придумывайте более раннюю дату.

Показывайте неопределённость в интерфейсе

Ниже приведено рекомендуемое поведение приложения, а не дополнительные статусы API:

  1. До отправки: сохраните аккаунт, переписку, якорь и локальное время запроса. Выполняйте запросы операторов последовательно для каждой переписки, чтобы уменьшить пересечение операций.
  2. После принятия: покажите «Запрос принят; ожидаем доступную историю». Продолжайте принимать текущие сообщения независимо.
  3. При каждом пакете: идемпотентно объединяйте отдельные сообщения. Сохраняйте актуальные правки и защиту от восстановления удалённого контента: старая история не должна перезаписывать новое состояние.
  4. После получения более старого контента: разрешите явный следующий запрос с самым ранним допустимым якорем. Если более раннего подходящего якоря нет, сообщите «Более ранний якорь не получен», а не «Вся история загружена».
  5. После тайм-аута или отсутствия callback: оставьте результат неопределённым и продолжайте принимать запоздавшие пакеты. Не отправляйте тот же запрос повторно автоматически.

Документация не определяет курсор следующей страницы или статус завершения. account.history.synced — сводка отдельного пакета либо фрагмента HistorySync, а не доказательство завершения запроса по требованию или полноты архива. Не превращайте это событие в вымышленный сигнал завершения задачи.

Также отделяйте связи цитирования в истории от возможностей отправки. Исторические сообщения не содержат reply_token; руководство по ответам с цитатой объясняет, почему ID родительского сообщения не заменяет токен. Недоступное вложение должно оставаться явно недоступным, а не отображаться как скачанный файл.

Ошибки и проверки перед запуском

Ответ 400 может означать invalid_request, provider_invalid_request — в том числе при синтетическом якоре звонка — или unsupported_conversation_type. Другие provider возвращают 501 unsupported_by_provider. Исправляйте область применения или входные данные вместо запуска бесконечных повторов. Сохраняйте HTTP request_id для диагностики, но не используйте его для связи с callback.

Перед запуском проверьте повторные пакеты, разные фрагменты с одинаковым ID события, callback после HTTP-тайм-аута, перемежение истории с текущими сообщениями и якорь без направления. Это предложенные тесты, а не результаты уже проведённых испытаний.

UnifyPort предоставляет неофициальный интерфейс. Возможность помогает дополнить контекст переписки по принципу best-effort, но не обеспечивает полный бэкап, гарантированную повторную доставку или доступ к произвольным аккаунтам. Продолжайте вести собственное разрешённое хранилище сообщений и управлять сроками хранения.

Частые вопросы

Значит ли 202, что старые сообщения уже получены?

Нет. Это подтверждение принятия запроса. Доступные сообщения поступают через асинхронные события истории.

Можно запрашивать дальше, пока не придёт короткий пакет?

Не используйте это как условие завершения. Размер пакета не доказывает полноту истории, а автоматические запросы могут пересекаться с запоздалыми результатами.

Подходит ли операция для групп WhatsApp, LINE или Zalo?

Она документирована только для личных чатов provider=whatsapp. Общая схема webhook не означает одинаковую поддержку запросов истории у всех платформ.

Следующий шаг и источники

Реализуйте приёмник и состояния неопределённого результата по справочнику запроса истории переписки, прежде чем включать кнопку в inbox.

Официальные материалы проверены 2026-09-30:

UnifyPort API

Превратите интеграцию сообщений в стабильный продуктовый pipeline.

Начните с отправки через единый API, затем возвращайте входящие сообщения в бизнес-систему стандартными событиями.