Формат событий вебхуков
Этот справочник описывает публичные события вебхука проекта и вебхука приложения. Их JSON имеет одинаковую структуру. Вебхук проекта получает выбранные события своего проекта; вебхук приложения — проектов с активной установкой приложения. Проект определяется по project_id.
Общая структура
Senler отправляет POST с Content-Type: application/json. Полный пример подписки на сегмент при выбранном Standard Webhooks; идентификаторы и время в примере условные:
{
"event_id": "019e8e31-7e00-7000-8000-000000000001",
"event_type": "segment_subscribed",
"timestamp": "2026-10-15T12:00:00.000Z",
"project_id": "11111111-1111-4111-8111-111111111111",
"channel_id": "22222222-2222-4222-8222-222222222222",
"channel_type": "tg",
"lead_id": "000000000000000000000001",
"dialog_id": null,
"platform_user_id": "123456789",
"data": {
"segment_id": "000000000000000000000002",
"source": "manual",
"reason": "manual",
"occurred_at": "2026-10-15T12:00:00.000Z"
}
}
Общие поля присутствуют в каждом боевом событии:
event_id— строковый ID события. Он сохраняется при повторной доставке. Считайте его непрозрачным идентификатором: формат не ограничен UUID.event_type— строка с одним из 12 типов, описанных ниже. По ней выбирайте обработчикdata.timestamp— время в ISO 8601. В Standard Webhooks сохраняется исходное время тела; время текущей попытки передаётся вwebhook-timestamp. В Senler Webhook Standardtimestampобновляется при отправке и совпадает сX-Webhook-Timestamp.project_id— строковый ID проекта.channel_id,lead_id,dialog_id— строковые ID соответствующих объектов Senler илиnull, если контекста нет.channel_type—vk,tg,max,discord,widget,streamvi,email,avitoилиnull. Для Telegram приходитtg.platform_user_id— строковый ID пользователя на внешней платформе илиnull. Это отдельный идентификатор, неlead_idSenler.data— объект с полями конкретного типа события. Ниже приведены его состав и короткие примеры.
Проверяйте подпись приложения или подпись вебхука проекта до обработки JSON. Формат подписи выбирается в настройках отправителя. Не требуйте непустые идентификаторы канала или диалога у события, для которого такого контекста нет.
Сообщения и кнопки
command_start
Приходит при входящем сообщении с командой /start, а также при запуске диалога с переданным стартовым параметром.
Обязательные поля data: command — строка start; args — строка с параметром запуска, пустая, если параметра нет.
{"command": "start", "args": "campaign_42"}
Если сообщение /start campaign_42 получено от лида, оно создаёт и command_start, и message_new. При подписке на оба типа получатель увидит два события с разными event_id. Это самостоятельные события; повтор доставки одного из них сохраняет его прежний ID.
message_new
Приходит при создании входящего сообщения лида с текстовым полем content. Сообщения агента и оператора этот тип не создают.
Обязательное поле data.content — строка с содержимым сообщения; она может быть пустой. Объект data не содержит полную карточку сообщения и список вложений.
{"content": "Хочу записаться на консультацию"}
button_clicked
Приходит при нажатии кнопки, для которой получены данные callback. Обычный переход по URL сам по себе не гарантирует такое событие.
callback_data— обязательная непустая строка с данными кнопки.button_text— текст кнопки, если он доступен.callback_id— идентификатор callback, если его передала платформа.message_id— идентификатор сообщения, если он доступен в событии нажатия.
Последние три поля необязательны для обработки: учитывайте отсутствие значения или null; доступное значение — строка.
{"callback_data": "confirm_order", "button_text": "Подтвердить", "callback_id": "callback-123", "message_id": "456"}
Разрешение сообщений и лиды
У следующих четырёх типов одинаковый состав data. Оба поля присутствуют и допускают null:
key— строковый ключ из контекста действия, если он задан. Это не ID лида или сегмента.error_message— строка с сообщением из контекста события, если оно есть. Наличие поля не означает, что обычное событие подписки или создания лида завершилось ошибкой.
Обычный пример без дополнительного контекста:
{"key": null, "error_message": null}
message_allow
Пользователь разрешил отправку сообщений, и Senler получил соответствующее событие подписки на сообщения. Подписка на сегмент передаётся отдельным типом segment_subscribed.
lead_created
В проекте создан лид. Его ID находится в общем lead_id; полная карточка лида в data не передаётся.
lead_unsubscribed
Лид отписался от сообщений. Выход из отдельного сегмента передаётся как segment_unsubscribed.
lead_blocked
Зафиксирована блокировка бота пользователем. Данные этого события имеют тот же состав key и error_message.
События сегментов
Оба события передают фактическое сохранённое изменение членства. Вебхук получает изменения всех сегментов доступного ему проекта; нужный сегмент определяйте по data.segment_id. В боевом событии lead_id заполнен. Контекст канала и диалога может быть null.
segment_subscribed
Лид стал участником сегмента. Если требуется согласие пользователя, событие приходит после подтверждения. Повторное добавление уже подписанного лида нового события не создаёт. Подписка после отписки создаёт новое событие с новым ID.
Полный пример приведён в общей структуре.
segment_unsubscribed
Лид перестал быть участником сегмента. Отмена ещё не подтверждённой подписки не создаёт отписку. Общая структура та же, что при подписке, но event_type равен segment_unsubscribed.
Пример data после запрета сообщений VK:
{
"segment_id": "000000000000000000000002",
"source": "vk_messages",
"reason": "channel_access_revoked",
"occurred_at": "2026-10-15T13:00:00.000Z"
}
Поля data
Все четыре поля обязательны и не равны null:
segment_id— строковый ID сегмента Senler, не название и не короткий публичный код ссылки.source— строка: откуда пришло действие, например из Telegram-бота, кабинета или автоматизации.reason— строка: что послужило причиной изменения, например прямая ссылка или потеря доступа к каналу.occurred_at— время самого изменения членства в ISO 8601. Оно сохраняется при повторной доставке при обоих форматах подписи.
source и reason описывают разные стороны действия. Например, source: "tg_bot" и reason: "direct_link" означают подписку через Telegram-бота по прямой ссылке. При ручном изменении оба поля равны manual.
Источник source
vk_app— приложение VK.vk_messages— сообщения VK.tg_bot— Telegram-бот.tg_app— приложение Telegram.max_bot— бот MAX.max_app— приложение MAX.web— веб-страница.manual— ручное действие.auto_assignment— автоматическое назначение сегмента.automation— автоматизация.ai_agent— действие ИИ-агента.trigger— действие триггера.
Причина reason
landing— подписка через лендинг.direct_link— переход по прямой ссылке подписки.keyword— срабатывание ключевого слова.all_messages— правило подписки по входящим сообщениям.manual— ручное изменение членства.channel_access_revoked— автоматическая отписка после запрета сообщений VK; применяется к подпискам, связанным с этим каналом.automation— изменение из автоматизации.ai_agent— изменение по действию ИИ-агента.trigger— изменение по действию триггера.
События ошибок
error
Ошибка выполнения агента, например тайм-аут ИИ или недостаточный баланс. Состав data описан ниже вместе с message_undelivered.
message_undelivered
Не удалось отправить сообщение агента, автоматизации или оператора. Это результат отправки сообщения, а не ошибка HTTP-запроса с самим вебхуком.
У error и message_undelivered все перечисленные поля data присутствуют; значения имеют тип string | null:
key— дополнительный ключ из контекста действия.error_code— код ошибки для программной обработки.error_message— текст причины, если он доступен.error_message_key— ключ локализации сообщения об ошибке.agent_id— ID агента.sender_type,sender_id— тип и ID отправителя; например, типassistant,userилиautomation.message_event_id— ID исходящего сообщения уmessage_undelivered; уerrorравенnull.response_id— ID ответа агента.automation_id,version_id,run_id,task_id,node_id— доступный контекст автоматизации.
Пример data для message_undelivered; код ошибки условный:
{
"key": null,
"error_code": "delivery_failed",
"error_message": "Не удалось отправить сообщение",
"error_message_key": null,
"agent_id": null,
"sender_type": "automation",
"sender_id": null,
"message_event_id": "message-event-id",
"response_id": null,
"automation_id": "000000000000000000000003",
"version_id": "000000000000000000000004",
"run_id": "000000000000000000000005",
"task_id": "000000000000000000000006",
"node_id": "send-message"
}
automation_step_failed
Шаг автоматизации окончательно завершился ошибкой: повторы исчерпаны или для этой ошибки не предусмотрены. Промежуточная неудачная попытка, тестовый запуск и предусмотренный переход HTTP-шага по подключённой ветке «Ошибка» это событие не создают.
Все перечисленные поля data присутствуют:
automation_id,version_id,run_id,task_id,node_id— обязательные строки с идентификаторами автоматизации и выполнения.node_name— сохранённое название шага, строка илиnull.message_event_id— ID исходящего сообщения, строка илиnull.error_code,error_message— обязательные строки с кодом и причиной ошибки.occurred_at— время окончательного сбоя в ISO 8601.retryable— всегдаfalse: это окончательный сбой текущей задачи.
{
"automation_id": "000000000000000000000003",
"version_id": "000000000000000000000004",
"run_id": "000000000000000000000005",
"task_id": "000000000000000000000006",
"node_id": "send-message",
"node_name": "Отправить сообщение",
"message_event_id": "message-event-id",
"error_code": "delivery_failed",
"error_message": "Не удалось отправить сообщение",
"occurred_at": "2026-10-15T13:00:00.000Z",
"retryable": false
}
Значения ID и кода ошибки в примере условные. У этого типа общие channel_type и platform_user_id равны null, даже если известен channel_id. Подробности выбора событий и их взаимосвязь описаны в событиях ошибок.
Обработка и тестовые запросы
Сохраняйте обработанные event_id и не выполняйте повторно уже принятое событие. Разные типы событий об одном действии могут иметь разные ID: например, command_start и message_new, либо message_undelivered и automation_step_failed. Возвращайте 2xx после надёжного приёма события, включая повтор.
Тест вебхука проекта передаёт выбранный event_type и test: true; ID лида, канала и диалога равны null, данные синтетические. Без выбора типа приходит event_type: "test". Тест вебхука приложения использует служебный тип test. Тестовые данные могут быть короче боевых примеров выше; выделите для них отдельную обработку без действий над реальными клиентами.
Другие виды вызовов
tool_call: HTTP-инструменты — отдельный контракт с аргументами, настройками и результатом инструмента.automation_step: шаги приложения — отдельный контракт выполнения шага и его завершения.- История доставки и повторы — диагностика получения событий приложением.
tool_call и automation_step не выбираются в списке 12 публичных событий; их вызовы настраиваются в соответствующих инструментах и шагах.