#Бот-платформа

33 REST-эндпоинта для создания чат-ботов Битрикс24. Не нужны вебхуки и публичный сервер — бот опрашивает события через polling и отвечает через HTTP.

Скоуп: imbot | Базовый URL: https://vibecode.bitrix24.tech/v1 | Авторизация: X-Api-Key

Быстрый старт | Echo-бот (пример) | Коды ошибок | Справочник эндпоинтов

#Разделы документации

  • Управление ботами — регистрация, обновление, удаление
  • События — polling входящих сообщений и команд
  • Сообщения — отправка, редактирование, удаление, форматирование
  • Чаты — создание чатов, управление участниками и менеджерами
  • Команды — slash-команды бота
  • Интерфейс — реакции, индикатор набора, поле ввода
  • Файлы — загрузка и скачивание

#Быстрый старт

#1. Зарегистрируйте бота

Terminal
curl -X POST https://vibecode.bitrix24.tech/v1/bots \
  -H "X-Api-Key: $VIBE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "my_helper_bot",
    "name": "Помощник",
    "type": "bot",
    "eventMode": "fetch"
  }'

Ответ:

JSON
{
  "success": true,
  "data": {
    "botId": 42,
    "code": "my_helper_bot",
    "name": "Помощник",
    "type": "bot",
    "eventMode": "fetch"
  }
}

#2. Получайте события (long-polling)

Terminal
curl -H "X-Api-Key: $VIBE_KEY" \
  "https://vibecode.bitrix24.tech/v1/bots/42/events"

Ответ содержит nextOffset — передайте его как offset в следующем запросе:

JSON
{
  "success": true,
  "data": {
    "events": [
      {
        "eventId": 35,
        "type": "ONIMBOTV2MESSAGEADD",
        "date": "2026-04-13T10:05:00+03:00",
        "data": {
          "dialogId": "12",
          "bot": { "id": 42, "code": "my_helper_bot", "type": "bot" },
          "message": {
            "id": 1501,
            "chatId": 87,
            "authorId": 1,
            "date": "2026-04-13T10:05:00+03:00",
            "text": "Привет, бот!"
          },
          "chat": { "id": 87, "dialogId": "12", "type": "private" },
          "user": { "id": 1, "name": "Иван Петров", "firstName": "Иван", "lastName": "Петров" }
        }
      }
    ],
    "nextOffset": 36,
    "hasMore": false,
    "storedOffset": 0
  }
}

Следующий запрос:

Terminal
curl -H "X-Api-Key: $VIBE_KEY" \
  "https://vibecode.bitrix24.tech/v1/bots/42/events?offset=42"

#3. Отправьте ответ

Terminal
curl -X POST https://vibecode.bitrix24.tech/v1/bots/42/messages \
  -H "X-Api-Key: $VIBE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "dialogId": "12",
    "fields": { "message": "Привет! Чем могу помочь?" }
  }'

Ответ:

JSON
{
  "success": true,
  "data": {
    "id": 1502,
    "uuidMap": []
  }
}

#Полный пример: Echo-бот

javascript
const VIBE_KEY = process.env.VIBE_KEY
const BASE = 'https://vibecode.bitrix24.tech/v1'

// ── 1. Регистрация бота ─────────────────────────────────────────
const regRes = await fetch(`${BASE}/bots`, {
  method: 'POST',
  headers: { 'X-Api-Key': VIBE_KEY, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    code: 'echo_bot',
    name: 'Echo Bot',
    type: 'bot',
    color: 'AQUA',
    eventMode: 'fetch',
    workPosition: 'Повторяет ваши сообщения'
  })
})
const { data: bot } = await regRes.json()
const BOT_ID = bot.botId

console.log(`Bot registered with ID: ${BOT_ID}`)

// ── 2. Регистрация slash-команд ─────────────────────────────────
await fetch(`${BASE}/bots/${BOT_ID}/commands`, {
  method: 'POST',
  headers: { 'X-Api-Key': VIBE_KEY, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    command: 'ping',
    title: 'Ping',
    description: 'Проверить, жив ли бот'
  })
})

await fetch(`${BASE}/bots/${BOT_ID}/commands`, {
  method: 'POST',
  headers: { 'X-Api-Key': VIBE_KEY, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    command: 'help',
    title: 'Помощь',
    description: 'Показать список команд'
  })
})

// ── 3. Polling-цикл ─────────────────────────────────────────────
let offset = undefined

async function poll() {
  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': VIBE_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

  // ── Обработка сообщений ────────────────────────────────────
  if (event.type === 'ONIMBOTV2MESSAGEADD') {
    const dialogId = data.dialogId
    const text = data.message?.text || ''
    const userName = data.user?.firstName || 'друг'

    // Пропускаем системные сообщения и свои собственные
    if (data.message?.isSystem) return
    if (data.message?.authorId === BOT_ID) return

    // Показываем "думает..."
    await fetch(`${BASE}/bots/${BOT_ID}/typing`, {
      method: 'POST',
      headers: { 'X-Api-Key': VIBE_KEY, 'Content-Type': 'application/json' },
      body: JSON.stringify({
        dialogId,
        statusMessageCode: 'IMBOT_AGENT_ACTION_THINKING'
      })
    })

    // Ставим реакцию на сообщение
    await fetch(`${BASE}/bots/${BOT_ID}/messages/${data.message.id}/reactions`, {
      method: 'POST',
      headers: { 'X-Api-Key': VIBE_KEY, 'Content-Type': 'application/json' },
      body: JSON.stringify({ reaction: 'like' })
    })

    // Отправляем эхо-ответ с клавиатурой
    await fetch(`${BASE}/bots/${BOT_ID}/messages`, {
      method: 'POST',
      headers: { 'X-Api-Key': VIBE_KEY, 'Content-Type': 'application/json' },
      body: JSON.stringify({
        dialogId,
        fields: {
          message: `${userName}, вы написали: [I]${text}[/I]`,
          keyboard: [
            {
              TEXT: 'Повторить',
              BG_COLOR_TOKEN: 'primary',
              ACTION: 'SEND',
              ACTION_VALUE: text || 'ping',
              BLOCK: 'Y'
            },
            {
              TEXT: 'Помощь',
              BG_COLOR_TOKEN: 'secondary',
              ACTION: 'SEND',
              ACTION_VALUE: '/help',
              DISPLAY: 'LINE'
            }
          ]
        }
      })
    })
  }

  // ── Обработка команд ───────────────────────────────────────
  if (event.type === 'ONIMBOTV2COMMANDADD') {
    const dialogId = data.dialogId
    const command = data.command

    if (command.command === 'ping') {
      await fetch(`${BASE}/bots/${BOT_ID}/commands/${command.id}/answer`, {
        method: 'POST',
        headers: { 'X-Api-Key': VIBE_KEY, 'Content-Type': 'application/json' },
        body: JSON.stringify({
          messageId: data.message.id,
          message: '[B]Pong![/B] Бот работает нормально.'
        })
      })
    }

    if (command.command === 'help') {
      await fetch(`${BASE}/bots/${BOT_ID}/commands/${command.id}/answer`, {
        method: 'POST',
        headers: { 'X-Api-Key': VIBE_KEY, 'Content-Type': 'application/json' },
        body: JSON.stringify({
          messageId: data.message.id,
          message: '[B]Echo Bot — Команды[/B]\n\n/ping — проверить, жив ли бот\n/help — показать этот список\n\nПросто напишите мне — я повторю ваше сообщение.'
        })
      })
    }
  }

  // ── Обработка реакций ──────────────────────────────────────
  if (event.type === 'ONIMBOTV2REACTIONCHANGE') {
    const dialogId = data.dialogId
    const userName = data.user?.firstName || 'Кто-то'

    if (data.action === 'add') {
      await fetch(`${BASE}/bots/${BOT_ID}/messages`, {
        method: 'POST',
        headers: { 'X-Api-Key': VIBE_KEY, 'Content-Type': 'application/json' },
        body: JSON.stringify({
          dialogId,
          fields: {
            message: `${userName} поставил реакцию: ${data.reaction}`,
            system: true
          }
        })
      })
    }
  }

  // ── Вход в чат ─────────────────────────────────────────────
  if (event.type === 'ONIMBOTV2JOINCHAT') {
    await fetch(`${BASE}/bots/${BOT_ID}/messages`, {
      method: 'POST',
      headers: { 'X-Api-Key': VIBE_KEY, 'Content-Type': 'application/json' },
      body: JSON.stringify({
        dialogId: data.dialogId,
        fields: {
          message: 'Привет! Я Echo Bot. Напишите мне что-нибудь, и я повторю.\n\nКоманды:\n[SEND=/ping]Ping[/SEND] | [SEND=/help]Помощь[/SEND]'
        }
      })
    })
  }
}

poll()

#Коды ошибок

#Ошибки бот-платформы

Код HTTP Описание
SCOPE_DENIED 403 API-ключ не имеет скоупа imbot
TOKEN_MISSING 401 API-ключ не имеет настроенных токенов
CODE_REQUIRED 400 Не передан параметр code при регистрации
NAME_REQUIRED 400 Не передан параметр name при регистрации
INVALID_BOT_ID 400 botId должен быть числом
BOT_NOT_FOUND 404 Бот с таким ID не найден — зарегистрируйте через POST /v1/bots
BOT_ACCESS_DENIED 403 Бот принадлежит другому API-ключу
BOT_ALREADY_EXISTS 409 Бот с таким code уже зарегистрирован. Ответ содержит data с botId
REGISTRATION_FAILED 502 Битрикс24 не вернул ID бота при регистрации

#Системные ошибки

Код HTTP Описание
AUTH_REQUIRED 401 Отсутствует заголовок X-Api-Key
INVALID_KEY 401 Неверный API-ключ
KEY_REVOKED 403 API-ключ отозван
RATE_LIMIT 429 Превышен лимит запросов
BITRIX_ERROR 502 Ошибка в ответе Bitrix24 API
BITRIX_UNAVAILABLE 502 Портал Битрикс24 недоступен
INTERNAL_ERROR 500 Внутренняя ошибка сервера

#Справочник эндпоинтов

Все 33 эндпоинта бот-платформы:

Метод Путь Bitrix24 метод Описание
POST /v1/bots imbot.v2.Bot.register Регистрация бота
GET /v1/bots Список ботов
GET /v1/bots/:botId imbot.v2.Bot.get Данные бота
PATCH /v1/bots/:botId imbot.v2.Bot.update Обновление бота
DELETE /v1/bots/:botId imbot.v2.Bot.unregister Удаление бота
GET /v1/bots/:botId/events imbot.v2.Event.get Получение событий (polling)
POST /v1/bots/:botId/messages imbot.v2.Chat.Message.send Отправка сообщения
PATCH /v1/bots/:botId/messages/:messageId imbot.v2.Chat.Message.update Обновление сообщения
DELETE /v1/bots/:botId/messages/:messageId imbot.v2.Chat.Message.delete Удаление сообщения
POST /v1/bots/:botId/chats/:dialogId/read imbot.v2.Chat.Message.read Прочитать сообщения
GET /v1/bots/:botId/messages/:messageId imbot.v2.Chat.Message.get Получить сообщение
GET /v1/bots/:botId/messages/:messageId/context imbot.v2.Chat.Message.getContext Контекст сообщения
POST /v1/bots/:botId/messages/:messageId/reactions imbot.v2.Chat.Message.Reaction.add Добавить реакцию
DELETE /v1/bots/:botId/messages/:messageId/reactions imbot.v2.Chat.Message.Reaction.delete Удалить реакцию
POST /v1/bots/:botId/typing imbot.v2.Chat.InputAction.notify Индикатор набора
POST /v1/bots/:botId/text-field imbot.v2.Chat.TextField.enabled Управление полем ввода
POST /v1/bots/:botId/chats imbot.v2.Chat.add Создание чата
GET /v1/bots/:botId/chats/:dialogId imbot.v2.Chat.get Информация о чате
PATCH /v1/bots/:botId/chats/:dialogId imbot.v2.Chat.update Обновление чата
POST /v1/bots/:botId/chats/:dialogId/leave imbot.v2.Chat.leave Покинуть чат
POST /v1/bots/:botId/chats/:dialogId/owner imbot.v2.Chat.setOwner Назначить владельца
POST /v1/bots/:botId/chats/:dialogId/users imbot.v2.Chat.User.add Добавить участников
DELETE /v1/bots/:botId/chats/:dialogId/users imbot.v2.Chat.User.delete Удалить участника
GET /v1/bots/:botId/chats/:dialogId/users imbot.v2.Chat.User.list Список участников
POST /v1/bots/:botId/chats/:dialogId/managers imbot.v2.Chat.Manager.add Добавить менеджеров
DELETE /v1/bots/:botId/chats/:dialogId/managers imbot.v2.Chat.Manager.delete Удалить менеджеров
POST /v1/bots/:botId/commands imbot.v2.Command.register Регистрация команды
GET /v1/bots/:botId/commands imbot.v2.Command.list Список команд
PATCH /v1/bots/:botId/commands/:commandId imbot.v2.Command.update Обновление команды
DELETE /v1/bots/:botId/commands/:commandId imbot.v2.Command.unregister Удаление команды
POST /v1/bots/:botId/commands/:commandId/answer imbot.v2.Command.answer Ответ на команду
POST /v1/bots/:botId/files imbot.v2.File.upload Загрузка файла
GET /v1/bots/:botId/files/:fileId imbot.v2.File.download Скачивание файла