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

История хранит фактические изменения статуса. Она помогает восстановить порядок изменений, а не только узнать текущее значение.

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

#Три маршрута

  • GET /v1/leads/{id}/status-history: история участия лида в кампании, право leads:read.
  • GET /v1/campaigns/{id}/status-history: история кампании, право campaigns:read.
  • GET /v1/campaigns/{id}/accounts/{account_id}/status-history: история аккаунта в контексте выбранной кампании, право accounts:read.

История аккаунта не раскрывает его работу в других кампаниях. Действует охват ключа по пространствам и кампаниям. Объект вне охвата дает 404, как несуществующий.

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

Каждый маршрут принимает limit и cursor. По умолчанию 50 записей, максимум 100. Переходы идут по возрастанию entity_revision, а не по времени доставки уведомления. Курсор живет 15 минут; при 410 начните новый обход и объедините записи по id. Подробные ответы есть в справочнике истории.

#Запись перехода

Каждый элемент data имеет object=status_transition и содержит:

  • id: идентификатор перехода; entity_kind: lead, campaign или account; entity_id: идентификатор этого объекта.
  • workspace_id, campaign_id, lead_id: контекст. В истории кампании и аккаунта lead_id может быть null.
  • entity_revision: порядковый номер перехода для объекта, начиная с 1. Используйте его для порядка внутри истории одного объекта.
  • from_status, to_status: предыдущий и новый публичные статусы.
  • occurred_at: время изменения; recorded_at: когда оно было сохранено.
  • reason_code: operator_action, schedule, queue_exhausted, recipient_not_found, telegram_auth, subscription, recovery или unspecified.
  • source: кто изменил статус: user (пользователь кабинета), system (автоматика сервиса), support (поддержка Meliora) или unknown. Это справка, а не инструкция клиенту.

Если причина не установлена, приходит unspecified, если источник неизвестен, приходит unknown. Сохранение того же статуса не является новым переходом. История описывает изменение поля статуса, а не каждое действие над объектом.

#Публичные статусы

У лида: new, contacted, completed, replied, blocked, failed, suspended, deleted, opted_out, unknown. Их смысл описан в статусах лида.

У кампании: draft, scheduled, active, paused, stopped, completed, archived, launching, failed, paused_no_credits, unknown. См. статусы кампании.

У аккаунта в истории:

  • online: подключен; offline: отключен.
  • limited: ограничен; banned: заблокирован.
  • deleted: удален; locked: доступ заблокирован; unauthorized: требуется авторизация.
  • paused: на паузе; unknown: значение не удалось определить.

Неизвестное исходное значение становится unknown. Оно допустимо и в from_status, и в to_status; не превращайте его в failed или offline. Набор истории аккаунта включает paused; в обычном списке аккаунтов это значение может быть представлено как unknown.

Статусы могут возвращаться к прежним значениям: например, paused сменяется на active. Для истории не подходит правило «разрешать статусам двигаться только вперед».

#Начальный снимок и полнота

meta.baseline содержит отдельный объект status_baseline с status, entity_revision, recorded_at, контекстом объекта и provenance=baseline, либо null. Ревизия снимка может быть 0. Это наблюдавшийся начальный статус, а не переход из выдуманного предыдущего значения. Он не создает *.status_changed.

Границы истории находятся в meta:

  • history_started_at: начало ведения истории. Более ранние изменения не восстанавливаются.
  • available_from: начало доступной истории.
  • retained_from: начало сохраненного периода.
  • observed_at: время чтения данных сервером.

Неизвестные границы равны null. Удаление старых записей по сроку хранения не должно выглядеть как полная история с момента создания объекта.

meta.completeness.status принимает complete, partial или unknown. Также есть gaps, gaps_truncated и incomplete_from. Каждый разрыв содержит id, from, to, state; состояния: open, recovering, recovered, unrecoverable, unknown. Список ограничен 50 интервалами, gaps_truncated=true сообщает о сокращении. incomplete_from помогает заметить более раннюю неполноту; null сам по себе не доказывает отсутствие разрывов.

complete относится к доступному периоду истории, а не ко всей жизни объекта. При partial или unknown сохраните отметку неполноты, сверяйте текущую карточку и позже повторяйте чтение истории. has_more=false говорит только о конце страниц.

#События смены статуса

Лента поддерживает lead.status_changed, campaign.status_changed, account.status_changed. Выберите каталог 2b или один конкретный новый type.

В data есть organization_id, workspace, campaign, transition_id, entity_kind, entity_id, from_status, to_status, reason_code, source, occurred_at, recorded_at. transition_id совпадает с id перехода в истории. Событие аккаунта относится к одной кампании; список других кампаний не передается.

lead.status_changed сообщает только о смене статуса. lead.replied сообщает о засчитанном бизнес-ответе: один ответивший лид учитывается один раз в кампании. Не увеличивайте счетчик ответов по lead.status_changed или по каждому message.received: последнее означает отдельное входящее сообщение. Один и тот же ответ может привести к нескольким разным типам событий об одном взаимодействии.

Повторные доставки убирайте по event.id. Уведомления могут прийти позже самого изменения. Для восстановления порядка прочитайте историю по entity_revision и сопоставьте transition_id; для текущего состояния сверяйте карточку. Не выбирайте итоговый статус только по порядку прихода вебхуков.

Новые вебхуки этих типов содержат только метаданные. Текст сообщения к изменению статуса не прилагается.