Ошибки и лимиты

Коды ошибок PlusVibe API: 401 (ключ), 402 (баланс), 403 (IP), 429 (лимит частоты). Как обрабатывать ошибки и повторять запросы с экспоненциальной задержкой.

Ошибки, сформированные PlusVibe на /v1/*, имеют JSON-envelope error.message, error.type и error.code. Не используйте текст сообщения или заголовки стороннего сервиса как контракт.

Формат ошибки

{
  "error": {
    "message": "insufficient balance",
    "type": "insufficient_quota",
    "code": 402,
    "request_id": "8d4b6b3a-..."
  }
}

Коды ответов

ПараметрТипОписание
401authentication_error / 401Нет, формат неверен или ключ отключён. Не повторять до исправления credentials.
402insufficient_quota / 402Нет доступного баланса или лимита — ожидание его не исправит. 402 никогда не приходит с Retry-After и повторять его не нужно: пополните баланс или дождитесь обновления окна подписки.
403permission_error или policy type / 403IP, модель или политика не разрешают запрос. Не повторять без изменения запроса или настроек.
429rate_limit_exceeded, inflight_client_cap или rate_limit_error / 429Ваш лимит, лимит одновременных запросов, временно занятый резерв баланса (cause reserved_in_flight) или ограничение поставщика. Повторять только после Retry-After; 429 никогда не означает, что исчерпан ваш баланс.
410media_endpoint_retired / media_endpoint_retiredТолько для retired media routes. Не повторять; перейдите на /api/media/generate.
413invalid_request_error / 413Только Files API: файл больше 50 MiB. Уменьшите файл, затем создайте новый запрос.
503overloaded / 503Глобальная перегрузка edge. Повторять после Retry-After: 2. Другие 503 могут быть не retryable без изменения модели или запроса.

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

ПараметрТипОписание
x-pv-cost-rubstringBest-effort оценка стоимости в рублях. В потоках заголовок доступен всегда, когда известна входная оценка; поле pv_cost_rub в финальном usage-событии появляется только при x-pv-cost: 1. Фактическое списание — в истории usage.
x-pv-generation-idstringID записи в истории использования (GET /v1/generations/{id}). Возвращается только для не-потоковых (non-streaming) запросов chat/completions.
x-pv-dropped-paramsstringСписок параметров запроса через запятую, которые выбранный маршрут не принимает и которые поэтому не были отправлены модели (например temperature,top_p). Появляется только когда что-то действительно снято, на ответах и на ошибках. Мы никогда не снимаем параметр молча: если заголовка нет — всё, что вы прислали, ушло в модель как есть.
Retry-AfterintegerСекунды ожидания. Edge ставит его на 429 частоты, 429 concurrency (5), 503 global overload (2) и некоторых временных 402. Не предполагается для каждого 429/503.
Для потоковых запросов (stream: true) x-pv-generation-id не возвращается, так как биллинг завершается после окончания стрима. Историю запросов смотрите через GET /v1/generations.

Лимиты частоты и параллелизм

ПараметрТипОписание
0 / 50 / 100 / 300 / 1 000 ₽RPM90 / 550 / 1 100 / 3 300 / 11 000 запросов в минуту соответственно. Публикуется только исполняемый RPM: TPM не ограничивается как клиентский runtime-лимит.
RPM account-wideedgeRPM считается по клиентскому аккаунту сразу для всех его API-ключей. Индивидуальный лимит клиента может только уменьшить tier RPM.
0 / 50 / 100 / 300 / 1 000 ₽concurrency4 / 25 / 50 / 150 / 500 одновременных запроса соответственно. Лимит одновременных запросов определяется тем же тиром баланса, что и RPM, и считается по клиентскому аккаунту.
Превышение параллелизмаedgeПревышение лимита аккаунта - 429 и Retry-After: 5. Кроме него действует общий защитный предел сервиса на все аккаунты сразу: 503 и Retry-After: 2. Эти значения могут быть настроены сервисом.

Повтор запросов (retry)

Для retryable ответа сначала используйте Retry-After, если он есть. Без заголовка не считайте любой 429 или 503 автоматически retryable: проверьте HTTP status и публичный error.type, устраните не-retryable причину и используйте ограниченный backoff только для временной ошибки.

import time, requests

def call_with_retry(url, headers, payload, max_retries=5):
    for attempt in range(max_retries):
        r = requests.post(url, headers=headers, json=payload)
        if r.status_code == 429:
            # уважаем Retry-After, иначе экспоненциальная задержка
            wait = int(r.headers.get("Retry-After", 2 ** attempt))
            time.sleep(wait)
            continue
        return r
    return r
Ошибки и лимиты API PlusVibe — коды 401, 402, 403, 429 | PlusVibe API