#Получить события (polling)
GET /v1/bots/:botId/events
Основной механизм получения входящих сообщений и команд. Бот периодически запрашивает новые события.
Вайбкод хранит lastOffset в базе данных — при первом запросе без offset используется сохранённое значение. Это позволяет боту продолжить с места остановки после перезапуска.
#Параметры
| Параметр | Тип | Обяз. | По умолч. | Описание |
|---|---|---|---|---|
botId (path) |
number | да | — | ID бота |
offset (query) |
number | нет | из БД | Начальная позиция. Без параметра — сохранённое в БД значение. offset=0 — начать с начала |
limit (query) |
number | нет | 100 |
Максимальное количество событий (1-1000) |
withUserEvents (query) |
boolean | нет | false |
Включить user-события (ONIMV2*). Требует предварительной подписки — порядок настройки описан на странице User-события. Без подписки запрос вернёт 502 BITRIX_ERROR: User is not subscribed |
#Примеры
#curl — личный ключ
curl "https://vibecode.bitrix24.tech/v1/bots/42/events?limit=50" \
-H "X-Api-Key: YOUR_API_KEY"
#curl — OAuth-приложение
curl "https://vibecode.bitrix24.tech/v1/bots/42/events?limit=50" \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN"
#JavaScript — личный ключ
const res = await fetch('https://vibecode.bitrix24.tech/v1/bots/42/events?limit=50', {
headers: {
'X-Api-Key': 'YOUR_API_KEY',
},
})
const { success, data } = await res.json()
console.log('События:', data.events.length, 'Ещё:', data.hasMore)
#JavaScript — OAuth-приложение
const res = await fetch('https://vibecode.bitrix24.tech/v1/bots/42/events?limit=50', {
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
},
})
const { success, data } = await res.json()
#Поля ответа
| Поле | Тип | Описание |
|---|---|---|
events |
array | Массив событий (см. типы событий) |
events[].eventId |
number | ID события — передайте как offset в следующем запросе |
events[].type |
string | Код события (ONIMBOTV2MESSAGEADD, ONIMBOTV2COMMANDADD и т.д.) |
events[].date |
string | Дата и время события (ISO 8601) |
events[].data |
object | Данные события (структура зависит от типа, ключи в camelCase) |
nextOffset |
number | Смещение для следующего запроса |
hasMore |
boolean | Есть ещё необработанные события |
storedOffset |
number | Текущее сохранённое смещение в БД |
persisted |
boolean | true если lastOffset в БД продвинулся (доставлено хотя бы одно событие). false — ответ пустой, курсор не изменился |
hint |
string (optional) | Диагностическое сообщение, появляется после 5+ подряд пустых ответов — указывает на состояние установки на стороне B24 |
#Пример ответа
Есть новые события (persisted: true):
{
"success": true,
"data": {
"events": [
{
"eventId": 35,
"type": "ONIMBOTV2MESSAGEADD",
"date": "2026-04-13T17:15:00+03:00",
"data": {
"dialogId": "chat123",
"message": { "id": 1501, "text": "Привет, бот!" },
"user": { "id": 1, "name": "Иван Петров" }
}
}
],
"nextOffset": 36,
"hasMore": false,
"storedOffset": 35,
"persisted": true
}
}
Пустой ответ после нескольких запросов подряд (появляется поле hint):
{
"success": true,
"data": {
"events": [],
"nextOffset": 36,
"hasMore": false,
"storedOffset": 36,
"persisted": false,
"hint": "Events queue empty for 5+ consecutive polls. If you expect events: (1) verify the bot is registered correctly via GET /v1/bots/:botId, (2) confirm your OAuth app's INSTALL event handler responded 200 to Bitrix24, (3) try POST /v1/bots to re-register if the bot was deleted on the B24 side, (4) check that eventMode='fetch' was set when the bot was created. The Вайбкод platform forwards what B24 delivers — empty results indicate B24 is not routing events to this bot."
}
}
#Пример ответа при ошибке
404 — бот не найден:
{
"success": false,
"error": {
"code": "BOT_NOT_FOUND",
"message": "Bot 999 not found. Register it first via POST /v1/bots."
}
}
#Ошибки
| HTTP | Код | Описание |
|---|---|---|
| 400 | INVALID_BOT_ID |
botId не является числом |
| 404 | BOT_NOT_FOUND |
Бот с таким ID не найден |
| 403 | BOT_ACCESS_DENIED |
Бот принадлежит другому API-ключу |
| 502 | BITRIX_ERROR |
Ошибка Bitrix24 (текст ошибки в message) |
| 403 | SCOPE_DENIED |
API-ключ не имеет скоупа imbot |
| 401 | TOKEN_MISSING |
API-ключ не имеет настроенных токенов |
Полный список общих ошибок API — Ошибки.
#Известные особенности
Какой токен использовать. Для личного ключа vibe_api_… достаточно заголовка X-Api-Key. Для OAuth-ключа vibe_app_… обязательно добавлять Authorization: Bearer <session_token> — без Bearer запрос вернёт 401 TOKEN_MISSING. Получение session_token для OAuth-приложения — см. Ключи и авторизация.
Серверное хранение offset: Вайбкод хранит lastOffset в базе. При первом запросе без offset — используется сохранённое значение. После получения событий lastOffset обновляется автоматически, не дожидаясь результата записи.
offset=0: явная передача offset=0 начинает с начала истории — для отладки или первичной загрузки.
offset=N (конкретное значение): само событие с указанным ID попадает в ответ. Чтобы не получить дубли, всегда передавайте nextOffset из предыдущего ответа, а не eventId последнего обработанного события.
Цепочка запросов:
GET /events → { nextOffset: 42, hasMore: true }
GET /events?offset=42 → { nextOffset: 55, hasMore: false }
GET /events?offset=55 → { events: [], hasMore: false }
Рекомендуемый интервал polling: 2-5 секунд между запросами.
Polling-цикл (готовый пример):
const BOT_ID = 42
const API_KEY = 'YOUR_API_KEY'
const BASE = 'https://vibecode.bitrix24.tech/v1'
async function pollEvents() {
let offset = undefined
while (true) {
try {
const url = new URL(`${BASE}/bots/${BOT_ID}/events`)
if (offset !== undefined) url.searchParams.set('offset', String(offset))
const res = await fetch(url, {
headers: { 'X-Api-Key': API_KEY },
})
const { data } = await res.json()
for (const event of data.events ?? []) {
await handleEvent(event)
}
if (data.nextOffset !== undefined) {
offset = data.nextOffset
}
} catch (err) {
console.error('Poll error:', err.message)
}
await new Promise(r => setTimeout(r, 3000))
}
}
async function handleEvent(event) {
const { data } = event
switch (event.type) {
case 'ONIMBOTV2MESSAGEADD':
// Ответить на сообщение
await fetch(`${BASE}/bots/${BOT_ID}/messages`, {
method: 'POST',
headers: { 'X-Api-Key': API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({
dialogId: data.chat.dialogId,
fields: { message: `Получил: ${data.message.text}` },
}),
})
break
case 'ONIMBOTV2COMMANDADD':
// Ответить на команду
await fetch(`${BASE}/bots/${BOT_ID}/commands/${data.command.id}/answer`, {
method: 'POST',
headers: { 'X-Api-Key': API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({
messageId: data.message.id,
message: `Команда /${data.command.command}: ${data.command.params}`,
}),
})
break
}
}
pollEvents()
#Смотрите также
- Диагностика проблем — что делать, если
events: [],TOKEN_MISSING,INTERNAL_ERROR,BOT_DISABLED - Bot-события — 8 типов событий с примерами payload
- User-события — подписка на события чатов
- Отправить сообщение — ответ на событие
- Ответить на команду — обработка ONIMBOTV2COMMANDADD
- Бот-платформа — обзор, быстрый старт, polling-цикл
- Лимиты и оптимизация — rate limits платформы