#Коды ошибок

Справочник кодов ошибок Vibe API: единый формат ответа, перечень кодов, типичные причины и способы устранения. Применяется ко всем эндпоинтам /v1/....

#Формат ответа при ошибке

Каждый ответ с ошибкой возвращается в едином виде. error — объект.

JSON
{
  "success": false,
  "error": {
    "code": "ENTITY_NOT_FOUND",
    "message": "Элемент не найден"
  }
}
Поле Тип Обяз. Описание
success boolean да При ошибке всегда false
error.code string да Машиночитаемый код ошибки. Используйте для различения типов ошибок в коде клиента
error.message string да Описание ошибки на языке backend (русский или английский)
error.hint string нет Подсказка для разработчика: что попробовать дальше, на какие пределы обратить внимание
error.userMessage string нет Сообщение для конечного пользователя на русском языке. Появляется в биллинговых, инфраструктурных и тарифных ошибках
error.warning string нет Появляется при повторяющихся одинаковых ошибках на одном ключе. Сигнал, что в коде клиента, скорее всего, баг
error.retryAfter number нет Секунды до следующей попытки. Появляется в 429 (rate-limit) и 504 (queue timeout)

Пример ответа с дополнительными полями (429 RATE_LIMITED):

JSON
{
  "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.

#Сводная таблица кодов

Таблица покрывает основные коды, которые встречаются на любом эндпоинте Vibe 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 ...
TOKEN_EXPIRED 401 Срок действия OAuth-токена истёк
TOKEN_REFRESH_FAILED 401 Не удалось обновить OAuth-токен на стороне Битрикс24
WRONG_KEY_TYPE 401 Тип ключа не подходит к эндпоинту: например, management-ключ на entity-маршруте

#Права и скоупы

Код HTTP Когда возникает
SCOPE_DENIED 403 У ключа нет нужного скоупа (например, crm для сделок, imbot для ботов)
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

#Валидация запроса

Код HTTP Когда возникает
VALIDATION_ERROR 400 Тело или query не прошли проверку схемы. message содержит подробности по полям
INVALID_PARAMS 400 Битрикс24 вернул INVALID_PARAMS или route-handler нашёл некорректное значение параметра
INVALID_REQUEST 400 Структура запроса не соответствует требуемой (например, calls в /v1/batch пустой массив или содержит больше 50 элементов)
MISSING_PARAMS 400 Не передан обязательный параметр, явно перечисленный в схеме эндпоинта
MISSING_REQUIRED_FILTER 400 Не передан обязательный фильтр для list-эндпоинтов, требующих контекста (timelines, task-comments и подобные)
INVALID_FILTER_FIELD 400 Фильтр по несуществующему полю сущности
UNKNOWN_SORT_FIELD 400 Сортировка по несуществующему полю (для сущностей, у которых валидатор сортировки активен)
BATCH_LIMIT_EXCEEDED 400 Запрос содержит больше 50 элементов в массивной операции (vipchats, task-comments и подобные)

#Ресурс не найден

Код HTTP Когда возникает
ENTITY_NOT_FOUND 404 Запись CRM-сущности с указанным id не существует. Канонический код для /v1/deals/:id, /v1/contacts/:id и подобных
NOT_FOUND 404 Только GET /:id: Битрикс24 вернул success, но result пустой (применимо к нескольким смарт-методам)

Доменные *_NOT_FOUND (BOT_NOT_FOUND, SERVER_NOT_FOUND, AGENT_NOT_FOUND, PORTAL_NOT_FOUND, USER_NOT_FOUND, FILE_NOT_FOUND) описаны на страницах соответствующих разделов.

#Конфликты состояния

Код HTTP Когда возникает
CONFLICT 409 Текущее состояние ресурса несовместимо с запросом
ALREADY_EXISTS 409 Запись с такими ключевыми полями уже существует

#Биллинг и тариф

Возникают на эндпоинтах создания и пробуждения инфраструктуры (серверы, агенты, управляемые боты). Ответ содержит userMessage на русском языке для показа в интерфейсе клиента.

Код HTTP Когда возникает
BILLING_EXHAUSTED 402 Баланс ушёл в красную зону, аккаунт заморожен. Нужен top-up
ACCOUNT_FROZEN 402 Платёжный аккаунт заморожен по другим причинам
COMMERCIAL_PLAN_REQUIRED 402 Бесплатный тариф Битрикс24, пробный период недоступен или уже использован
TRIAL_EXPIRED 402 14-дневный пробный период завершён
TRIAL_PORTAL_LIMIT 402 На пробном периоде превышен общий лимит серверов на портал
TRIAL_USER_LIMIT 402 На пробном периоде превышен лимит серверов на пользователя
PLAN_NOT_ALLOWED_ON_TRIAL 402 Запрошенный план сервера/агента недоступен на пробном периоде
SERVER_WAKE_BLOCKED 403 Пробуждение сервера заблокировано по небиллинговой причине

#Ограничение частоты

Код HTTP Когда возникает
RATE_LIMITED 429 Битрикс24 ограничил частоту запросов или превышен внутренний лимит. В ответе — retryAfter (секунды) и заголовок Retry-After
ERROR_LOOP_DETECTED 429 Блокировка на стороне Вайбкод: один и тот же запрос повторяется с одинаковой ошибкой. Сигнал о баге в коде клиента. Каждый N-й запрос пробрасывается дальше для проверки восстановления

#Backend и сторонние сервисы

Код HTTP Когда возникает
BITRIX_ERROR 422 Битрикс24 вернул бизнес-ошибку, не подпадающую под более узкие категории (ACCESS_DENIED, NOT_FOUND, INVALID_PARAMS)
BITRIX_UNAVAILABLE 502 Битрикс24 вернул 5xx или не ответил вовремя
WINDOWED_SEARCH_FAILED 502 Все под-окна /search завершились с ошибкой
QUEUE_TIMEOUT 504 Очередь портала перегружена: больше 30 секунд ожидания на стороне Вайбкод
INTERNAL_ERROR 500 Непредвиденная ошибка backend Вайбкод

#Подробное описание

#`MISSING_API_KEY` (401)

Запрос не содержит заголовка X-Api-Key.

JSON
{
  "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)

Переданный ключ не существует или его формат не распознан.

JSON
{
  "success": false,
  "error": {
    "code": "INVALID_API_KEY",
    "message": "Invalid API key"
  }
}

Причины:

  • Опечатка или лишние пробелы в ключе.
  • Ключ удалён владельцем или администратором.
  • Ключ от другого окружения (staging/production).
  • Префикс не из числа поддерживаемых: vibe_api_, vibe_app_, vibe_live_, vibe_mgmt_.

Решение:

  • Сверить ключ в личном кабинете на странице /keys.
  • Создать новый ключ, если старый удалён.

#`SCOPE_DENIED` (403)

У ключа нет нужного скоупа для запрошенной операции.

JSON
{
  "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: у пользователя или приложения нет прав на сущность или операцию.

JSON
{
  "success": false,
  "error": {
    "code": "BITRIX_ACCESS_DENIED",
    "message": "ACCESS_DENIED"
  }
}

Причины:

  • У пользователя нет прав на сущность в CRM (например, чужая сделка с ограничением видимости).
  • Приложение Битрикс24 не имеет нужного scope в правах на портале.
  • Запрашиваемый модуль выключен на портале (отсутствует CRM, бот-платформа и тому подобное).

Решение:

  • Проверить права пользователя в карточке сущности Битрикс24.
  • Открыть настройки приложения на портале и расширить набор разрешений.

#`VALIDATION_ERROR` (400)

Тело или query-параметры не прошли проверку схемы. Для большинства V1-эндпоинтов обработка реализована через Zod, поэтому сообщение содержит конкретные поля с проблемами.

JSON
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "fields.title: Required; fields.stageId: Expected string, received number"
  }
}

Причины:

  • Отсутствуют обязательные поля.
  • Тип значения не соответствует схеме (строка вместо числа, неверный формат даты).
  • Тело запроса — некорректный JSON либо отсутствует заголовок Content-Type: application/json.

Решение:

  • Сверить body со схемой эндпоинта в справочнике сущностей или на странице конкретного эндпоинта.
  • Числа передавать без кавычек, даты — в формате ISO 8601 (2026-04-29T10:00:00).
  • Добавить заголовок Content-Type: application/json.

#`INVALID_PARAMS` (400)

Битрикс24 или route-handler нашёл некорректное значение параметра. Часто появляется как обёртка для ошибок Битрикс24 формата INVALID_PARAMS: ....

JSON
{
  "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-эндпоинте, который требует контекста.

JSON
{
  "success": false,
  "error": {
    "code": "MISSING_REQUIRED_FILTER",
    "message": "filter[entityType] and filter[entityId] are required for /v1/timelines"
  }
}

Причины:

  • Список тайм-лайн-записей, комментариев и других «вложенных» данных требует пары родительских идентификаторов.

Решение:

  • Добавить обязательные параметры фильтра, перечисленные в message или на странице эндпоинта.

#`BATCH_LIMIT_EXCEEDED` (400)

Запрос превышает лимит элементов в массивной операции. На уровне /v1/batch лимит проверяется через INVALID_REQUEST со ссылкой на Array must contain at most 50 element(s). На доменных bulk-эндпоинтах (например, chats, task-comments) — отдельный код BATCH_LIMIT_EXCEEDED.

JSON
{
  "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 не существует или была удалена.

JSON
{
  "success": false,
  "error": {
    "code": "ENTITY_NOT_FOUND",
    "message": "Элемент не найден"
  }
}

Причины:

  • Запись с таким id действительно не существует.
  • Запись была удалена параллельным процессом.
  • Перепутана сущность: запрос идёт на /v1/deals/:id, а ID — от лида.

Решение:

  • Проверить наличие записи через list-эндпоинт сущности.
  • Восстановить из корзины Битрикс24, если запись была удалена недавно (через интерфейс портала).

#`RATE_LIMITED` (429)

Битрикс24 ограничил частоту запросов либо сработал внутренний лимит Вайбкод.

JSON
{
  "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

Причины:

  • Сложилось слишком много одновременных запросов от одного ключа.
  • Превышен лимит запросов в секунду на стороне Битрикс24.

Решение:

  • Дождаться времени из error.retryAfter или заголовка Retry-After.
  • Реализовать повторные попытки с экспоненциальной задержкой.
  • Объединять до 50 вызовов через `POST /v1/batch`.
  • Кэшировать редко изменяемые справочные данные (поля, статусы, валюты).

#`ERROR_LOOP_DETECTED` (429)

Вайбкод фиксирует серию одинаковых ошибок на одном ключе для одного метода Битрикс24 — и временно блокирует запрос на стороне Вайбкод, чтобы не накручивать счётчики Битрикс24. Каждый N-й запрос пробрасывается дальше: если backend восстановился, блокировка снимается автоматически.

JSON
{
  "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 — там указан конкретный метод с серией ошибок.
  • Найти источник запроса в коде, исправить параметры или логику.
  • При платформенной аварии — администратор платформы может сбросить блокировку через POST /api/platform/analytics/circuit-breaker/<apiKeyId>/clear.

#`BILLING_EXHAUSTED` (402)

Платёжный аккаунт ушёл в красную зону: баланс отрицательный, грейс-период исчерпан. Запросы на создание и пробуждение инфраструктуры блокируются до пополнения.

JSON
{
  "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 после окончания пробного периода.

JSON
{
  "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-дневный пробный период завершился, тариф остался бесплатным.

JSON
{
  "success": false,
  "error": {
    "code": "TRIAL_EXPIRED",
    "message": "Trial period has ended.",
    "userMessage": "Пробный период (14 дней) завершён. Перейдите на коммерческий тариф Битрикс24, чтобы продолжить пользоваться серверами и агентами."
  }
}

Решение:

  • Перейти на коммерческий тариф Битрикс24.
  • Обновить статус через POST /v1/portals/:id/refresh-tariff.

#`BITRIX_ERROR` (422)

Битрикс24 вернул бизнес-ошибку, которая не подпадает под более узкие категории (ACCESS_DENIED, NOT_FOUND, INVALID_PARAMS, RATE_LIMITED).

JSON
{
  "success": false,
  "error": {
    "code": "BITRIX_ERROR",
    "message": "Invalid filter: field 'NON_EXISTENT_FIELD' is not allowed in filter",
    "hint": "Known Bitrix24 limitation: …"
  }
}

Причины:

  • Битрикс24 отверг операцию по бизнес-причине: несовместимое состояние, неподдерживаемое значение, бизнес-правило.
  • Запрос работает на портале, где соответствующий модуль отключён.

Решение:

  • Прочитать message — там оригинальный текст ошибки от Битрикс24.
  • При наличии hint — использовать его как первый шаг диагностики.

#`BITRIX_UNAVAILABLE` (502)

Битрикс24 вернул 5xx или не ответил в отведённое время.

JSON
{
  "success": false,
  "error": {
    "code": "BITRIX_UNAVAILABLE",
    "message": "Bitrix24 returned 503 Service Unavailable"
  }
}

Причины:

  • Технические работы или перегрузка на стороне Битрикс24.
  • Сетевые проблемы между Вайбкод и порталом.

Решение:

  • Повторить запрос через несколько минут, реализовав повторные попытки с экспоненциальной задержкой.
  • Проверить статус портала по адресу /bitrix/admin/site_checker.php (для администратора портала).

#`QUEUE_TIMEOUT` (504)

Очередь запросов к Битрикс24 для конкретного портала перегружена: больше 30 секунд ожидания.

JSON
{
  "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
  }
}

Решение:

  • Уменьшить параллелизм, отдать клиенту повторную попытку через retryAfter секунд.
  • Для /search-эндпоинтов — сузить диапазон дат либо передать autoWindow: false.
  • Объединить вызовы через POST /v1/batch.

#`INTERNAL_ERROR` (500)

Непредвиденная ошибка на стороне Vibe API.

JSON
{
  "success": false,
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "Internal server error"
  }
}

Решение:

  • Повторить запрос.
  • Если ошибка воспроизводится стабильно — отправить тикет через POST /v1/feedback с указанием времени запроса. Заголовок X-Request-Id из ответа ускоряет диагностику.

#Обработка ошибок в коде

#JavaScript

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

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

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;
}

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