Для AI-агентов: markdown этой страницы — /docs-content/errors/limits.md индекс документации — /llms.txt

Лимиты, очереди и паузы

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

Сводная таблица всех кодов API Вайбкод — Коды ошибок.

`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.",
    "scope": "portal"
  }
}

Заголовки ответа:

Retry-After: 2

В теле одиночного 429 RATE_LIMITED поля retryAfter нет — срок повтора приходит заголовком Retry-After. Если платформа формирует подошибку RATE_LIMITED для отдельного вызова пакета, срок приходит полем retryAfter в data.errors.<id> или data[i].error: конверт отвечает 200 и не несёт отдельного заголовка для подвызова. Прямой отказ Битрикс24 внутри общего пакета может прийти только с code и message, без срока повтора — подробности. Поле hint приходит не на всех путях отказа: у границы платформы тело состоит из code и message. Один код объединяет локальные ограничения до отправки и отказ по частоте от уже вызванного Битрикс24, поэтому по RATE_LIMITED нельзя утверждать, что целевой вызов не отправлялся. Оба известных источника одиночного отказа отказывают без применения операции, и после Retry-After повтор записи безопасен. Полная матрица — Что безопасно повторять.

Причины:

  • Всплеск запросов с одного адреса превысил границу платформы — 60 запросов в секунду, считается по IP-адресу клиента. Такой отказ приходит с Retry-After: 1 и без заголовков X-RateLimit-*. У части эндпоинтов на границе действует свой, более строгий лимит.
  • Исчерпан собственный поминутный лимит эндпоинта. По умолчанию он считается по API-ключу. Исключения, где счётчик один на портал и все его ключи делят его между собой: POST /v1/search — 60 в минуту, POST /v1/batch — 30 в минуту, POST /v1/research — 20 в минуту, чтения по сущностям — 300 в минуту, и пакет по одной сущности POST /v1/{entity}/batch — 30 в минуту. У чтений по сущностям счётчик ведётся у каждой сущности и у каждой операции по отдельности: список, поиск, агрегаты, описание полей, связанные записи и товарные позиции. Названные числа — платформенные потолки, и они делятся на реплики бэкенда, поэтому фактическое значение для вашего ключа приходит в заголовке x-ratelimit-limit.
  • Превышен лимит запросов в секунду на стороне Битрикс24. Он считается на портал.

Решение:

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

`CALLER_RATE_LIMITED` (429)

Исчерпан общий поминутный лимит запросов вызывающего. Отказ даёт сама платформа Вайбкод до выполнения операции, поэтому действие не применялось и повтор после паузы безопасен.

Запросы к /v1 считаются в общих счётчиках:

Счётчик X-RateLimit-Scope Порог в минуту
API-ключ key 600 на ключ
Владелец ключей: все ключи одного человека вместе user 1200
Опрос событий бота — GET /v1/bots/{botId}/events bot 120 на бота

У опроса событий бота свои счётчики, и расходуются они отдельно от остальных запросов. Кроме 120 в минуту на бота, опросы считаются на ключ (key, 600 в минуту на все опросы одного ключа) и на владельца ключей (user, 1200 в минуту на все опросы его ключей). Пороги те же, что у остальных запросов, а расход раздельный: опросы не уменьшают остаток для остальных запросов, остальные запросы не уменьшают остаток для опросов.

Приложение OAuth считается по пользователю приложения на портале: у каждого пользователя приложения на каждом портале свой счётчик key, отдельного счётчика владельца для него нет. Опросы событий бота у приложения считаются так же, своим счётчиком key на пользователя приложения на портале. Индивидуальный порог, заданный ключу приложения, тоже действует на каждого пользователя приложения, а не на ключ целиком. Запросы AI-методов этими счётчиками не считаются, у них собственный лимит. Исключение — управление ключами AI-провайдеров (/v1/ai/credentials и /v1/ai/providers): эти запросы считаются общими счётчиками наравне с остальными.

JSON
{
  "success": false,
  "error": {
    "code": "CALLER_RATE_LIMITED",
    "message": "Too many requests: the key limit is 600 per minute. Retry after 23 seconds."
  }
}

Заголовки ответа:

Retry-After: 23
X-RateLimit-Scope: key

X-RateLimit-Scope называет сработавший счётчик: key, user или bot. Retry-After — секунды до конца текущего минутного окна. Повтор раньше этого срока вернёт тот же отказ и окно не продлит. Поля retryAfter в теле нет.

Названные пороги (600, 1200, 120) — платформенные потолки, и они делятся между репликами бэкенда: счётчики ведутся отдельно на каждой реплике. Клиент, который работает по одному соединению, может остаться на одной реплике и получить отказ раньше названного числа. Эффективное число слой в заголовке не публикует и вычислить его из других заголовков нельзя: закладывайте темп заметно ниже потолка и при 429 ждите Retry-After.

Опирайтесь только на Retry-After и X-RateLimit-Scope. Если у эндпоинта есть собственный лимит, в этом отказе могут прийти и X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. Они относятся к лимиту эндпоинта и общий лимит не описывают: остаток в X-RateLimit-Remaining больше нуля не означает, что запрос можно повторить раньше срока из Retry-After.

Причины:

  • Ключ отправил слишком много запросов за минуту (платформенный потолок — 600, на одной реплике отказ может прийти раньше), например при выгрузке записей по одной.
  • Несколько ключей одного человека вместе отправили слишком много запросов в минуту (потолок — 1200, отказ может прийти раньше).
  • Бот опрашивает события слишком часто (потолок — 120 раз в минуту), либо все опросы одного ключа вместе упёрлись в потолок 600 в минуту, а опросы всех ключей одного человека — 1200. Отказ может прийти раньше названных чисел.

Решение:

  • Дождаться срока из заголовка Retry-After и повторить запрос. Для записи повтор безопасен.
  • Для выгрузок читать записи страницами через поиск и объединять вызовы через POST /v1/batch: один пакетный запрос с несколькими вызовами заменяет много отдельных.
  • Опрашивать события бота реже. Потолки — 120 запросов в минуту на бота, 600 на все опросы одного ключа и 1200 на все опросы ключей одного владельца; держите темп заметно ниже них.
  • По значению X-RateLimit-Scope определить исчерпанный счётчик. Если это user, нагрузку нужно распределить во времени: выпуск новых ключей счётчик владельца не расширяет.

`ERROR_LOOP_DETECTED` (429)

Вайбкод приостанавливает вызовы метода после серии отказов Битрикс24 на одном API-ключе. Исправьте запрос перед продолжением. Повтор неизменённого запроса не устраняет причину.

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

Для проверочного вызова нужны одновременно настроенное количество запросов (по умолчанию 50) и минимальная пауза. Первая пауза — 1 минута; каждая неудачная проба увеличивает её до 5, 15, затем 60 минут. Дальнейшие неудачи сохраняют паузу 60 минут. Локальный отказ без отправки в Битрикс24 не тратит пробу и не увеличивает её паузу. Пока проверочный вызов не завершён, новая проба не отправляется.

Заголовок Retry-After и поле error.retryAfter содержат одинаковую рекомендуемую паузу в секундах: остаток времени до пробы, а если время уже истекло, но вызов ещё блокируется — 60 секунд до повторной проверки. Допуск не гарантирован: условие количества запросов тоже должно выполниться, а другая проверочная операция может ещё выполняться. Проба может дойти до Битрикс24, поэтому не повторяйте записи автоматически: перед продолжением после исправления причины перечитайте текущее состояние.

Поле error.scope равно "apiKey": блок относится к паре «ключ и метод». Другие методы этого ключа и тот же метод на других ключах продолжают работать.

При начале блокировки владелец ключа получает уведомление бота, не чаще раза в сутки для одной пары «ключ и метод». В нём указаны приложение или ключ, метод, код ошибки и число отказов; текста ошибки портала нет. Публикуются только известные коды: неизвестный код и код маршрута, скрывающего портальные ошибки, заменяются на BITRIX_ERROR.

Решение:

  • Прочитать error.message: там указаны метод, код отказа и число последовательных ошибок.
  • Исправить параметры запроса или остановить цикл, если целевой объект удалён.
  • Продолжать только после устранения причины и с учётом Retry-After; успешная проба снимает блок.
  • Обратиться в поддержку, если нужен ручной сброс.

`QUEUE_OVERFLOW` (429)

Очередь запросов к Битрикс24 для конкретного портала переполнена: слишком много вызовов уже в ожидании (по умолчанию — 100 и больше). Ответ возвращается мгновенно, за миллисекунды, с HTTP-заголовком Retry-After: N (секунды).

JSON
{
  "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,
    "scope": "portal"
  }
}

Решение:

  • Повторить запрос через Retry-After секунд, увеличивая паузу перед каждой следующей попыткой и добавляя к ней случайную величину, чтобы повторы от разных клиентов не пришли одной волной.
  • Уменьшить параллелизм на стороне клиента.
  • Объединить вызовы через POST /v1/batch.

`QUEUE_TIMEOUT` (429)

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

JSON
{
  "success": false,
  "error": {
    "code": "QUEUE_TIMEOUT",
    "message": "Portal queue saturated — too many concurrent Bitrix24 calls",
    "userMessage": "Запросы к Bitrix24 в очереди дольше 80 с. Вероятно, на портале много одновременных операций.",
    "hint": "The request was NOT sent to Bitrix24 — safe to retry (honor Retry-After, use backoff with jitter). If this is a /search request with a wide date range, try adding \"autoWindow\": false OR narrow the date range to <14 days.",
    "retryAfter": 10,
    "scope": "portal"
  }
}

Запрос НЕ был отправлен в Битрикс24 — безопасно повторить.

Число секунд в userMessage — то ожидание, которое применилось к этому вызову. Обрабатывайте отказ по коду QUEUE_TIMEOUT, а срок повтора берите из retryAfter и заголовка Retry-After.

Решение:

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

`TIMEOUT_QUARANTINE` (429)

Когда механизм включён для портала, метод, который три раза подряд не ответил за отведённое вызову время, ставит пару «портал + метод» на паузу: Вайбкод временно больше не отправляет к ней запросы.

JSON
{
  "success": false,
  "error": {
    "code": "TIMEOUT_QUARANTINE",
    "message": "Vibe-side block (not a Bitrix24 limit). crm.item.list timed out 3 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 минут, потому что метод исчерпал бюджет рабочего времени на портале. Отказ приходит и когда его прислал сам портал, и когда Вайбкод отбивает вызов на входе, зная, что пауза ещё действует.

JSON
{
  "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": там пауза общая для всего портала.
  • Первый OPERATION_TIME_LIMIT приходит от уже вызванного метода Битрикс24. После него Вайбкод запоминает паузу и может отбивать следующие запросы до отправки. Поэтому код сам по себе не доказывает отсутствие эффекта: чтение повторять безопасно, а перед повтором записи сначала перечитайте состояние.
  • Код приходит и внутри 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.

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