For AI agents: markdown of this page — /docs-content-en/bots/troubleshooting.md documentation index — /llms.txt
Bot platform troubleshooting
If the bot does not reply to messages, start with the sections below. Each scenario is a separate set of checks with ready-to-use curl commands and reference responses from Vibecode.
Diagnostic scenarios
- Events do not arrive — a user writes to the bot, but
GET /v1/bots/:botId/eventsreturns an empty array - The bot was working and went silent — the bot used to reply, then stopped, and event polling no longer runs
- TOKEN_MISSING with an authorization key —
vibe_app_…sent withoutAuthorization: Bearer - Empty events in a row —
success: true, butnextOffsetdoes not move - BITRIX_ERROR: User is not subscribed —
withUserEvents=truewithout a prior subscription - INTERNAL_ERROR while polling events — a transient proxy error and a retry scheme with exponential backoff
- Bot disabled (BOT_DISABLED) — automatic disabling on
AUTH_FAILURESorPORTAL_DELETED - The code is taken but the bot is missing from the list —
409 BOT_ALREADY_EXISTSon registration and an emptyGET /v1/bots - fetch vs webhook differences — the difference in data formats and delivery behavior
- Stickers — a platform limitation
- Bot API v2 methods are missing from the Bitrix24 REST method list — the Bitrix24 REST method list does not include Bot API v2 names
- Where to reach out — what to attach to a support ticket
Events do not arrive
Symptom: a user writes to the bot in a Bitrix24 chat, the bot does not reply, GET /v1/bots/:botId/events returns events: [].
Checklist in order
- The bot is registered and active.
GET /v1/bots/:botIdreturnssuccess: truewith the fieldsbot.id,bot.code,bot.eventMode. If 404 — the bot is not registered, runPOST /v1/bots. eventMode: "fetch". Checked in the response of step 1. Ifwebhook— events do not arrive via polling, Bitrix24 delivers them towebhookUrl.- The bot type matches the scenario. A bot of type
botonly receives messages with an@mentionand direct messages. To receive all messages in a chat you need the typepersonalorsupervisor— it is specified at registration in thetypefield and cannot be changed afterwards. If you expect all messages but the type isbot, events will arrive only on an@mention. - The bot is added to the chat. The bot receives events only from chats it is a member of. For a direct dialog this happens on the user's first interaction with the bot. For a group chat the bot must be added explicitly via
POST /v1/bots/:botId/chats/:dialogId/users. - The user is writing to this exact bot. If your Bitrix24 account has several bots, check the
codeof the bot being addressed in the chat and compare it with thecodein theGET /v1/bots/:botIdresponse. Messages to another bot will not land in this bot's queue. - After 5+ empty polls, check the
hintfield in theGET /v1/bots/:botId/eventsresponse. The platform adds a diagnostic hint if the queue has been empty for several polls in a row. - Re-bind the event subscription. If the bot is active (messages are reaching the chats) but the queue is empty and the
hintfield has appeared, callPOST /v1/bots/:botId/resubscribe. Re-binding restores delivery and preserves the bindings of Open Channels and the welcome bot, unlike re-registering viaPOST /v1/bots.
If all 7 items pass but the queue is still empty — it means the Bitrix24 account is not routing events to the bot. Collect the data from the Where to reach out section and submit a ticket.
The checklist assumes polling is running. If the bot replied at first and then went silent, and polling no longer runs, start with the next section.
The bot was working and went silent
Symptom: the bot used to reply to messages, then stopped. The last GET /v1/bots/:botId/events call went through without errors, no new requests come from the bot, and user messages go unanswered.
Cause
The virtual machine the bot runs on has been stopped by the idle timeout — on a new machine it is 60 minutes. The bot sends its event polls outbound, while only inbound requests to the application reset the timer, so polling does not keep the machine online. After an hour without inbound requests it stops together with the bot process. How to avoid this when starting a bot — Where the bot runs.
Check
curl -H "X-Api-Key: YOUR_API_KEY" \
https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID
On a stopped machine data.status is sleeping, and the timeout in effect is returned in data.sleepAfterMinutes.
Solution
Disable auto-sleep and wake the machine:
# Disable auto-sleep — only null is accepted,
# 0 is rejected with VALIDATION_ERROR
curl -X PATCH https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/sleep \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"sleepAfterMinutes": null}'
# Wake it and wait until it is ready
curl -X POST -H "X-Api-Key: YOUR_API_KEY" \
"https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/wake?wait=true"
An application deployed through the Deploy API comes up together with the machine: the deploy creates a systemd autostart unit unless you passed systemd: false.
Confirm it in the chat: message the bot in a Bitrix24 chat and wait for its reply — that proves polling works again. The bot has to be the first to collect the events that piled up while the machine slept: a GET /v1/bots/:botId/events response advances the cursor stored on the server, so events handed to a manual call never reach the bot. If no reply arrives in the chat, check the service log — GET /v1/infra/servers/:id/logs.
The allowed timeout values and the mutual exclusion with wake-schedule windows — Configure auto-sleep.
TOKEN_MISSING with an authorization key
Symptom:
{ "success": false, "error": { "code": "TOKEN_MISSING", "message": "API key has no tokens configured." } }
Cause
The vibe_app_… key was sent without the Authorization: Bearer <session_token> header. An authorization key works in tandem with a user session token — without Bearer the request has no context identifying the user on whose behalf to call Bitrix24.
Solution
A personal key vibe_api_… — no Bearer needed:
curl https://vibecode.bitrix24.com/v1/bots/42/events \
-H "X-Api-Key: YOUR_API_KEY"
An authorization key vibe_app_… — Bearer is mandatory:
curl https://vibecode.bitrix24.com/v1/bots/42/events \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN"
Obtaining the USER_SESSION_TOKEN for an OAuth app — see Keys and authorization.
This error also comes up in an application-side event handler that calls the V1 API in response to a delivered event. The handler has no user session, so a vibe_app_ key does not work there — use a personal vibe_api_ key. See Application-side handler.
Empty events in a row
Symptom: the response is correct, there are no errors, but events: [], nextOffset === storedOffset, persisted: false.
What the response fields mean
persisted: false— thelastOffsetcursor in the Vibecode database did not move, because Bitrix24 did not return a single event.nextOffset === storedOffset— nothing to process.hintappears after 5+ empty polls in a row — a diagnostic hint.
This is normal if
- the bot was just registered — nobody has messaged it yet
- the queue is empty — clients have read all messages
- there is no activity in chats with the bot between polls.
When to move on to diagnostics
If at least one condition holds — go back to the Events do not arrive section:
- there are unread messages to the bot in the chat
- more than a minute has passed since the message was sent
- the
hintfield has appeared.
BITRIX_ERROR: User is not subscribed
Symptom: GET /v1/bots/:botId/events?withUserEvents=true returns 422 with this message.
Cause
User events (types ONIMV2* — chat changes, user reactions) require a separate subscription. Without a subscription the withUserEvents=true parameter does not enable delivery.
Solution
Subscribe once before using withUserEvents=true. The full setup procedure and the list of events are in the User events section.
After subscribing, GET /v1/bots/:botId/events?withUserEvents=true starts returning user events together with bot events in the same array.
INTERNAL_ERROR while polling events
Symptom:
{ "success": false, "error": { "code": "INTERNAL_ERROR", "message": "Internal server error" } }
What to do
- Do not repeat the request right away. Retries without a pause prolong the error state and become a cause of overload in their own right.
- Use exponential backoff between attempts — start at 5 seconds, double on each subsequent failure, cap at 60 seconds. After a successful response the interval resets to the working value (2-5 seconds between polls).
- Do not reset
offset. The stored cursor was not affected — continue from the same value. A reset leads to reprocessing already delivered events. - If the error does not go away after several delay cycles — submit a support ticket with the
botId, the time of first occurrence, the last successfulnextOffset, and the interval between attempts. Do not increase the request frequency "just in case" — it will make things worse.
Ready-to-use template with exponential backoff
const BOT_ID = 42
const API_KEY = 'YOUR_API_KEY'
const BASE = 'https://vibecode.bitrix24.com/v1'
let backoffMs = 5000
while (true) {
try {
const res = await fetch(`${BASE}/bots/${BOT_ID}/events`, {
headers: { 'X-Api-Key': API_KEY },
})
const json = await res.json()
if (!json.success && json.error?.code === 'INTERNAL_ERROR') {
console.warn(`INTERNAL_ERROR — pause ${backoffMs} ms`)
await new Promise(r => setTimeout(r, backoffMs))
backoffMs = Math.min(backoffMs * 2, 60000)
continue
}
backoffMs = 5000
for (const event of json.data?.events ?? []) {
// handle the event
}
} catch {
await new Promise(r => setTimeout(r, backoffMs))
backoffMs = Math.min(backoffMs * 2, 60000)
}
await new Promise(r => setTimeout(r, 3000))
}
Plan access while polling on .com. The international instance uses the Bitrix24 plan model.
A plan denial remains separate from BOT_DISABLED. After a plan upgrade, call
GET /v1/me?refresh=tariff to refresh access state. /reauth and /resubscribe solve credential
and event-binding problems, not plan access.
Bot disabled (BOT_DISABLED)
Symptom:
{ "success": false, "error": { "code": "BOT_DISABLED", "message": "Bot is disabled. This bot will not process API calls until it is re-enabled.", "details": { "reauthAllowed": true } } }
HTTP code — 410 Gone. All bot endpoints are affected: events, messages, chats, commands, update, delete.
The message intentionally does not expose an internal reason. The only client-facing recovery
signal is strict boolean error.details.reauthAllowed.
Solution
When reauthAllowed=true, call POST /v1/bots/:botId/reauth. The check confirms the bot's access, refreshes the token if needed, and clears the disabled state. If the response is 410 REAUTH_REQUIRED, access cannot be restored automatically; re-authorize the key via OAuth or recreate the personal key.
When reauthAllowed=false, do not call /reauth: ordinary disabled states return
409 BOT_REAUTH_NOT_ALLOWED. If ownership or state changes during the probe, the response is
409 BOT_REAUTH_STATE_CHANGED, and the newer state is preserved. Manual /reauth also remains
the active post-transfer credential probe.
To reset only the authorization error counter, without an access check, use PATCH /v1/bots/:botId with the body {"disabled": false}:
curl -X PATCH https://vibecode.bitrix24.com/v1/bots/42 \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"disabled": false}'
PORTAL_DELETED — the bot is restored automatically when the Bitrix24 account returns to the ACTIVE status. Forced enabling via PATCH is not required for this reason value.
PATCH … {"disabled": true} is forbidden — it returns 400 DISABLE_NOT_ALLOWED. Disabling is system-imposed. To delete, use DELETE /v1/bots/:botId.
The code is taken but the bot is missing from the list
Symptom: POST /v1/bots responds with 409 BOT_ALREADY_EXISTS, while GET /v1/bots under the same key returns an empty bots array.
Cause
The bot was registered by another key of this Bitrix24 account — for example, the key was re-created together with the application. The bot list is filtered by the calling key, so someone else's bot never lands in it, while code uniqueness is checked across the whole account, so the code stays taken.
Solution
The identifier of the existing bot arrives in the data.botId field of the 409 response — use it to transfer ownership to your key, and the bot keeps its chats and history. The step-by-step procedure, the target key requirements and the error codes are in Bot access recovery.
fetch vs webhook differences
Vibecode supports two event delivery modes: fetch (default) and webhook. The mode is set by the eventMode field at bot registration and does not change afterwards.
fetch |
webhook |
|
|---|---|---|
| How it works | The client requests events itself via GET /v1/bots/:botId/events |
Bitrix24 pushes events as HTTP POST to webhookUrl |
| Value types | Preserved: number, boolean, null |
Everything arrives as strings ("1", "true", "") — a consequence of body serialization on the Bitrix24 side |
The bot object in an event |
Without the auth field |
Contains auth with the Bitrix24 account's OAuth tokens |
| Timeout | None (long polling) | 10 seconds — Bitrix24 waits for a 200 from your server and closes the connection |
| Redelivery | Server-side offset storage — an event cannot be missed | No automatic retries on timeout or a 5xx response |
| Body format | JSON in the GET /v1/bots/:botId/events response |
application/x-www-form-urlencoded in Bitrix24's own format (event=…&data[bot][id]=…&auth[member_id]=…) |
| When to choose | Most scenarios, especially AI agents and closed apps on a personal key | When you need minimal reaction time and have a publicly accessible server |
With eventMode: "webhook", GET /v1/bots/:botId/events always returns an empty array — events are delivered directly to webhookUrl and never land in the polling queue.
webhook requires a publicly reachable URL
In webhook mode, Bitrix24 sends events as a POST request directly to webhookUrl — without a user signing in to Vibecode. So webhookUrl must be publicly reachable from the internet.
If webhookUrl points at a Black Hole server, whether the event reaches the app depends on that server's key.
The key is bound to an OAuth application. The event carries the auth[application_token] of that application, the platform recognizes the sender and lets the request through under any access policy. There is no need to change the policy.
A personal vibe_api_… key. There is no way to identify the sender, so only the PUBLIC policy accepts the event. Under OWNER_ONLY (the default), NAMED_USERS, DEPARTMENT, PORTAL, and AUTHENTICATED the request is rejected, and the event never reaches the app. There are two options. Switch the server to the PUBLIC policy via PATCH /v1/infra/servers/:id/access-policy — it opens the subdomain to everyone without authorization, so enable it deliberately. Or receive events by polling: eventMode: "fetch" and GET /v1/bots/:botId/events.
An option for both cases is to specify an external publicly reachable webhookUrl, not on a Black Hole subdomain.
A server created for an AI agent always stays on the OWNER_ONLY policy — it cannot be changed. For a webhook bot on such a server, use an external publicly reachable webhookUrl.
The server must be running when the event arrives. A sleeping Black Hole server will not receive the event, and there are no delivery retries — for a webhook bot, disable automatic sleep so the server stays available. The same timeout also stops the machine of a bot in fetch mode, because outbound polling does not reset it: see The bot was working and went silent.
The reachability of webhookUrl is not verified at registration — the bot will register even with an unreachable address.
Stickers
Bots cannot send stickers to users. This is a limitation of the Bitrix24 Bot API v2.
Bots can receive stickers: if a user sends a sticker, the ONIMBOTV2MESSAGEADD event arrives, but the message.text field will be empty. You can react to stickers by sending a text message or an attachment via POST /v1/bots/:botId/messages.
Bot API v2 methods are missing from the Bitrix24 REST method list
Symptom: the integration calls the methods REST method on the Bitrix24 account with no parameters and looks for Bot API v2 method names in the response, for example imbot.v2.Chat.Message.send. Those names are not in the response, and the integration concludes that sending messages and bot reactions are unavailable.
Cause
The Bitrix24 REST method list is incomplete with regard to Bot API v2. Some bot methods are present in it under previous-generation names, and version 2 methods are not part of that list. A check of the form "is the name in the list" therefore reports a capability as missing even though it works on the account. This is Bitrix24 platform behavior, not a Vibecode limitation.
A name missing from the list and a method missing from the account produce different answers: a call to a name that does not exist returns a "method not found" refusal, and a call to a Bot API v2 method with incomplete parameters returns a missing-parameter error. This explains the symptom, but it is not a way to check availability: bot capabilities on Vibecode are defined by the endpoint reference, not by the account's responses.
Solution
Do not use the Bitrix24 REST method list to check bot capabilities. The procedure is:
- Register the bot — Register a bot,
POST /v1/bots. - Receive events — Get events (polling),
GET /v1/bots/:botId/events. - Send messages — Send message,
POST /v1/bots/:botId/messages. - Add and remove reactions — Add reaction, Remove reaction.
The full list of bot capabilities is the Endpoint reference: every Vibecode bot platform endpoint and the Bitrix24 method behind it.
The bot platform revision of the account is returned by Bot platform revision, GET /v1/bots/revision. A growing data.rest value means that new REST capabilities of the bot platform have appeared on the account. It is a revision number, not a list of endpoints: there is no "number — capability" mapping, and no threshold such as "reactions are available once rest reaches N".
Where to reach out
If none of the sections above helped — leave a ticket in the Feedback section. Attach the following to the ticket:
- the
botId(a number) - the full
GET /v1/bots/:botIdresponse - the last 3
GET /v1/bots/:botId/eventsresponses with the fieldsnextOffset,storedOffset,persisted,hint - the time when the symptom first appeared (UTC)
- the key type (
vibe_api_…orvibe_app_…) — without the key itself - a screenshot of the chat with the unread message, if any.