Для AI-агентов: markdown этой страницы — /docs-content/errors.md индекс документации — /llms.txt
Коды ошибок
Справочник кодов ошибок API Вайбкод: единый формат ответа, перечень кодов, типичные причины и способы устранения. Применяется ко всем эндпоинтам /v1/....
Формат ответа при ошибке
Каждый ответ с ошибкой возвращается в едином виде. error — объект.
{
"success": false,
"error": {
"code": "ENTITY_NOT_FOUND",
"message": "Элемент не найден"
}
}
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
success |
boolean | да | При ошибке всегда false |
error.code |
string | да | Машиночитаемый код ошибки. Используйте для различения типов ошибок в коде клиента |
error.message |
string | да | Описание ошибки для разработчика. Язык заранее не известен и зависит от источника: технические сообщения платформы приходят на английском, сообщения от Битрикс24 — на языке портала, сообщения о сбоях облачного провайдера локализуются под язык пользователя. Не разбирайте текст и не полагайтесь на его язык — ветвитесь по error.code |
error.hint |
string | object | нет | Подсказка для разработчика: что попробовать дальше, на какие пределы обратить внимание. Строка с текстом либо, на эндпоинтах создания инфраструктуры POST /v1/infra/servers, объект с полями reason, recovery и example — в example готовое тело запроса для исправления |
error.userMessage |
string | нет | Сообщение для конечного пользователя на русском языке. Появляется в биллинговых, инфраструктурных и тарифных ошибках, при перегрузке очереди портала и в отказах лимитера рабочего времени портала |
error.details |
object | нет | Машиночитаемый контекст отдельных кодов. Примеры: reason в INVALID_STATE, deployableKeys в INFRA_FORBIDDEN_FOR_COWORK_KEY, upgradeUrl в отказах по подписке, method и switchUrl в WRITE_BLOCKED_READONLY_KEY. Набор полей зависит от кода — читайте его описание |
error.warning |
string | нет | Появляется при повторяющихся одинаковых ошибках на одном ключе — вероятный признак ошибки в коде клиента. Счётчик эвристический, поэтому предупреждение не гарантирует наличие ошибки |
error.retryAfter |
number | нет | Секунды до следующей попытки. Появляется в 429 (rate-limit, очередь портала — QUEUE_OVERFLOW/QUEUE_TIMEOUT, лимитер рабочего времени портала — OPERATION_TIME_LIMIT) и в транзиентных 503 (BITRIX_TIMEOUT, POOL_EXHAUSTED, DB_TRANSIENT, SERVICE_UNAVAILABLE). У LARGE_BODY_BACKEND_BUSY поле приходит не на всех путях отказа — там берите срок из заголовка Retry-After |
error.b24Code |
string | нет | Машиночитаемый код причины от Битрикс24 в ответах 422 BITRIX_ERROR. Приходит не всегда — только когда Битрикс24 прислал отдельный код |
error.release |
string | нет | Идентификатор обновления Битрикс24, которого ждёт портал: имя модуля и номер версии одной строкой, например imopenlines 26.700.0. Приходит только в METHOD_NOT_YET_AVAILABLE |
error.scope |
string | нет | Радиус отказа по лимиту: "apiKey" — приостановлен только вызывающий ключ, "portal" — пауза действует на весь портал Битрикс24 и её видят все его ключи. Появляется в OPERATION_TIME_LIMIT ("apiKey"), TIMEOUT_QUARANTINE ("portal") и FEEDBACK_QUOTA_EXCEEDED (оба значения). Различает «чинить свой код» и «ждать вместе с порталом» |
Пример ответа с дополнительными полями (429 RATE_LIMITED):
{
"success": false,
"error": {
"code": "RATE_LIMITED",
"message": "QUERY_LIMIT_EXCEEDED",
"hint": "Wait 1-2 seconds and retry. Use POST /v1/batch to combine up to 50 calls in 1 request.",
"retryAfter": 2
}
}
HTTP-заголовок Retry-After дублирует значение error.retryAfter для совместимости со стандартом HTTP. Есть отказы, где поле в теле не приходит, а заголовок — приходит, поэтому опирайтесь на заголовок.
Сводная таблица кодов
Таблица покрывает основные коды, которые встречаются на любом эндпоинте API Вайбкод. Доменные коды (BOT_NOT_FOUND, SERVER_NOT_RUNNING, AGENT_LIMIT_REACHED и подобные) описаны на страницах соответствующих разделов.
Авторизация и ключи
| Код | HTTP | Когда возникает |
|---|---|---|
MISSING_API_KEY |
401 | Запрос без заголовка X-Api-Key |
INVALID_API_KEY |
401 | Ключ не найден в системе или формат не распознан |
INVALID_APP_KEY |
401 | Передан vibe_app_*, но без сопровождающего Authorization: Bearer ... |
WRONG_AUTH_SCHEME |
401 | API-ключ передан в заголовке Authorization: Bearer. Ключ OAuth-приложения (vibe_app_*) передаётся в X-Api-Key, а Authorization: Bearer несёт сессионный токен (vibe_session_*). Клиенту, который умеет только Bearer, используйте личный ключ (vibe_api_*) — он принимается в Authorization: Bearer |
TOKEN_EXPIRED |
401 | Срок действия OAuth-токена истёк |
TOKEN_REFRESH_FAILED |
401 | Не удалось обновить OAuth-токен на стороне Битрикс24 |
WRONG_KEY_TYPE |
401 | Тип ключа не подходит к эндпоинту: например, management-ключ на entity-маршруте |
WRONG_KEY |
403 | Сервер существует, но привязан к другому API-ключу. Операции над содержимым приложения — выкладка, команда, загрузка файла и чтение логов — принимают либо управляющий ключ сервера, либо ключ, приложение которого привязано к этому серверу. Управление машиной, токены доступа и загрузка значка требуют управляющего ключа. В ответе — hint с восстановлением из двух шагов: перепривязать сервер в кабинете и сменить ключ, которым обращается клиент. Подробнее — восстановление доступа |
TOKEN_MISSING |
401 | У ключа нет кредов Битрикс24. Для личного ключа (vibe_api_*) — нет вебхука портала, причина приходит в error.details. Для ключа приложения (vibe_app_*) — не передан Authorization: Bearer с токеном сессии |
SESSION_REQUIRED |
401 | Операция с местами встраивания выполнена без заголовка Authorization: Bearer с токеном сессии там, где аккаунт его требует |
SESSION_APP_MISMATCH |
403 | Сессия в Authorization: Bearer выписана другому приложению или другому аккаунту Битрикс24, чем ключ в X-Api-Key. Передайте ключ авторизации того приложения, которое выписало сессию через POST /v1/oauth/token |
PERSONAL_KEY_WEBHOOK_SCOPES_INVALID |
400 | Выписка или обновление ключа портала, где placement и entity запрошены, а кроме них в наборе прав ничего нет. Ключ портала стоит на входящем вебхуке Битрикс24, а такие права вебхук не несёт — добавьте право на данные либо заведите OAuth-приложение. Приходит на создании и обновлении ключа, подробнее — менеджмент-ключи |
ACCOUNT_PENDING_ERASURE |
503 | Аккаунт владельца ключа ждёт удаления данных — на это время ключ заморожен. В ответе заголовок Retry-After: 3600. Действует на любой ключ владельца, включая менеджмент-ключ. Отмена запроса на удаление возвращает ключу работу, перевыпускать его не нужно |
Состояние аккаунта Битрикс24
Состояние аккаунта, к которому привязан ключ, проверяется на каждом вызове. Отказы этой группы не привязаны к эндпоинту: пока аккаунт в одном из перечисленных состояний, ключ получает их на маршрутах /v1/..., у которых нет собственного отказа для этого состояния, и повтор запроса ничего не меняет.
| Код | HTTP | Когда возникает |
|---|---|---|
PORTAL_SUSPENDED |
403 | Аккаунт приостановлен |
PORTAL_DELETED |
403 | Аккаунт удалён |
PORTAL_BLOCKED |
403 | Аккаунт заблокирован. Рядом с кодом приходит blockedAt — момент блокировки в формате ISO 8601. Причину блокировки ответ не раскрывает |
NO_PORTAL |
401 | Ключ не привязан ни к одному аккаунту. Исключение — маршруты хранилища: непривязанный ключ получает там 403 STORAGE_REQUIRES_PORTAL_BINDING. Тот же код с HTTP 500 приходит на маршрутах авторизации пользователей приложения и означает там другое — приложение не связано с аккаунтом |
Авторизация пользователей приложения (OAuth)
| Код | HTTP | Когда возникает |
|---|---|---|
INVALID_REDIRECT_URI |
400 | redirect_uri не зарегистрирован у приложения на входе GET /v1/oauth/authorize |
INVALID_STATE |
400 | state не найден или истёк за 20 минут на приёме ответа Битрикс24. В error.details.reason — NOT_FOUND или EXPIRED |
INVALID_CODE |
400 | Код авторизации не найден или принадлежит другому приложению |
CODE_EXPIRED |
400 | Срок действия кода авторизации прошёл — 5 минут |
CODE_ALREADY_USED |
400 | Код авторизации уже обменян на токен сессии |
REDIRECT_URI_MISMATCH |
400 | redirect_uri при обмене кода не совпадает с переданным на входе |
DOMAIN_MISMATCH |
400 | domain в POST /v1/oauth/placement-session не совпадает с порталом приложения |
USER_AUTH_REQUIRED |
401 | Токен пользователя Битрикс24 не подтвердил авторизацию на портале |
MISSING_TOKEN |
400 | POST /v1/oauth/revoke без заголовка Authorization: Bearer с токеном сессии |
Отказ на приёме возврата может прийти не кодом, а параметром ?error= в адресе redirect_uri — token_exchange_failed, invalid_domain или profile_fetch_failed.
Полное описание потока — Авторизация пользователей приложения.
Права и скоупы
| Код | HTTP | Когда возникает |
|---|---|---|
SCOPE_DENIED |
403 | У ключа нет нужного скоупа (например, crm для сделок, imbot для ботов) |
WRITE_BLOCKED_READONLY_KEY |
403 | У ключа задан режим «только чтение», а вызов выполняет запись |
INFRA_FORBIDDEN_FOR_COWORK_KEY |
403 | Ключ подписки Cowork (vibe:cowork) — только data-plane: запрещены provision / deploy / exec / upload / lifecycle сервера и публикация в каталог. Используйте проектный ключ с правами на деплой. В error.details.deployableKeys ответ перечисляет ваши другие активные ключи с правом деплоя (name / prefix / suffix, до 5) |
INFRA_SCOPE_REQUIRED |
403 | У ключа нет скоупа vibe:infra — управление инфраструктурой недоступно. Добавьте скоуп или используйте ключ с правами на инфраструктуру |
KEY_POLICY_READONLY_REQUIRED |
403 | Политика портала разрешает обычным пользователям создавать только ключи с режимом «только чтение» — выпуск ключа с записью отклонён |
MANAGEMENT_KEY_READ_ONLY |
403 | Management-ключ без прав на запись пытается выполнить POST/PATCH/DELETE |
MANAGEMENT_KEY_NO_ENTITY_ACCESS |
403 | Management-ключ обращается к entity-эндпоинту — нужен APP-ключ с нужным скоупом |
BITRIX_ACCESS_DENIED |
403 | Битрикс24 ответил ACCESS_DENIED: у пользователя нет прав на операцию или сущность |
OAUTH_REQUIRED |
403 | Эндпоинт требует пользовательский контекст — нужен ключ типа vibe_app_* + Bearer-токен |
WAITLIST_PENDING |
403 | Аккаунт ожидает активации в waitlist |
OAUTH_SCOPE_CHANGE_REQUIRES_REISSUE |
403 | Попытка добавить право Битрикс24 к OAuth-app-ключу (vibe_app_*) через PATCH /v1/keys/:id или к приложению через PATCH /v1/apps/:id. Права OAuth-приложения фиксируются при выпуске — снятие прав работает, а для нового права создайте приложение заново с нужным набором и пройдите авторизацию заново: перевыпуск ключа права не выдаёт |
OAUTH_APP_REQUIRED |
400 | Операция с местами встраивания выполнена личным ключом vibe_api_*. Привязка, отвязка и список привязанных мест доступны только ключу авторизации приложения vibe_app_* |
PLACEMENT_SCOPE_MISSING |
403 | У ключа нет скоупа placement — привязка и отвязка мест встраивания недоступны |
SESSION_REQUIRES_ADMIN |
403 | Привязка места встраивания на коробочном аккаунте выполняется под учётной записью без прав администратора аккаунта |
B24_EMBEDDING_APP_NOT_FOUND |
404 | Битрикс24 не знает идентификатор приложения: локальное приложение на аккаунте удалили или переустановили. Создайте локальное приложение заново и вызовите POST /v1/apps/:id/relink-oauth с новыми bitrixClientId и bitrixClientSecret. Не путать с APP_NOT_FOUND — тот про связку ключа и приложения на стороне платформы Вайбкод |
B24_EMBEDDING_INSTALL_DENIED |
403 | Битрикс24 отказал в установке встройки при действующей подписке: у пользователя, чьим ключом разработчика идёт вызов, нет права ставить локальные приложения и/или нет доступа к самому приложению. Подписка считается действующей в двух случаях — её подтвердил Битрикс24 либо проверку выполнить не удалось, а аккаунт уже числится подписанным в Вайбкод. Если действующей подписки нет ни по одному из источников, тот же отказ приходит как 502 |
APP_NOT_REGISTERED |
400 | У приложения нет идентификатора приложения Битрикс24 — привязать или отвязать место встраивания нельзя |
BOX_NO_DEVELOPER_KEY |
400 | У автора приложения не настроен ключ разработчика — операция с местами встраивания на коробочном аккаунте недоступна |
OAUTH_APP_KEY_CANNOT_RELINK |
403 | POST /v1/apps/:id/relink-oauth вызван ключом самого OAuth-приложения (vibe_app_*). Перепривязывать учётные данные приложения таким ключом нельзя — используйте личный ключ (vibe_api_*) или кабинет |
Валидация запроса
| Код | HTTP | Когда возникает |
|---|---|---|
VALIDATION_ERROR |
400 | Тело или query не прошли проверку схемы. message содержит подробности по полям |
INVALID_JSON_BODY |
400 | Тело запроса не разбирается как JSON. Приходит до проверки схемы, поэтому полей в message нет. Этот код возвращают маршруты сущностей /v1/<сущность>, а также /v1/apps, /v1/bots, /v1/keys, /v1/note, все операции сервера /v1/infra/servers/:id, /v1/infra/runtimes, маршруты пользовательских полей, чатов /v1/chats/* и открытых линий /v1/openlines/* |
FST_ERR_CTP_INVALID_JSON_BODY |
400 | Тот же случай — тело не разбирается как JSON — на остальных маршрутах: POST /v1/search, POST /v1/research, POST /v1/batch и прочих |
fst_err_ctp_invalid_json_body |
400 | Тот же случай на OpenAI-совместимых маршрутах AI Router — /v1/ai/, /v1/chat/, /v1/models, /v1/audio/. На них коды приводятся к нижнему регистру, а ответ идёт в OpenAI-конверте: error.type, error.code, без поля success |
INVALID_PARAMS |
400 | Битрикс24 вернул INVALID_PARAMS или route-handler нашёл некорректное значение параметра |
INVALID_REQUEST |
400 | Структура запроса не соответствует требуемой — например, calls в /v1/batch пустой массив или содержит больше 50 элементов, создание сервера без обязательных полей, не-объект вместо тела на маршрутах пользовательских полей |
MISSING_PARAMS |
400 | Не передан обязательный параметр, явно перечисленный в схеме эндпоинта |
MISSING_REQUIRED_FILTER |
400 | Не передан обязательный фильтр для list-эндпоинтов, требующих контекста: timelines (entityType + entityId), catalog-products и catalog-sections (iblockId), catalog-product-property-enums (propertyId). Он же приходит на агрегацию дел без сужающего фильтра — там достаточно одного сужения из нескольких, и message их перечисляет |
MISSING_REQUIRED_PARAMS |
400 | Не переданы обязательные параметры контекста для поиска или списка вложенных данных: files требует folderId, folders — parentId, calendar-events — type и ownerId. message перечисляет недостающие поля |
MISSING_REQUIRED_FIELDS |
400 | Не передано поле тела, объявленное обязательным при создании сущности. message называет недостающее поле |
MISSING_FIELD |
400 | Создание пользовательского поля без userTypeId. message приводит примеры допустимых типов |
EMPTY_CREATE_BODY |
400 | Тело запроса на создание пустое — не передано ни одного поля |
EMPTY_UPDATE_BODY |
400 | Тело запроса на обновление пустое — не передано ни одного поля |
INVALID_FILTER_FIELD |
400 | Имя поля фильтра начинается с родного префикса Битрикс24 @ (IN) или !@ (NOT IN) — используйте операторы $in / $nin |
UNKNOWN_FILTER_FIELD |
400 | Фильтрация по полю, которого нет в схеме сущности (для сущностей с полной схемой полей). Когда поле отклонил валидатор Вайбкод, message перечисляет допустимые имена после слова Available. Когда поле отклонил Битрикс24, список полей приходит в error.hint |
UNKNOWN_SELECT_FIELD |
400 | Отбор полей select по имени, которого нет в схеме событий календаря — единственной сущности, где незнакомое имя отклоняется. message перечисляет допустимые имена после слова Available. На остальных сущностях запрос выполняется, а имя перечисляется предупреждением в meta.warnings. Рядом со значением * незнакомое имя тоже не отклоняется — приходит предупреждение |
UNKNOWN_SORT_FIELD |
400 | Сортировка по несуществующему полю (для сущностей, у которых валидатор сортировки активен) |
BATCH_LIMIT_EXCEEDED |
400 | Запрос содержит больше 50 элементов в массивной операции (vipchats, task-comments и подобные) |
MESSAGE_REQUIRED |
400 | POST /v1/chats/{dialogId}/messages без текста: поле message пустое и нет блока attach. Частая причина — текст передан под неизвестным именем поля, например text. Ответ перечисляет нераспознанные поля |
INVALID_EVENT |
400 | Код события подписки портала не соответствует формату ^[A-Z][A-Z0-9_]+$. См. Подписки на события портала |
INVALID_APP_PATH |
400 | Путь доставки appPath не начинается с / либо содержит управляющие символы. См. Подписки на события портала |
PLATFORM_HANDLER_UNRESOLVABLE |
400 | Адрес обработчика указывает на технический адрес сервера приложения, а платформенный обработчик определить не удалось. Место встраивания не зарегистрировано. См. Привязать место |
Пустое тело с заголовком Content-Type: application/json принимается как {} на маршрутах /v1/infra/*, а также на всех маршрутах пользовательских полей: /v1/userfields/:entity, /v1/userfields/:entity/types и /v1/userfields/:entity/:id, те же три пути под /v1/items/:entityTypeId/userfields, а также короткие адреса счетов /v1/userfields/invoices, /v1/userfields/invoices/types и /v1/userfields/invoices/:id. Операции, которым тело не нужно — POST /v1/infra/servers/:id/wake, DELETE /v1/infra/servers/:id/access-tokens/:tokenId и подобные, — отвечают по существу, а не отклоняют запрос на разборе тела. Так ведут себя клиенты, которые ставят этот заголовок на любой запрос (например, axios и PowerShell Invoke-RestMethod).
Дальше запрос проверяет сама операция, и код отказа зависит от маршрута — берите его из таблицы выше или со страницы нужной операции. Тело, которое не разбирается как JSON, на этих маршрутах отклоняется кодом INVALID_JSON_BODY, то есть пустое и битое тело различаются.
Размер тела запроса
| Код | HTTP | Когда возникает |
|---|---|---|
PAYLOAD_TOO_LARGE |
413 | Тело запроса больше потолка этого маршрута |
LARGE_BODY_BACKEND_BUSY |
429 | Платформа уже обрабатывает предельное число крупных тел. Запрос не выполнялся, повторите его через Retry-After секунд |
Потолок зависит от маршрута. По умолчанию — 1 МБ. Создание и обновление записей, файлы ботов и чатов, note.file.add — 40 МиБ. Загрузка на Диск — 70 МБ. Файл внутри тела едет в base64 и растёт примерно на треть, поэтому исходный файл при потолке 40 МиБ — чуть меньше 30 МиБ. Тот же код приходит от пограничного слоя на его собственном пороге. Тело под необъявленным типом содержимого — например, text/plain — на маршрутах сущностей, пользовательских полей, чатов, заметок и ключей отклоняется кодом 415 FST_ERR_CTP_INVALID_MEDIA_TYPE, а пустое тело под тем же типом принимается там как {}. На /v1/infra/* и /v1/apps, включая публикацию исходников и места встраивания, потолок тела для непонятого типа равен одному байту, поэтому тот же запрос отвечает 413.
Крупным считается тело больше 1 МиБ — это тот же порог, что и потолок по умолчанию, — и число одновременно обрабатываемых крупных тел ограничено. Отказ приходит только там, где потолок тела поднят: записи сущностей, файлы ботов и файлы чатов. На загрузке на Диск и на note.file.add его не бывает. Когда свободного места нет, приходит 429 LARGE_BODY_BACKEND_BUSY с заголовком Retry-After: 5. Так же отвечает запрос без заголовка Content-Length, если объём переваливает тот же порог уже по ходу передачи. Срок повтора берите из заголовка: поле error.retryAfter в теле этого отказа приходит не на всех путях.
Исключение — маршруты AI (/v1/ai/*, /v1/chat/*, /v1/audio/*, /v1/models): у них конверт ошибки, совместимый с OpenAI, и на превышении тела в error.code приходит служебный код фреймворка в нижнем регистре, а не PAYLOAD_TOO_LARGE.
Загрузка файлов
| Код | HTTP | Когда возникает |
|---|---|---|
STORAGE_FORBIDDEN_CONTENT_TYPE |
415 | Для PUBLIC-объектов запрещены типы text/html, application/javascript, application/x-javascript, image/svg+xml — они опасны межсайтовым выполнением скриптов. Загружайте такой файл как PRIVATE |
Предусловия подписок на события портала
| Код | HTTP | Когда возникает |
|---|---|---|
NOT_OAUTH_APP |
400 | Сервер не привязан к OAuth-приложению с application_token — подписку на событие зарегистрировать нельзя |
NO_USER_TOKEN |
400 | У приложения нет OAuth-токена — сначала авторизуйте приложение на портале |
Полное описание операций — Подписки на события портала.
Установка приложения через модуль-коннектор
| Код | HTTP | Когда возникает |
|---|---|---|
CONNECTOR_APP_INSTALL_FORBIDDEN |
403 | Администратор аккаунта Битрикс24 запретил этому сотруднику устанавливать приложения. Право выдаёт администратор аккаунта, повтор запроса состояние не меняет |
CONNECTOR_MODULE_NOT_INSTALLED |
409 | Модуль-коннектор на аккаунте не установлен. Состояние постоянное — пока модуль не установят, повтор бессмыслен |
CONNECTOR_APP_INSTALL_FAILED |
502 | Другой сбой установки на стороне модуля-коннектора. Запрос можно повторить |
CONNECTOR_REST_UNAVAILABLE |
502 | Подписка или пробный период действуют, но Битрикс24 отказал в выписке парного ключа. Исходная причина — в error.details.reason, error.details.retryable: true говорит, что состояние временное |
Коды приходят на создании приложения там, где приложение устанавливает модуль-коннектор: на коробочном аккаунте, а на облачном — когда такой выпуск для аккаунта включён. При любом из этих отказов ни приложение, ни парный ключ не создаются.
Ресурс не найден
| Код | HTTP | Когда возникает |
|---|---|---|
ROUTE_NOT_FOUND |
404 | Маршрута или HTTP-глагола не существует: опечатка в пути, несуществующая сущность, неподдерживаемый метод, а также операция, которой у этой сущности нет. Сверьте путь со списком в GET /v1/guide |
ENTITY_NOT_FOUND |
404 | Запись CRM-сущности с указанным id не существует. Канонический код для /v1/deals/:id, /v1/contacts/:id и подобных |
NOT_FOUND |
404 | Только GET /:id: Битрикс24 вернул success, но result пустой (применимо к нескольким смарт-методам) |
OPERATION_NOT_FOUND |
404 | Операции выкладки с таким идентификатором нет, она принадлежит другому ключу либо запись уже удалена. Три случая отвечают одинаково намеренно — см. Исход выкладки |
Доменные *_NOT_FOUND (BOT_NOT_FOUND, SERVER_NOT_FOUND, AGENT_NOT_FOUND, APP_NOT_FOUND, PORTAL_NOT_FOUND, USER_NOT_FOUND, FILE_NOT_FOUND, SUBSCRIPTION_NOT_FOUND) описаны на страницах соответствующих разделов.
B24_EMBEDDING_APP_NOT_FOUND (404) — отдельный случай: приложение есть на платформе Вайбкод, но Битрикс24 не знает его идентификатор, потому что локальное приложение на аккаунте удалили или переустановили. Лечится пересозданием локального приложения и вызовом POST /v1/apps/:id/relink-oauth с новыми bitrixClientId и bitrixClientSecret. Не путать с APP_NOT_FOUND — тот про связку ключа и приложения на стороне платформы Вайбкод.
Два вида 404. Один и тот же HTTP-статус 404 означает два разных состояния — различайте их по error.code. ROUTE_NOT_FOUND — маршрута или глагола не существует, повторять запрос бессмысленно: проверьте путь по GET /v1/guide. ENTITY_NOT_FOUND и доменные коды вида *_NOT_FOUND — маршрут существует, не найден запрошенный объект. Оба состояния отвечают в едином конверте V1.
Маршрута не существует:
{
"success": false,
"error": {
"code": "ROUTE_NOT_FOUND",
"message": "Route GET:/v1/dealz not found. Check GET /v1/guide for available endpoints and verbs."
}
}
Маршрут существует, объекта нет:
{
"success": false,
"error": {
"code": "ENTITY_NOT_FOUND",
"message": "Элемент не найден"
}
}
Конфликты состояния
| Код | HTTP | Когда возникает |
|---|---|---|
CONFLICT |
409 | Текущее состояние ресурса несовместимо с запросом |
ALREADY_EXISTS |
409 | Запись с такими ключевыми полями уже существует |
EVENT_BOUND_ELSEWHERE |
409 | Событие портала уже привязано к другому серверу того же OAuth-приложения. См. Подписки на события портала |
OAUTH_CLIENT_ID_IN_USE |
409 | POST /v1/apps/:id/relink-oauth: указанный bitrixClientId уже привязан к другому приложению. Один client_id — одно приложение |
OPERATION_OUTCOME_EXPIRED |
410 | Операция выкладки ваша и она точно была, но её исход больше не хранится (срок — 7 суток). См. Исход выкладки |
Биллинг и тариф
Возникают на эндпоинтах создания и пробуждения инфраструктуры (серверы, агенты, управляемые боты). Ответ содержит userMessage на русском языке для показа в интерфейсе клиента.
| Код | HTTP | Когда возникает |
|---|---|---|
BILLING_EXHAUSTED |
402 | Баланс ушёл в красную зону, аккаунт заморожен. Нужен top-up |
ACCOUNT_FROZEN |
402 | Платёжный аккаунт заморожен по другим причинам |
COMMERCIAL_PLAN_REQUIRED |
402 | Бесплатный тариф Битрикс24, пробный период недоступен или уже использован |
MARKETPLACE_REQUIRED |
402 | На портале нет активной подписки BitrixGPT + Маркетплейс — оформите её, чтобы открыть создание серверов, деплой и пробуждение |
INT_VIBE_PLUS_REQUIRED |
402 | На портале не подключён тариф Vibe+. Подключите тариф Vibe+ и повторите запрос |
TRIAL_EXPIRED |
402 | 14-дневный пробный период завершён |
TRIAL_PORTAL_LIMIT |
402 | На пробном периоде превышен общий лимит серверов на портал |
TRIAL_USER_LIMIT |
402 | На пробном периоде превышен лимит серверов на пользователя |
PLAN_NOT_ALLOWED_ON_TRIAL |
402 | Запрошенный план сервера/агента недоступен на пробном периоде |
SERVER_WAKE_BLOCKED |
403 | Пробуждение сервера заблокировано по небиллинговой причине |
B24_MARKET_SUBSCRIPTION_REQUIRED |
403 | На аккаунте нет активной подписки BitrixGPT + Маркетплейс. Приходит на привязке места встраивания и на установке приложения — в том числе на коробочном портале, где ключ выдаёт модуль-коннектор |
B24_MARKET_TRIAL_USED |
403 | Пробный период подписки BitrixGPT + Маркетплейс уже использован — привязка места встраивания и установка приложения требуют платной подписки |
INT_TARIFF_REQUIRED |
403 | Аккаунт работает по тарифной модели доступа, при этом как привязка места встраивания, так и установка приложения требуют коммерческого тарифа Битрикс24 |
Ограничение частоты
| Код | HTTP | Когда возникает |
|---|---|---|
RATE_LIMITED |
429 | Битрикс24 ограничил частоту запросов или превышен внутренний лимит. В ответе — retryAfter (секунды) и заголовок Retry-After |
ERROR_LOOP_DETECTED |
429 | Блокировка на стороне Вайбкод: один и тот же запрос повторяется с одинаковой ошибкой. Сигнал о баге в коде клиента. Каждый N-й запрос пробрасывается дальше для проверки восстановления |
OPERATION_TIME_LIMIT |
429 | Битрикс24 приостановил ЭТОТ метод для ВАШЕГО ключа примерно на 5 минут: метод исчерпал бюджет рабочего времени. В ответе scope: "apiKey", retryAfter и заголовок Retry-After. Остальные методы и другие ключи портала работают |
TIMEOUT_QUARANTINE |
429 | Блокировка на стороне Вайбкод: метод несколько раз подряд не ответил порталу за отведённое вызову время, и пара «портал + метод» поставлена на паузу. В ответе scope: "portal", retryAfter и заголовок Retry-After. Пауза общая для ВСЕХ ключей портала и снимается автоматически |
Backend и сторонние сервисы
| Код | HTTP | Когда возникает |
|---|---|---|
BITRIX_ERROR |
422 | Битрикс24 вернул бизнес-ошибку, не подпадающую под более узкие категории (ACCESS_DENIED, NOT_FOUND, INVALID_PARAMS) |
AGGREGATION_LIMIT_EXCEEDED |
422 | Агрегация отказалась отвечать: выборка шире 5000 записей, оценённая стоимость вызова превысила безопасный бюджет, страница записей не догрузилась — либо (для дел без сужающего фильтра) Битрикс24 не ответил за отведённое на вызов время. message говорит, какой именно случай. Заголовка Retry-After нет: отказ не временный |
METHOD_NOT_YET_AVAILABLE |
422 | Метод выходит в обновлении Битрикс24 и на этот портал ещё не приехал. Ответ содержит поле error.release с идентификатором обновления, например imopenlines 26.700.0. Это признак раскатки, а не ошибка вызова — подробнее |
BITRIX_UNAVAILABLE |
502 | Битрикс24 вернул 5xx или не ответил вовремя |
BIND_FAILED |
502 | Битрикс24 отклонил регистрацию события (event.bind) — например, портал не на коммерческом тарифе. См. Подписки на события портала |
WINDOWED_SEARCH_FAILED |
— | Больше не возвращается: при полном отказе авто-окон /search возвращается реальный код Битрикс24 — UNKNOWN_FILTER_FIELD / INVALID_PARAMS / BITRIX_ACCESS_DENIED / RATE_LIMITED / BITRIX_UNAVAILABLE / BITRIX_TIMEOUT (503), как для узкого диапазона |
QUEUE_OVERFLOW |
429 | Очередь портала переполнена: слишком много одновременных вызовов Битрикс24. Отклоняется мгновенно, Retry-After в заголовке |
QUEUE_TIMEOUT |
429 | Очередь портала перегружена: больше 30 секунд ожидания на стороне Вайбкод. Запрос не был отправлен в Битрикс24 — безопасно повторить |
BITRIX_TIMEOUT |
503 | Битрикс24 принял запрос, но не ответил за 15 секунд — исход неизвестен. Для write: сначала перечитайте сущность, изменение могло примениться |
POOL_EXHAUSTED |
503 | Сервис временно перегружен — исчерпан пул соединений с базой данных. В ответе retryAfter и заголовок Retry-After, повторите через несколько секунд |
DB_TRANSIENT |
503 | Транзакция в базе данных закрылась или истекла до того, как операция завершилась, — платформа откатила её целиком. Отказ временный: в ответе retryAfter и заголовок Retry-After, повторите через несколько секунд. Изменение не применилось ни частично, ни полностью |
SERVICE_UNAVAILABLE |
503 | Граница платформы не смогла передать запрос бэкенду (например, в момент редеплоя) — либо не дождалась ответа. В ответе retryAfter и заголовок Retry-After. Если запрос мог быть выполнен (истёк таймаут ожидания ответа), для не-идемпотентных операций перед повтором сверьте состояние сущности |
INTERNAL_ERROR |
500 | Непредвиденная ошибка backend Вайбкод |
NETWORK_DEVKEY_REQUIRED |
503 | Ключ разработчика для автора приложения ещё не выдан — привязка места встраивания временно недоступна |
Подробное описание
`MISSING_API_KEY` (401)
Запрос не содержит заголовка X-Api-Key.
{
"success": false,
"error": {
"code": "MISSING_API_KEY",
"message": "API key required. Pass via X-Api-Key header."
}
}
Причины:
- Не передан заголовок
X-Api-KeyилиAuthorization. - Заголовок передан с пустым значением.
Решение:
- Добавить заголовок
X-Api-Key: vibe_api_...илиX-Api-Key: vibe_app_.... - Проверить, что переменная окружения с ключом установлена корректно (для CLI-утилит и SDK).
`INVALID_API_KEY` (401)
Переданный ключ не существует или его формат не распознан.
{
"success": false,
"error": {
"code": "INVALID_API_KEY",
"message": "Invalid API key"
}
}
Причины:
- Опечатка или лишние пробелы в ключе.
- Ключ удалён владельцем или администратором.
- Ключ от другого окружения (staging/production).
- Префикс не из числа поддерживаемых:
vibe_api_,vibe_app_,vibe_live_,vibe_mgmt_.
Решение:
- Сверить ключ в личном кабинете на странице
/keys. - Создать новый ключ, если старый удалён.
`TOKEN_MISSING` (401)
У ключа нет кредов Битрикс24, поэтому вызов к порталу выполнить нечем. Причина зависит от типа ключа, и это два разных сценария.
Личный ключ (vibe_api_*) ходит в портал по вебхуку. Если вебхука на ключе нет,
ответ на вызовах сущностей (/v1/{сущность} и POST /v1/batch) несёт машиночитаемую
причину в error.details. На остальных маршрутах приходит тот же код без details:
{
"success": false,
"error": {
"code": "TOKEN_MISSING",
"message": "This personal API key (vibe_api_*) has no Bitrix24 webhook credentials, ...",
"details": {
"reason": "B24_MARKET_SUBSCRIPTION_REQUIRED",
"paywallCode": "B24_MARKET_SUBSCRIPTION_REQUIRED"
}
}
}
Значения details.reason:
| Причина | Что означает | Что делать |
|---|---|---|
B24_MARKET_SUBSCRIPTION_REQUIRED |
На портале нет активной подписки на Битрикс24 Маркет | Активировать демо Маркета или оформить подписку, затем переподключить ключ |
B24_MARKET_TRIAL_USED |
Демо Маркета уже использовано, платной подписки нет | Оформить подписку на Маркет, затем переподключить ключ |
INT_TARIFF_REQUIRED |
У портала нет платного тарифа Битрикс24 (регионы с тарифной моделью доступа) | Подключить платный тариф, затем переподключить ключ |
VIBE_SCOPES_ONLY |
Ключ не запрашивал ни одного скоупа Битрикс24 — вебхук ему не выдаётся by design | Создать ключ с нужными скоупами Битрикс24 |
WEBHOOK_NOT_CONFIGURED |
Доступ Битрикс24 в порядке либо неизвестен, а вебхука на ключе нет | Переподключить ключ. При details.hint — повторить проверку через GET /v1/me?refresh=tariff |
Переподключение — POST /api/keys/:id/reconnect: выдаёт ключу вебхук, не меняя саму
строку ключа (интеграции перенастраивать не нужно), и снимает авто-блокировку со связанных
ботов. Не применимо к ключам приложения, системным ключам и ключам без скоупов Битрикс24 —
для них остаётся создание нового ключа.
paywallCode приходит только для тарифных причин. Вместе с ним может прийти
upgradeUrl — ссылка на страницу подключения на портале. У INT_TARIFF_REQUIRED
её нет.
Ключ приложения (vibe_app_*) держит токены портала в пользовательской сессии, а не
на ключе. Вызов только с X-Api-Key, без Authorization: Bearer <токен сессии>, законно
отвечает TOKEN_MISSING — details в этой ветке не приходит, а message описывает
пропущенный шаг OAuth. Полный поток — Ключи и авторизация.
Как посмотреть состояние ключа заранее: GET /v1/me для личного ключа отдаёт блок
b24Credentials (ready, а при ready: false — та же reason и действия), а
GET /v1/keys — признак b24Ready на каждом ключе. Ответ /v1/me кэшируется на 30 секунд,
поэтому сразу после починки на портале читайте его как GET /v1/me?refresh=tariff — иначе
до полуминуты будет отдаваться прежнее состояние. У GET /v1/keys кэша нет.
`SCOPE_DENIED` (403)
У ключа нет нужного скоупа для запрошенной операции.
{
"success": false,
"error": {
"code": "SCOPE_DENIED",
"message": "This endpoint requires 'crm' scope"
}
}
Причины:
- Для CRM-сущностей нужен скоуп
crm, для задач —task, для бот-платформы —imbot, для AI Router —vibe:ai, для инфраструктуры —vibe:infra. - Скоуп ключа сужен на этапе создания.
Решение:
- Открыть страницу ключа в личном кабинете и выпустить новый ключ с расширенным набором скоупов.
- Полный список скоупов и их назначение — на странице Ключи и авторизация.
`BITRIX_ACCESS_DENIED` (403)
Битрикс24 ответил ACCESS_DENIED: у пользователя или приложения нет прав на сущность или операцию.
{
"success": false,
"error": {
"code": "BITRIX_ACCESS_DENIED",
"message": "ACCESS_DENIED"
}
}
Причины:
- У пользователя нет прав на сущность в CRM (например, чужая сделка с ограничением видимости).
- Набор скоупов на портале уже, чем набор скоупов ключа. Скоупы Битрикс24 закрепляются за ключом в момент выпуска, поэтому скоуп, добавленный к уже выпущенному ключу,
GET /v1/meпокажет, а к данным портала ключ обратится с прежним набором. - Запрашиваемый модуль выключен на портале (отсутствует CRM, бот-платформа и тому подобное).
Решение зависит от типа ключа. Когда отказ вызван набором скоупов, в error.hint приходит подсказка с конкретным случаем. Подсказка приходит не всегда: голому ACCESS_DENIED без пояснений от Битрикс24 её может не быть.
- API-ключ (
vibe_api_). Набор скоупов, с которым ключ обращается к порталу, хранится на портале отдельно от набора у самого ключа. Перевыпустить ключ, переподключить его или создать новый с отмеченным скоупом — правка разрешений приложения на портале в этом случае ничего не меняет. - Ключ авторизации (
vibe_app_). Создать приложение заново с нужным скоупом и пройти авторизацию заново. Перевыпуск ключа здесь скоуп не выдаёт. - Методы чатов и ботов. Для них того же отказа недостаточно объяснить скоупом: владелец ключа должен быть администратором портала. Выпустить ключ под учётной записью администратора — расширение скоупов тут не поможет.
- Если дело в правах сотрудника, а не в скоупах ключа — проверить права пользователя в карточке сущности Битрикс24.
Полное описание того, как скоупы закрепляются за ключом и что делать, если после перевыпуска отказ повторяется, — Ключи и авторизация.
`WRITE_BLOCKED_READONLY_KEY` (403)
У ключа задан режим «только чтение» (accessMode: "READONLY"), а запрос выполняет запись. Полное описание режима, переключения и политики портала — Режим доступа.
{
"success": false,
"error": {
"code": "WRITE_BLOCKED_READONLY_KEY",
"message": "Key is in read-only mode. Switch to read+write in /keys to enable writes.",
"details": {
"method": "crm.item.add",
"keyName": "MCP key",
"currentMode": "READONLY",
"switchUrl": "/keys"
}
}
}
Поля details:
| Поле | Когда возвращается | Описание |
|---|---|---|
method |
Только при проксировании в Битрикс24 | Имя метода Битрикс24, который был бы вызван при успешной записи (например, crm.item.add). Для менеджмент-ключей не возвращается — блокировка идёт по HTTP-методу запроса |
keyName |
Всегда | Название ключа из личного кабинета. Если у ключа нет названия — возвращается "unnamed" |
currentMode |
Всегда | Действующий режим ключа — всегда "READONLY" для этой ошибки |
switchUrl |
Всегда | Путь до страницы личного кабинета, где режим переключается, — "/keys" |
Причины:
- API-ключ или ключ авторизации (
vibe_api_,vibe_app_) в режимеREADONLYвыполнил вызов, который проксируется в Битрикс24 как операция записи: создание, обновление, удаление, действие над сущностью. - Менеджмент-ключ (
vibe_live_) в режимеREADONLYвыполнил запрос с HTTP-методомPOST,PATCH,PUTилиDELETE— например, попытка создать ключ черезPOST /v1/keysили удалить запись обратной связи.
Решение:
- Владельцу ключа — открыть Ключи API, в карточке нужного ключа в блоке Режим доступа выбрать «Чтение и запись» и сохранить. Режим применяется к следующему запросу, перевыпуск не нужен.
- Если в карточке выбор переключателя недоступен — администратор портала ограничил режим. Запросить у администратора снятие ограничения для этого ключа.
- При работе через AI-агента — действующий режим возвращает
GET /v1/meв полеdata.accessMode. Если запись нужна постоянно, выпустить отдельный ключ с режимом «чтение и запись».
`VALIDATION_ERROR` (400)
Тело или query-параметры не прошли проверку схемы. Для большинства V1-эндпоинтов обработка реализована через Zod, поэтому сообщение содержит конкретные поля с проблемами.
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "fields.title: Required; fields.stageId: Expected string, received number"
}
}
Причины:
- Отсутствуют обязательные поля.
- Тип значения не соответствует схеме (строка вместо числа, неверный формат даты).
- Отсутствует заголовок
Content-Type: application/json. Тело, которое не разбирается как JSON, отклоняется отдельными кодами —INVALID_JSON_BODY,FST_ERR_CTP_INVALID_JSON_BODYилиfst_err_ctp_invalid_json_bodyна маршрутах AI Router. Какой из них придёт, зависит от маршрута — см. таблицу выше.
Решение:
- Сверить body со схемой эндпоинта в справочнике сущностей или на странице конкретного эндпоинта.
- Числа передавать без кавычек, даты — в формате ISO 8601 (
2026-04-29T10:00:00). - Добавить заголовок
Content-Type: application/json.
`INVALID_PARAMS` (400)
Битрикс24 или route-handler нашёл некорректное значение параметра. Ошибки Битрикс24 формата INVALID_PARAMS: ... приходят под этим же кодом.
{
"success": false,
"error": {
"code": "INVALID_PARAMS",
"message": "Path parameter :id must be a positive integer"
}
}
Причины:
- Некорректное значение path-параметра (например, не число там, где ожидается число).
- Битрикс24 отверг параметр запроса (например, неподходящее значение enum-поля).
Решение:
- Проверить страницу эндпоинта: какие значения допустимы для каждого параметра.
- Для
filterиспользовать список полей изGET /v1/<entity>/fields.
`MISSING_REQUIRED_FILTER` (400)
Не передан обязательный фильтр на list-эндпоинте, который требует контекста.
{
"success": false,
"error": {
"code": "MISSING_REQUIRED_FILTER",
"message": "filter[entityType] and filter[entityId] are required for /v1/timelines"
}
}
Причины:
- Список тайм-лайн-записей требует пары родительских идентификаторов
entityType+entityId. - Список товаров и разделов каталога требует
iblockId, а список значений списочного свойства —propertyId. - Агрегация дел требует сужающего фильтра: пара
ownerTypeId+ownerId, либоresponsibleId, либо граница по дате наcreatedAt/updatedAt/deadline. Здесь требование не «все перечисленные», а «любое одно» — Битрикс24 не успевает посчитать все дела аккаунта за отведённое на вызов время. Требование включается платформой отдельно на каждый аккаунт. Проверить состояние —data.aggregateFilterRequirement.enforcementв ответеGET /v1/activities/fields.
Проверка выполняется до обращения к Битрикс24 и действует на GET /v1/{entity}, POST /v1/{entity}/search и POST /v1/{entity}/aggregate.
Решение:
- Добавить обязательные параметры фильтра, перечисленные в
messageили на странице эндпоинта.
`BATCH_LIMIT_EXCEEDED` (400)
Запрос превышает лимит элементов в массивной операции. На уровне /v1/batch лимит проверяется через INVALID_REQUEST со ссылкой на Array must contain at most 50 element(s). На доменных bulk-эндпоинтах (например, chats, task-comments) — отдельный код BATCH_LIMIT_EXCEEDED.
{
"success": false,
"error": {
"code": "BATCH_LIMIT_EXCEEDED",
"message": "Maximum 50 dialogs per bulk request (Bitrix24 batch limit)."
}
}
Причины:
- В массиве больше 50 элементов.
Решение:
- Разделить операцию на несколько запросов по 50 элементов.
- Использовать batch-запросы для последовательных вызовов с одного ключа.
`ENTITY_NOT_FOUND` (404)
Запись CRM-сущности с указанным id не существует или была удалена.
{
"success": false,
"error": {
"code": "ENTITY_NOT_FOUND",
"message": "Элемент не найден"
}
}
Причины:
- Запись с таким
idдействительно не существует. - Запись была удалена параллельным процессом.
- Перепутана сущность: запрос идёт на
/v1/deals/:id, а ID — от лида.
Решение:
- Проверить наличие записи через list-эндпоинт сущности.
- Восстановить из корзины Битрикс24, если запись была удалена недавно (через интерфейс портала).
`RATE_LIMITED` (429)
Битрикс24 ограничил частоту запросов либо сработал внутренний лимит Вайбкод.
{
"success": false,
"error": {
"code": "RATE_LIMITED",
"message": "QUERY_LIMIT_EXCEEDED",
"hint": "Wait 1-2 seconds and retry. Use POST /v1/batch to combine up to 50 calls in 1 request.",
"retryAfter": 2
}
}
Заголовки ответа:
Retry-After: 2
Причины:
- Сложилось слишком много одновременных запросов от одного ключа: общий лимит платформы считается по API-ключу. Исключение —
POST /v1/search,POST /v1/researchиPOST /v1/batch: там лимит считается на портал, и все его ключи делят один счётчик. - Превышен лимит запросов в секунду на стороне Битрикс24. Он считается на портал.
Решение:
- Дождаться времени из
error.retryAfterили заголовкаRetry-After. - Реализовать повторные попытки с экспоненциальной задержкой.
- Объединять до 50 вызовов через
POST /v1/batch. - Кэшировать редко изменяемые справочные данные — поля, статусы, валюты.
`ERROR_LOOP_DETECTED` (429)
Вайбкод фиксирует серию одинаковых ошибок на одном ключе для одного метода Битрикс24 — и временно блокирует запрос на стороне Вайбкод, чтобы не накручивать счётчики Битрикс24. Каждый N-й запрос пробрасывается дальше: если backend восстановился, блокировка снимается автоматически.
{
"success": false,
"error": {
"code": "ERROR_LOOP_DETECTED",
"message": "Vibe-side block (not a Bitrix24 limit). 12 failures on crm.deal.list in the last hour.",
"hint": "Every 50th request will probe for recovery — keep retrying with backoff. If you suspect a platform-side issue (e.g. 5xx during an outage), platform admin can clear the block via POST /api/platform/analytics/circuit-breaker/<apiKeyId>/clear.",
"retryAfter": 60
}
}
Причины:
- В коде клиента баг: запрос с одинаковыми параметрами повторяется и стабильно даёт ошибку.
- Платформенная авария на стороне Битрикс24 в момент серии запросов.
Решение:
- Прочитать
message— там указан конкретный метод с серией ошибок. - Найти источник запроса в коде, исправить параметры или логику.
- При платформенной аварии — повторять с задержкой: каждый N-й запрос платформа пропускает для проверки восстановления, и блокировка снимается сама. Если она держится дольше самой аварии, обратитесь в поддержку.
- Маршрут, названный в поле
hintответа, — служебный эндпоинт платформы. Своим ключом его не вызвать, и вмешательство не требуется: он адресован поддержке.
`BILLING_EXHAUSTED` (402)
Платёжный аккаунт ушёл в красную зону: баланс отрицательный, грейс-период исчерпан. Запросы на создание и пробуждение инфраструктуры блокируются до пополнения.
{
"success": false,
"error": {
"code": "BILLING_EXHAUSTED",
"message": "Account is frozen due to negative balance.",
"userMessage": "Платёжный аккаунт заморожен из-за отрицательного баланса. Пополните счёт, чтобы продолжить работу с серверами и агентами.",
"hint": "Top up the account at /billing/topup, then call POST /v1/portals/:id/refresh-tariff."
}
}
Причины:
- На балансе нет средств для оплаты часовой стоимости серверов и агентов.
Решение:
- Пополнить баланс на странице
/billing/topup. - После пополнения вызвать
POST /v1/portals/:id/refresh-tariffдля обновления статуса.
`COMMERCIAL_PLAN_REQUIRED` (402)
Создание серверов и агентов недоступно на бесплатном тарифе Битрикс24 после окончания пробного периода.
{
"success": false,
"error": {
"code": "COMMERCIAL_PLAN_REQUIRED",
"message": "Commercial Bitrix24 plan required for infrastructure operations.",
"userMessage": "Создание инфраструктуры доступно на коммерческих тарифах Битрикс24. Пробный период уже использован.",
"hint": "Upgrade plan at https://www.bitrix24.ru/prices/, then call POST /v1/portals/:id/refresh-tariff."
}
}
Решение:
- Обновить тариф Битрикс24 до коммерческого.
- После обновления вызвать
POST /v1/portals/:id/refresh-tariffлибоGET /v1/me?refresh=tariff.
`TRIAL_EXPIRED` (402)
14-дневный пробный период завершился, тариф остался бесплатным.
{
"success": false,
"error": {
"code": "TRIAL_EXPIRED",
"message": "Trial period has ended.",
"userMessage": "Пробный период (14 дней) завершён. Перейдите на коммерческий тариф Битрикс24, чтобы продолжить пользоваться серверами и агентами."
}
}
Решение:
- Перейти на коммерческий тариф Битрикс24.
- Обновить статус через
POST /v1/portals/:id/refresh-tariff.
Отказы по подписке и тарифу (403)
Три кода одного класса: доступ к операции закрыт условиями подписки или тарифа аккаунта, а не правами ключа. Приходят на установке приложения и на привязке места встраивания — в том числе на коробочном аккаунте, где ключ выдаёт модуль-коннектор.
| Код | Когда приходит | error.details.upgradeUrl |
|---|---|---|
B24_MARKET_SUBSCRIPTION_REQUIRED |
На аккаунте нет активной подписки BitrixGPT + Маркетплейс | передаётся |
B24_MARKET_TRIAL_USED |
Пробный период подписки уже использован — нужна платная | передаётся |
INT_TARIFF_REQUIRED |
Аккаунт получает доступ по тарифу Битрикс24, а не по подписке: нужен коммерческий тариф. Приходит вместо двух кодов выше, а также когда модель доступа аккаунта определить не удалось | не передаётся |
{
"success": false,
"error": {
"code": "INT_TARIFF_REQUIRED",
"message": "Paid Bitrix24 plan required (international region)",
"userMessage": "Для доступа нужен платный тариф Битрикс24."
}
}
Решение:
- Отказ окончательный — повторять запрос бессмысленно. Пока условие доступа не изменилось на аккаунте, тот же вызов будет отклоняться.
- Если пришёл
error.details.upgradeUrl— это готовый адрес страницы оформления на самом аккаунте. Ведите пользователя по нему, а не собирайте адрес сами. - Если
upgradeUrlне пришёл, на установке приложения и привязке места встраивания оформлять нечего: у аккаунта тарифная модель доступа, и нужен коммерческий тариф Битрикс24. - Различайте эти коды в клиенте по
error.code, а не по тексту: у трёх отказов разные действия пользователя.
`BITRIX_ERROR` (422)
Битрикс24 вернул бизнес-ошибку, которая не подпадает под более узкие категории (ACCESS_DENIED, NOT_FOUND, INVALID_PARAMS, RATE_LIMITED).
{
"success": false,
"error": {
"code": "BITRIX_ERROR",
"message": "The requested period exceeds the maximum of 1 year",
"b24Code": "PERIOD_TOO_LARGE"
}
}
Причины:
- Битрикс24 отверг операцию по бизнес-причине: несовместимое состояние, неподдерживаемое значение, бизнес-правило.
- Запрос работает на портале, где соответствующий модуль отключён.
Решение:
- Прочитать
message— там оригинальный текст ошибки от Битрикс24. - При наличии
hint— использовать его как первый шаг диагностики. - Для программной обработки читать поле
error.b24Code— машиночитаемый код причины от Битрикс24, напримерBOT_TYPE_NOT_ALLOWEDилиPERIOD_TOO_LARGE. Ветвиться в коде по нему, а не по текстуmessage. - Поле
error.b24Codeприходит не всегда: когда Битрикс24 не прислал отдельный код, его в ответе нет.
`METHOD_NOT_YET_AVAILABLE` (422)
Метод выходит в обновлении Битрикс24, которое на этот портал ещё не приехало. Это признак раскатки, а не ошибка вызова: тот же запрос начнёт работать сам, как только обновление дойдёт до портала. На отдельных методах после этого добавляется своя проверка прав — она описана на странице метода.
{
"success": false,
"error": {
"code": "METHOD_NOT_YET_AVAILABLE",
"message": "Method \"imopenlines.v2.Stat.get\" is rolling out in update imopenlines 26.700.0 and is not yet available on this portal — this is not a call error.",
"release": "imopenlines 26.700.0"
}
}
Решение:
- Ветвиться по
error.code, а не по текстуmessage. - Поле
error.release— идентификатор обновления целиком: имя модуля и номер версии одной строкой. Сравнивать его на равенство как строку, разбирать как номер версии нельзя. - Частые повторы ничего не меняют: состояние переключается приездом обновления на портал, а не повтором вызова. Заголовка
Retry-Afterи поляretryAfterв этом отказе нет, потому что срока платформа не знает. Пока обновление не пришло, показывайте пользователю ожидание названной версии, а не ошибку интеграции.
`BITRIX_UNAVAILABLE` (502)
Битрикс24 вернул 5xx или не ответил в отведённое время.
{
"success": false,
"error": {
"code": "BITRIX_UNAVAILABLE",
"message": "Bitrix24 returned 503 Service Unavailable"
}
}
Причины:
- Технические работы или перегрузка на стороне Битрикс24.
- Сетевые проблемы между Вайбкод и порталом.
Решение:
- Повторить запрос через несколько минут, реализовав повторные попытки с экспоненциальной задержкой.
- Для записывающих операций (POST/PATCH) — сначала проверьте, не применился ли исходный запрос. Медленный портал может обработать запись уже ПОСЛЕ того, как API вернул таймаут — слепой повтор создаст дубль (задачи, эпика, комментария). Перед ретраем сделайте
GETпо списку/записи (например, поиск по только что отправленному названию) и повторяйте только если записи нет. - Проверить статус портала по адресу
/bitrix/admin/site_checker.php(для администратора портала).
`QUEUE_OVERFLOW` (429)
Очередь запросов к Битрикс24 для конкретного портала переполнена: слишком много вызовов уже в ожидании (по умолчанию — более 100). Ответ возвращается мгновенно, за миллисекунды, с HTTP-заголовком Retry-After: N (секунды).
{
"success": false,
"error": {
"code": "QUEUE_OVERFLOW",
"message": "Portal queue overloaded — 100 Bitrix24 calls already pending",
"userMessage": "Слишком много одновременных запросов к Bitrix24 — повторите через несколько секунд.",
"hint": "Honor the Retry-After header. Use exponential backoff with jitter for repeated failures.",
"retryAfter": 10
}
}
Решение:
- Очередь портала переполнена — повторите запрос через
Retry-Afterсекунд, используя backoff с джиттером (случайной добавкой к паузе), чтобы повторы от разных клиентов не пришли одной волной. - Уменьшить параллелизм на стороне клиента.
- Объединить вызовы через
POST /v1/batch.
`QUEUE_TIMEOUT` (429)
Очередь запросов к Битрикс24 для конкретного портала перегружена: больше 30 секунд ожидания.
{
"success": false,
"error": {
"code": "QUEUE_TIMEOUT",
"message": "Portal queue saturated — too many concurrent Bitrix24 calls",
"userMessage": "Запросы к Битрикс24 в очереди дольше 30 секунд. Вероятно, на портале много одновременных операций.",
"hint": "If this is a /search request with a wide date range, try adding \"autoWindow\": false OR narrow the date range to <14 days. See /v1/guide for optimization tips.",
"retryAfter": 10
}
}
Запрос НЕ был отправлен в Битрикс24 — безопасно повторить.
Решение:
- Повторить через
retryAfterсекунд, используя backoff с джиттером. - Уменьшить параллелизм.
- Для
/search-эндпоинтов — сузить диапазон дат либо передатьautoWindow: false. - Объединить вызовы через
POST /v1/batch. - Проверить таймаут на своей стороне: ожидание в очереди входит во время ответа, поэтому клиенту нужен запас — Клиентский таймаут.
`TIMEOUT_QUARANTINE` (429)
Метод несколько раз подряд не ответил вашему порталу Битрикс24 за отведённое вызову время, поэтому Вайбкод поставил пару «портал + метод» на паузу и больше не отправляет к ней запросы.
В процессе раскатки. Механизм включается на порталах постепенно. Пока он не включён на вашем, этот код не приходит: вызовы уходят в Битрикс24 как раньше и упираются в таймаут
BITRIX_TIMEOUT.
{
"success": false,
"error": {
"code": "TIMEOUT_QUARANTINE",
"message": "Vibe-side block (not a Bitrix24 limit). crm.item.list timed out 5 times in a row on this portal, so calls to it are paused.",
"hint": "Портал не отвечал на этот метод за отведённое вызову время, поэтому каждый следующий вызов только добавлял бы нагрузку. Дождитесь срока из Retry-After и НЕ сокращайте интервал повторов: агрессивный повтор занимает слот пробы восстановления и держит метод закрытым для всего портала дольше. Раз в 5 мин один вызов пропускается как проба, и первый успешный ответ снимает паузу немедленно. Облегчите запрос — меньше полей, меньше страница, более узкий фильтр: пару снимает с паузы именно лёгкий вызов.",
"retryAfter": 288,
"scope": "portal"
}
}
Заголовки ответа:
Retry-After: 288
Причины:
- Метод стабильно не отвечает порталу за отведённое вызову время — обычно из-за тяжёлого запроса: широкий диапазон дат, много полей в
select, большая страница, фильтр по неиндексированному полю. - Пауза считается на пару «портал + метод» и не зависит от того, каким ключом сделан вызов:
scope: "portal"означает, что её видят ВСЕ ключи портала, включая чужие интеграции. Контраст —OPERATION_TIME_LIMITсоscope: "apiKey": тот отказ про ваш ключ, этот — про весь портал. - Это отказ на стороне Вайбкод, а не лимит Битрикс24: запрос до портала не дошёл, поэтому ничего не изменилось — повтор безопасен даже для методов записи.
- Код приходит и внутри
200-ответа — на подвызовахPOST /v1/batch, которые Вайбкод исполняет отдельными запросами (data.errors[<id>]), и на элементах батча одной сущности (data[i].error). У200-конверта нет заголовкаRetry-Afterдля отдельного подвызова, поэтому срок приходит полемretryAfter, аscopeиhint— те же, что в одиночном429.
Решение:
- Дождаться срока из
retryAfter(или заголовкаRetry-After) и не сокращать интервал повторов: пока пауза действует, один вызов раз в 5 минут пропускается как проба восстановления, и агрессивный повтор занимает этот слот собой — метод остаётся закрытым для всего портала дольше, чем если бы вы просто подождали. - Добавлять к паузе случайную добавку (джиттер), чтобы повторы разных клиентов не пришли одной волной.
- Облегчить сам вызов: меньше полей в
select, меньше страница, более узкий фильтр или более узкий интервал дат. Пауза снимается первым успешным ответом, поэтому её снимает именно лёгкий вызов — тяжёлый снова упрётся в таймаут и продлит окно. - Не искать эндпоинт для снятия паузы — его нет, и вмешательство не требуется.
- Сам конверт
POST /v1/batchпод паузу не попадает: он объединяет разные методы, и его собственная задержка не говорит о том, какие из них перестали отвечать.
`OPERATION_TIME_LIMIT` (429)
Битрикс24 приостановил ЭТОТ метод примерно на 5 минут, потому что метод исчерпал бюджет рабочего времени на портале. Отказ приходит и когда его прислал сам портал, и когда Вайбкод отбивает вызов на входе, зная, что пауза ещё действует.
{
"success": false,
"error": {
"code": "OPERATION_TIME_LIMIT",
"message": "Bitrix24 operation-time limiter banned crm.item.list on this portal, retry in 245s",
"userMessage": "Битрикс24 приостановил этот запрос на несколько минут: метод исчерпал лимит рабочего времени на портале. Дождитесь срока из Retry-After — остальные методы работают.",
"hint": "Bitrix24 banned THIS method on this portal for ~5 minutes because it exhausted the portal's operating-time budget. Honor Retry-After — the same call cannot succeed sooner and retrying earlier only adds load. Other methods on the portal are unaffected; spread heavy reads over time or narrow them (fewer fields, smaller pages, POST /v1/batch).",
"retryAfter": 245,
"scope": "apiKey"
}
}
Заголовки ответа:
Retry-After: 245
Причины:
- Метод израсходовал бюджет рабочего времени, который Битрикс24 считает на скользящем окне.
- Пауза адресная:
scope: "apiKey"означает, что Битрикс24 приостановил связку «ваш ключ + этот метод». Другие методы работают, и другие ключи портала тот же метод вызывать могут. Контраст —TIMEOUT_QUARANTINEсоscope: "portal": там пауза общая для всего портала. - Запрос не был выполнен — повтор безопасен, в том числе для методов записи.
- Код приходит и внутри
200-ответа — на подвызовахPOST /v1/batch, которые Вайбкод исполняет отдельными запросами (data.errors[<id>]), и на элементах батча одной сущности (data[i].error). У200-конверта нет заголовкаRetry-Afterдля отдельного подвызова, поэтому срок приходит полемretryAfter, аscopeиhint— те же, что в одиночном429. ПоляuserMessageв конверте нет.
Решение:
- Дождаться срока из
retryAfter(или заголовкаRetry-After): раньше этого срока тот же вызов не пройдёт, а повторы только добавляют нагрузку. - Разнести тяжёлые чтения по времени, а не запускать их пачкой.
- Облегчить вызовы: меньше полей в
select, меньше страница, объединение черезPOST /v1/batch.
`BITRIX_TIMEOUT` (503)
Битрикс24 принял запрос, но не ответил за 15 секунд — исход неизвестен: запрос МОГ примениться на стороне портала.
{
"success": false,
"error": {
"code": "BITRIX_TIMEOUT",
"message": "Bitrix24 accepted the request but did not respond within 15s",
"hint": "For WRITE operations, verify whether the change was applied (re-read the entity) before retrying. Reads are safe to retry.",
"retryAfter": 10
}
}
Решение:
- Для чтения (GET/
/search) — повторить безопасно, после более длинного backoff, чем при429. - Для записывающих операций (POST/PATCH) — сначала перечитайте сущность. Изменение могло уже примениться на стороне Битрикс24, несмотря на то, что ответ не пришёл. Слепой повтор создаст дубль (задачи, эпика, комментария). Проверьте наличие записи (например, поиск по только что отправленному названию) и повторяйте запись только если её нет.
`INTERNAL_ERROR` (500)
Непредвиденная ошибка на стороне API Вайбкод.
{
"success": false,
"error": {
"code": "INTERNAL_ERROR",
"message": "Internal server error"
}
}
Решение:
- Повторить запрос.
- Если ошибка воспроизводится стабильно — отправить тикет через
POST /v1/feedbackс указанием времени запроса. ЗаголовокX-Request-Idиз ответа ускоряет диагностику.
Повторы и backoff
Сводка по кодам, которые сигнализируют о временной проблеме и подразумевают повтор:
| Код | HTTP | Стратегия повтора |
|---|---|---|
RATE_LIMITED, QUEUE_OVERFLOW, QUEUE_TIMEOUT |
429 | Повтор через Retry-After + backoff с джиттером (случайной добавкой к паузе) |
LARGE_BODY_BACKEND_BUSY |
429 | Повтор через Retry-After + джиттер. Запрос не выполнялся и состояние не менял — повтор безопасен и для записи |
OPERATION_TIME_LIMIT |
429 | Повтор строго через Retry-After: раньше этого срока тот же вызов не пройдёт. scope: "apiKey" — пауза только на вызывающем ключе |
TIMEOUT_QUARANTINE |
429 | Повтор через Retry-After + джиттер, и не сокращая интервал: агрессивный повтор занимает слот пробы восстановления и держит метод закрытым для всего портала дольше. scope: "portal" — пауза общая для всех ключей портала |
BITRIX_TIMEOUT |
503 | Более длинный backoff, чем при 429. Для write-операций — сначала verify-before-retry: перечитайте сущность, изменение могло уже примениться |
BITRIX_UNAVAILABLE |
502 | Повтор не поможет без изменения запроса — это 5xx самого Битрикс24 или сетевая проблема между Вайбкод и порталом, а не временная перегрузка очереди |
Обработка ошибок в коде
JavaScript
async function vibeRequest(url, options = {}) {
const response = await fetch(url, {
...options,
headers: {
'X-Api-Key': process.env.VIBE_API_KEY,
'Content-Type': 'application/json',
...options.headers,
},
});
const data = await response.json();
if (!data.success) {
const { code, message, retryAfter } = data.error;
switch (code) {
case 'RATE_LIMITED':
case 'QUEUE_TIMEOUT': {
const wait = retryAfter ?? Number(response.headers.get('Retry-After') ?? 1);
await new Promise(r => setTimeout(r, wait * 1000));
return vibeRequest(url, options);
}
case 'BITRIX_UNAVAILABLE':
await new Promise(r => setTimeout(r, 5000));
return vibeRequest(url, options);
case 'MISSING_API_KEY':
case 'INVALID_API_KEY':
throw new Error('Проверьте API-ключ');
default:
throw new Error(`${code}: ${message}`);
}
}
return data;
}
Python
import os
import time
import requests
def vibe_request(url, method="GET", json_data=None):
headers = {
"X-Api-Key": os.environ["VIBE_API_KEY"],
"Content-Type": "application/json",
}
response = requests.request(method, url, headers=headers, json=json_data)
data = response.json()
if not data.get("success"):
err = data.get("error", {})
code = err.get("code")
message = err.get("message")
retry_after = err.get("retryAfter") or int(response.headers.get("Retry-After", 1))
if code in ("RATE_LIMITED", "QUEUE_TIMEOUT"):
time.sleep(retry_after)
return vibe_request(url, method, json_data)
if code == "BITRIX_UNAVAILABLE":
time.sleep(5)
return vibe_request(url, method, json_data)
raise Exception(f"{code}: {message}")
return data
PHP
function vibeRequest(string $url, string $method = 'GET', ?array $data = null): array {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => [
'X-Api-Key: ' . getenv('VIBE_API_KEY'),
'Content-Type: application/json',
],
]);
if ($data !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
$body = json_decode(curl_exec($ch), true);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($body === null) {
throw new Exception("HTTP error: $httpCode");
}
if (empty($body['success'])) {
$errCode = $body['error']['code'] ?? 'UNKNOWN';
$errMsg = $body['error']['message'] ?? 'Unknown error';
$retryAfter = $body['error']['retryAfter'] ?? 1;
if (in_array($errCode, ['RATE_LIMITED', 'QUEUE_TIMEOUT'], true)) {
sleep((int) $retryAfter);
return vibeRequest($url, $method, $data);
}
if ($errCode === 'BITRIX_UNAVAILABLE') {
sleep(5);
return vibeRequest($url, $method, $data);
}
throw new Exception("$errCode: $errMsg");
}
return $body;
}