Для AI-агентов: markdown этой страницы — /docs-content/bots/events/webhook.md индекс документации — /llms.txt
Событие, доставленное вебхуком
Как выглядит тело события, которое Битрикс24 отправляет боту напрямую, какие в нём поля и чем обработчик проверяет подлинность запроса.
Когда приходит такое событие
Режим доставки задаётся при регистрации бота — POST /v1/bots с eventMode: "webhook" и адресом webhookUrl. Битрикс24 отправляет каждое событие POST-запросом прямо на этот адрес, платформа Вайбкод в доставке не участвует.
Опрос у такого бота остаётся пустым: GET /v1/bots/:botId/events отдаёт пустой массив events. Пока массив пуст, к ответу добавляется подсказка hint о том, что события ушли на webhookUrl. Рядом приходит nextPollAfterMs — его нет в ответе на запрос с withUserEvents=true.
Требования к адресу, время ожидания ответа, отсутствие повторной доставки и сравнение двух режимов — Диагностика проблем.
Тело запроса
Формат тела — application/x-www-form-urlencoded, вложенность передаётся квадратными скобками. Ниже событие «новое сообщение боту» разнесено по строкам для чтения, в запросе это одна строка без переносов.
event=ONIMBOTV2MESSAGEADD
&data[bot][id]=42
&data[message][id]=1501
&data[message][text]=%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82%2C+%D0%B1%D0%BE%D1%82
&data[message][params][FILE_ID][0]=15423
&data[chat][id]=123
&data[chat][dialogId]=chat123
&data[chat][type]=chat
&data[user][id]=1
&auth[application_token]=customFAKE-bot-token-0123456789abcdef01
&auth[domain]=your-portal.bitrix24.ru
&auth[member_id]=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
Разобранное тело — объект с тремя ключами верхнего уровня:
{
"event": "ONIMBOTV2MESSAGEADD",
"data": {
"bot": { "id": "42" },
"message": {
"id": "1501",
"text": "Привет, бот",
"params": { "FILE_ID": ["15423"] }
},
"chat": { "id": "123", "dialogId": "chat123", "type": "chat" },
"user": { "id": "1" }
},
"auth": {
"application_token": "customFAKE-bot-token-0123456789abcdef01",
"domain": "your-portal.bitrix24.ru",
"member_id": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
}
}
Поля тела
| Поле | Описание |
|---|---|
event |
Код типа события. Тот же набор кодов, что на опросе — Bot-события |
data |
Данные события. Состав повторяет объект data одноимённого события на опросе, значения приходят строками |
data.bot.id |
ID бота. Он же подставляется в путь при ответе — POST /v1/bots/:botId/messages |
data.chat.dialogId |
ID диалога для ответа: chatXXX для группового чата, ID сотрудника для личного |
data.message.id |
ID сообщения — для цитирования через replyId |
data.message.params.FILE_ID |
Массив ID вложенных файлов. Скачать — GET /files/:fileId |
auth.application_token |
Значение для проверки подлинности, см. раздел ниже |
auth.domain |
Адрес портала, с которого пришло событие |
auth.member_id |
Идентификатор портала в Битрикс24 |
Значения всех полей приходят строками — числа и логические значения тоже, это следствие формата тела. Поэтому data.message.id сравнивайте после приведения к числу, а не напрямую.
Проверка подлинности
Адрес webhookUrl доступен из интернета, поэтому обработчик обязан отличать событие портала от постороннего запроса. Признак — поле auth[application_token], и ожидаемое значение зависит от того, каким ключом бот зарегистрирован через POST /v1/bots.
| Ключ регистрации | Ожидаемое значение auth[application_token] |
|---|---|
Личный ключ vibe_api_… |
Строка custom и токен бота подряд |
| Ключ, привязанный к OAuth-приложению | application_token этого приложения — тот же, по которому приложение сверяет события подписок |
Дальше в разделе разобрана первая ветка. Для второй сравнивайте с application_token приложения, а токен бота в сверке не участвует.
Токен бота платформа выдаёт при регистрации сама и в ответах не показывает. Чтобы получить значение для сравнения, задайте свой токен — PATCH /v1/bots/:botId с полем fields.botToken: от 32 до 40 символов из алфавита [A-Za-z0-9_-]. Значение вне этих границ отклоняется с 400 BOT_TOKEN_INVALID, и токен бота остаётся прежним.
Одно и то же значение приходит либо на верхнем уровне в auth, либо вложенным в data[bot][auth] — проверяйте оба места. Не совпало — отвечайте 403 и событие не обрабатывайте.
Токен бота — секрет: он же авторизует входящие события. Храните его рядом с API-ключом и не публикуйте в клиентском коде.
Обработчик
Ниже код самого приложения, а не вызов к API Вайбкод, поэтому примера на cURL здесь нет. Пример собран под бота, зарегистрированного личным ключом: ожидаемое значение строится из токена бота. Бот зарегистрирован ключом OAuth-приложения — подставьте в EXPECTED_TOKEN application_token приложения.
import express from 'express'
const BOT_TOKEN = process.env.BOT_TOKEN // токен, заданный через PATCH fields.botToken
const EXPECTED_TOKEN = 'custom' + BOT_TOKEN
const VIBE = 'https://vibecode.bitrix24.tech/v1'
const app = express()
app.use(express.urlencoded({ extended: true }))
app.post('/bot-events', (req, res) => {
const incoming =
req.body.auth?.application_token ?? req.body.data?.bot?.auth?.application_token
if (incoming !== EXPECTED_TOKEN) return res.sendStatus(403)
// Ответ уходит до обработки: Битрикс24 ждёт ответа ограниченное время,
// а повторной доставки у события нет.
res.sendStatus(200)
handleEvent(req.body).catch((err) => console.error('Handler error:', err.message))
})
async function handleEvent({ event, data }) {
if (event !== 'ONIMBOTV2MESSAGEADD') return
// Собственный ответ бота приходит обратно — без этой проверки обработчик зациклится.
if (String(data.message?.authorId) === String(data.bot?.id)) return
await fetch(`${VIBE}/bots/${data.bot.id}/messages`, {
method: 'POST',
headers: { 'X-Api-Key': process.env.VIBE_API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({
dialogId: data.chat.dialogId,
fields: { message: `Получил: ${data.message.text}` },
}),
})
}
app.listen(3000)
Маршрутизация идёт по полю event, набор типов тот же, что на опросе. Полный отбор входящих сообщений, включая пропуск служебных, и структура data каждого типа — Bot-события.