Для 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

Разобранное тело — объект с тремя ключами верхнего уровня:

JSON
{
  "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 приложения.

javascript
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-события.

Смотрите также