API EN
Ранний доступ. Ключи выдаются по запросу. Как получить ключ

Читайте оба направления переписки в рамках одной кампании и проверяйте, за какой период данные полны.

Новые возможности включаются для кабинета по запросу.

#Что входит в переписку

Запрос GET /v1/leads/{id}/messages?view=conversation возвращает доступные сообщения с первого подтвержденного нашего сообщения этому лиду в этой кампании, включая само первое сообщение. Входят шаги кампании, ручные исходящие сообщения и отдельные входящие сообщения, в том числе сообщения с вложением без текста.

Лид означает участие контакта в одной кампании. Более ранняя переписка и сообщения другой кампании не входят в ответ. Если принадлежность сообщения этой переписке не установлена, API не приписывает его лиду по догадке. У лида может быть несколько диалогов с разными аккаунтами: полнота каждого находится в meta.dialogs.

Сохраняется первая доступная копия сообщения. Правки и удаления не отслеживаются. Уже удаленное до сохранения сообщение может отсутствовать даже в проверенном диапазоне. complete не означает, что восстановлены все когда-либо существовавшие сообщения.

#Запрос и поля сообщения

Нужны право messages:read и включенный у ключа «Текст сообщений». Без view маршрут сохраняет прежний формат ответа и прежние курсоры.

curl
curl -G https://api.melioralab.io/v1/leads/5a7c3e92-1f4b-4d68-9c2e-7b0a6d4f8e31/messages \
  -H "Authorization: Bearer $MELIORA_API_KEY" \
  -d view=conversation -d limit=50

Ответ имеет поля object, data, has_more, next_cursor, meta. У каждого сообщения есть:

  • id: устойчивый идентификатор. Объединяйте повторные результаты по нему.
  • workspace_id, campaign_id, lead_id, account_id: контекст сообщения.
  • direction: inbound или outbound; author: campaign, manager, lead или unknown.
  • state: sent, received или unknown. Неизвестный исход не означает неудачную отправку.
  • sent_at: время сообщения или null; observed_at: когда оно было сохранено.
  • media_kind: вид содержимого; attachment: описание вложения или null.
  • text, text_truncated, text_unavailable, text_unavailable_reason: сохраненный текст и его доступность.

Текст ограничен 4000 символами. text_truncated=true означает усечение, false означает полный текст, null означает, что это неизвестно. При недоступном тексте text=null; причина: not_saved, ownership_unproven, source_conflict или purged. Недоступность текста и полнота набора сообщений оцениваются отдельно.

Полные схемы и вымышленные ответы находятся в справочнике переписки.

#Вложения

attachment содержит только {kind, caption}. Виды: photo, video, voice, video_note, file, sticker, other. Аудиофайл относится к file, неподдержанный вид к other. Подпись ограничена 4000 символами или равна null; признаки доступности и усечения текста относятся и к подписи. Если текст недоступен, подпись тоже равна null.

Файлы, ссылки для скачивания, имена файлов и содержимое карточек контактов не выдаются.

#Как читать полноту

meta.completeness описывает весь доступный диапазон лида, а meta.dialogs[].completeness описывает каждый диалог отдельно.

  • overall, inbound, outbound: общая полнота и полнота двух направлений. Значения: complete, partial, unknown.
  • boundary_at: время первого подтвержденного нашего сообщения в кампании. Это начало диапазона, включая первое сообщение.
  • checked_at: когда диапазон проверен; checked_through: до какого времени включительно он проверен. Это разные величины. null означает, что значение неизвестно.
  • available_from, available_to: границы доступных сохраненных данных. Они сами по себе не доказывают полноту.
  • observed_at: время чтения сведений о полноте.
  • gaps: до 50 интервалов возможной неполноты с полями id, from, to, state. При незакрытом интервале to=null.
  • gaps_truncated=true: список разрывов сокращен; пустой список разрывов не доказывает полноту.

complete означает, что оба направления проверены от начала до checked_through на момент checked_at. Новые сообщения после проверки этим обещанием не покрываются. partial означает известную неполную часть, например разрыв или недоступный период. unknown означает, что данных для вывода недостаточно, например не установлена начальная граница.

Разрыв имеет состояние open, recovering, recovered, unrecoverable или unknown. recovered означает, что этот разрыв закрыт; для общего вывода все равно смотрите overall.

#Что делать при partial

  1. Сохраните полученные сообщения и отметку неполноты. Не показывайте отсутствие сообщения как доказательство, что его не было.
  2. Дочитайте все страницы текущего обхода. has_more=false означает только конец страниц сохраненных данных.
  3. Позже начните новый обход без cursor, сохранив view=conversation, и объедините сообщения по id. Сравните полноту и границы проверки у каждого диалога.
  4. Если разрыв остается unrecoverable, храните отметку неполноты. Если полнота долго не меняется, обратитесь в поддержку с Request-Id.

При unknown также сохраняйте неопределенность и повторяйте чтение позже, не считая историю полной.

#Курсор и snapshot_stale

Первая страница фиксирует набор данных для обхода. Страницы идут от ранних сообщений к поздним; курсор продолжает тот же набор. Сообщение, добавленное позже, в том числе более раннее по времени, появится в новом обходе.

Передавайте view=conversation на каждой странице. Менять limit можно: по умолчанию 50, максимум 100. Курсор привязан к лиду, представлению и охвату ключа; курсор прежнего представления сюда не подходит. Срок курсора 15 минут: при 410 cursor_expired начните заново, при 400 cursor_mismatch проверьте параметры и охват.

Если хотя бы на одной странице пришло meta.snapshot_stale=true, после начала обхода появились новые факты. Дочитайте текущий обход, затем начните новый без курсора и объедините результат по id. snapshot_stale=false не заменяет проверку meta.completeness.

#Входящие события и вебхуки

message.received означает одно отдельное входящее сообщение, в том числе без текста. data.message.id совпадает с идентификатором в переписке. data.backfilled=true означает восстановленный пропуск; время сообщения остается исходным. События не заменяют чтение всей доступной переписки.

Для ленты выберите каталог 2b или type=message.received. В ленте текст и подпись можно запросить через include_text=true. Новые вебхуки передают только метаданные; текст читайте этим маршрутом API.