Сообщения
Сообщения
Новое сообщение
message.createdОтправляется при создании нового сообщения — входящего от контакта или исходящего от оператора либо системы. Для сообщений, начатых из рекламы (WhatsApp Click-to-Message и реклама Instagram с переходом в Direct), payload включает объект referral с данными объявления. Нажатия quick-reply и интерактивных кнопок WhatsApp нормализуются в обычное текстовое сообщение: подпись кнопки попадает в content.text, а payload кнопки — в content.interactive_reply_payload.
HTTP-запрос
AISAR отправляет подписанный POST-запрос на ваш webhook_url:
http
POST {webhook_url}
Content-Type: application/json
X-AISAR-Signature: sha256=...
{
"event": "message.created",
"event_id": "evt_01JXXXXXXXXXXXXXXXXXXXXX",
"timestamp": "2026-03-22T12:00:00.000000Z",
"company_id": 1,
"data": {
"message": {
"id": 123,
"external_id": "3EB0ABC123456789",
"conversation_id": 45,
"thread_id": 67,
"channel_id": 2,
"direction": "inbound",
"type": "text",
"content": {
"text": "Hello, I need help"
},
"display_content": "Hello, I need help",
"media": null,
"reply_to_message_id": null,
"is_deleted": false,
"system_notification": false,
"created_at": "2026-03-22T12:00:00.000000Z"
},
"sender": {
"type": "contact",
"contact_id": 10,
"contact_account_id": 15,
"name": "John Doe",
"phone": "+77001234567",
"email": "john@example.com",
"external_id": "77001234567@s.whatsapp.net"
},
"recipient": null,
"conversation": {
"id": 45,
"status": "active",
"contact_id": 10,
"deal_id": null,
"subject": null,
"is_archived": false,
"is_group": false
},
"channel": {
"id": 2,
"type": "whatsapp",
"name": "Main WhatsApp"
},
"is_dialog_assigned": false,
"referral": null
}
}Заголовок X-AISAR-Signature содержит HMAC-SHA256 подпись тела запроса — используйте её, чтобы убедиться, что запрос пришёл от AISAR.
Пример payload
json
{
"event": "message.created",
"event_id": "evt_01JXXXXXXXXXXXXXXXXXXXXX",
"timestamp": "2026-03-22T12:00:00.000000Z",
"company_id": 1,
"data": {
"message": {
"id": 123,
"external_id": "3EB0ABC123456789",
"conversation_id": 45,
"thread_id": 67,
"channel_id": 2,
"direction": "inbound",
"type": "text",
"content": {
"text": "Hello, I need help"
},
"display_content": "Hello, I need help",
"media": null,
"reply_to_message_id": null,
"is_deleted": false,
"system_notification": false,
"created_at": "2026-03-22T12:00:00.000000Z"
},
"sender": {
"type": "contact",
"contact_id": 10,
"contact_account_id": 15,
"name": "John Doe",
"phone": "+77001234567",
"email": "john@example.com",
"external_id": "77001234567@s.whatsapp.net"
},
"recipient": null,
"conversation": {
"id": 45,
"status": "active",
"contact_id": 10,
"deal_id": null,
"subject": null,
"is_archived": false,
"is_group": false
},
"channel": {
"id": 2,
"type": "whatsapp",
"name": "Main WhatsApp"
},
"is_dialog_assigned": false,
"referral": null
}
}Поля payload
| Поле | Тип | Описание |
|---|---|---|
message.id | integer | Внутренний ID сообщения |
message.external_id | string | Внешний ID сообщения (платформенный, например ID сообщения WhatsApp) |
message.conversation_id | integer | ID диалога |
message.thread_id | integer | ID треда |
message.channel_id | integer | ID канала |
message.direction | string | inbound (от контакта) или outbound (от пользователя/системы) |
message.type | string | Тип сообщения: text, image, video, audio, voice, document, sticker, location, contact, poll, template, ig_post, ig_reel, ig_story, ig_story_reply, story_mention, share, ephemeral, unsupported_type, comment, call, note. voice — голосовое сообщение (записанное аудио, OGG/Opus), audio — обычный аудиофайл. template, ig_post, ig_reel, ig_story, ig_story_reply, story_mention, share, ephemeral, unsupported_type — виды вложений Instagram (карточка generic-шаблона, репост поста/рилса/сторис, ответ на сторис, упоминание в сторис, шеринг поста, самоуничтожающееся и нераспознанное вложение соответственно): для этих типов message.type наследует type первого вложения сообщения (см. message.media[].type ниже), а не выставляется отдельно. comment — комментарий к посту Instagram/Threads (комментарийный тред). call — карточка звонка в таймлайне. note — внутренняя заметка оператора (не покидает AISAR). Нажатия quick-reply / интерактивных кнопок WhatsApp нормализуются в text. Реакции НЕ являются message_type — они доставляются отдельным событием `message.reaction.updated`, а не через `message.created` |
message.content | object|string | Содержимое сообщения. Для текста: {"text": "..."}. Для медиа включает подпись, mime_type и т. п. Для нажатий кнопок дополнительно несёт interactive_reply_payload — payload кнопки / id пункта списка (null, если кнопка шаблона без payload) |
message.display_content | string|null | Текстовое представление содержимого сообщения |
message.media | array|null | Массив вложений; null, если медиа нет. Каждый элемент несёт только type/url/filename/mime_type/size/duration/playback_url — поле metadata вложения (download_status, media_id, содержимое IG-карточки и т.п.) в вебхук-payload НЕ отдаётся, оно доступно только через REST (GET /messages/{id} или .../attachments) |
message.media[].type | string | Тип вложения (полный набор значений CHECK-constraint message_attachments.type): image, video, audio, voice, document, file, contact, location, sticker, ig_reel, ig_post, ig_story, share, ig_story_reply, story_mention, ephemeral, unsupported_type, template |
message.media[].url | string | URL для скачивания |
message.media[].filename | string|null | Исходное имя файла |
message.media[].mime_type | string|null | MIME-тип (например, image/jpeg; голосовые сообщения — audio/ogg) |
message.media[].size | integer|null | Размер файла в байтах |
message.media[].duration | integer|null | Длительность в секундах (аудио / голосовые / видео) |
message.media[].playback_url | string|null | Подписанная ссылка на m4a/AAC-версию голосового вложения (транскодируется лениво из исходного OGG/Opus). Присутствует только для voice-вложений и audio-вложений с mime_type audio/ogg, у которых файл уже скачан локально; иначе null. В вебхуке ссылка временная — действует 7 дней (в REST-версии того же поля, MessageAttachment.playback_url, срок жизни ссылки не ограничен) |
message.reply_to_message_id | integer|null | ID цитируемого сообщения, если это ответ |
message.is_deleted | boolean | Удалено ли сообщение |
message.system_notification | boolean | Является ли сообщение системным уведомлением |
message.created_at | string | Метка времени ISO 8601 |
sender.type | string | contact для входящих сообщений, user для исходящих |
sender.contact_id | integer | ID контакта (для входящих) |
sender.contact_account_id | integer | ID аккаунта контакта (для входящих) |
sender.user_id | integer | ID пользователя (для исходящих) |
sender.name | string | Отображаемое имя отправителя |
sender.phone | string|null | Телефон контакта (для входящих) |
sender.email | string|null | Email отправителя |
sender.external_id | string | Платформенный ID контакта, например 77001234567@s.whatsapp.net (для входящих) |
recipient | object|null | Только для исходящих сообщений: контакт-получатель, та же структура, что у sender с type=contact |
conversation.id | integer | ID диалога |
conversation.status | string | active или closed |
conversation.contact_id | integer | ID контакта |
conversation.deal_id | integer|null | ID связанной сделки |
conversation.subject | string|null | Тема диалога |
conversation.is_archived | boolean | Архивирован ли диалог |
conversation.is_group | boolean | true, если это групповой чат (например, группа WhatsApp), false для личных переписок |
channel.id | integer | ID канала |
channel.type | string | Ключ типа канала: `whatsapp`, `whatsapp_business`, `instagram`, `instagram_business`, `threads`, `telegram`, `telegram_bot`, `live_chat` |
channel.name | string | Название канала |
is_dialog_assigned | boolean | true, если на диалог назначен пользователь, иначе false |
referral | object|null | Данные перехода из рекламы; null для обычных сообщений. Заполняется на первом сообщении диалога, начатого из объявления, для каналов `whatsapp`, `whatsapp_business` (Click-to-WhatsApp) и `instagram_business` (реклама с переходом в Direct). Набор полей зависит от канала: WhatsApp отдаёт `source_url`, `ctwa_clid`, `body`, `media_type`; Instagram — `post_id` и `ref`. Общие для обоих: `source_type`, `source_id`, `headline`, `image_url`, `video_url`. Для остальных типов каналов всегда null. |
referral.source_url | string | URL объявления или поста; только WhatsApp |
referral.source_type | string | Тип источника: ad или post |
referral.source_id | string | ID объявления или поста (для Instagram — `ad_id`); можно использовать с Meta API для получения данных кампании |
referral.headline | string | Заголовок объявления |
referral.body | string | Текст объявления |
referral.ctwa_clid | string | Клик-ID для точной атрибуции; только WhatsApp |
referral.media_type | string | Тип медиа в объявлении: image или video; только WhatsApp |
referral.image_url | string | URL изображения объявления (если есть) |
referral.video_url | string | URL видео объявления (если есть) |
referral.post_id | string | ID поста, из которого крутилось объявление; только Instagram |
referral.ref | string | Произвольная метка из диплинка (`ig.me/...?ref=`), если задана; только Instagram |