> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bettertoken.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Ошибки BetterToken API: HTTP-коды, лимиты и повторы

> Разберите ошибки BetterToken API по HTTP-статусу, телу ответа и ID запроса. Исправьте авторизацию, лимиты и тайм-ауты, настройте повторы временных сбоев.

Диагностируйте ошибку BetterToken API по HTTP-статусу и телу ответа вместе. Сохраните ID запроса из `error.message`. Перед повторной отправкой исправьте ошибки авторизации и настройки; повторяйте только запросы со сбоем, который удалось определить как временный.

## Перед диагностикой

Подготовьте Model ID, Base URL и ответ с ошибкой. Проверьте состояние ключа и баланс в [панели BetterToken](https://bettertoken.ai/workspace). Если вы ещё не получили ответ модели, начните с [примеров SDK](/guides/sdk-examples.md) или [настройки вашего инструмента](/ai-tools/overview.md).

## Прочитайте ответ с ошибкой

BetterToken возвращает ошибки API в JSON-объекте. Например, запрос без ключа может вернуть:

```json theme={null}
{
  "error": {
    "code": "",
    "message": "Token not provided (request id: …)",
    "type": "new_api_error"
  }
}
```

Читайте `error.message`, даже если `error.code` пуст. ID запроса в сообщении помогает найти неудачную попытку. Запрос к `/v1/models` без ключа возвращает `401`; он не проверяет, способна ли ваша модель сгенерировать ответ.

Перед обращением в поддержку сохраните:

| Данные | Что записать |
| - | - |
| HTTP-статус | Статус ответа; если HTTP-ответа нет — исключение клиента о тайм-ауте или сетевой ошибке |
| Тело ответа | JSON ошибки или другое содержимое ответа без секретных данных |
| ID запроса | Идентификатор из `error.message`, если он есть |
| Время | Дату, время и часовой пояс попытки |
| Model ID | Точное значение, отправленное в `model` |
| Base URL | Настроенный Base URL и конечный путь запроса |

Не включайте BetterToken API Key в снимки экрана, сообщения поддержке и общедоступные логи.

## Проверьте HTTP-статус

Таблица описывает общие значения статусов HTTP/API и связанные инструкции по настройке. Это не перечень собственных кодов ошибок BetterToken: выбирайте исправление по фактическому ответу.

| Статус | Частая причина | Что проверить сначала | Повторять? |
| - | - | - | - |
| `400` | Неверный запрос, поле или сочетание параметров | Структуру JSON, обязательные поля, модель и требования конечной точки | Сначала исправьте запрос |
| `401` | Ключ отсутствует, недействителен, просрочен или отозван | Состояние ключа, лишние пробелы и заголовок авторизации для протокола | Сначала исправьте авторизацию |
| `403` | Запрос отклонён | Сообщение ответа, баланс, состояние ключа и настройки клиента | Сначала устраните причину отказа |
| `404` | Путь или запрошенный ресурс не найден | Base URL, пропущенный или повторный `/v1`, конечный путь и точный Model ID | Сначала исправьте URL или ресурс |
| `408` / тайм-аут клиента | Сервер не получил полный запрос вовремя либо клиент перестал ждать | Получен ли HTTP-статус, настройки тайм-аута, сеть и состояние запроса в панели | Сначала проверьте, завершился ли запрос |
| `409` / `422`, если возвращены | Обычно конфликт или невозможность обработать содержимое | Подробности ответа, переданное состояние или поля | Сначала устраните причину |
| `429` | Достигнуто ограничение | Тело ответа и заголовки повтора; см. [диагностику лимитов](/faq/codex/usage-limit-vs-api-rate-limit.md) | Только при подтверждённом временном ограничении частоты |
| `500` | Ошибка на стороне сервера | Запись запроса, сообщение и повторяемость сбоя | Ограниченное число повторов при временном сбое |
| `502` / `503` | Ошибка шлюза или upstream-сервиса, временная недоступность | Тело ответа и заголовок `Retry-After`, если он есть | Ограниченное число повторов при временном сбое |
| `504` | Шлюз не дождался ответа upstream-сервиса | Запись в панели и завершение запроса | Проверьте завершение перед повтором |

Ошибки протокола и суффиксов разобраны в [FAQ по Base URL](/faq/model-calling/base-url-config.md). Вопросы кэша — в [FAQ по оплате кэша](/faq/service-assurance/cache-billing.md).

## Повторяйте временные сбои

Если `429` или серверная ошибка определены как временные, используйте экспоненциальную задержку со случайным разбросом и ограничением числа попыток. Соблюдайте `Retry-After`, если он вернулся. Если ожидание превышает бюджет повторов, остановите цикл и подождите вне него. Повторы SDK и ваш цикл расходуют общий бюджет попыток, поэтому при собственной политике отключите повторы SDK.

Не повторяйте без изменений ошибки `400`, `401`, `403`, а также ошибки баланса и настройки. Тайм-аут клиента или разрыв потока не доказывают, что запрос прекратился до обработки. Сначала проверьте **панель управления**, особенно при генерации изображений или в сценарии, где действие может выполниться повторно.

Примеры ниже отправляют запрос Chat Completions без потоковой выдачи, максимум в четыре попытки. Они повторяют HTTP `500`, `502` и `503`. Повторы `429` отключены, пока вы не подтвердите временный лимит частоты. При тайм-ауте, сетевом исключении или `504` выполнение останавливается, чтобы вы проверили завершение. Максимальное ожидание перед каждой повторной попыткой — 30 секунд.

### Подготовьте запрос

Скопируйте актуальный Model ID из [каталога моделей](https://bettertoken.ai/pricing) и замените оба заполнителя. Выберите текстовую модель, доступную через [Chat Completions](/api-reference/chat-completions.md).

```bash theme={null}
export BETTERTOKEN_API_KEY="YOUR_API_KEY"
export BETTERTOKEN_MODEL_ID="YOUR_MODEL_ID"
```

Пример Python использует стандартную библиотеку. Пример JavaScript сохраните в файл `.mjs` и запустите в версии Node.js с поддержкой `fetch` и `AbortSignal.timeout`.

**Python**

```python theme={null}
import json
import os
import random
import time
import urllib.error
import urllib.request
from datetime import datetime, timezone
from email.utils import parsedate_to_datetime

def retry_after_seconds(value):
    try:
        return max(0.0, float(value))
    except ValueError:
        return max(0.0, (
            parsedate_to_datetime(value) - datetime.now(timezone.utc)
        ).total_seconds())

retry_temporary_429 = False  # Enable only after diagnosing the returned limit.
payload = json.dumps({
    "model": os.environ["BETTERTOKEN_MODEL_ID"],
    "messages": [{"role": "user", "content": "Reply with one word: OK"}],
}).encode()
for attempt in range(4):
    request = urllib.request.Request(
        "https://bettertoken.ai/v1/chat/completions", data=payload,
        headers={
            "Authorization": "Bearer " + os.environ["BETTERTOKEN_API_KEY"],
            "Content-Type": "application/json",
        },
    )
    try:
        with urllib.request.urlopen(request, timeout=120) as response:
            print(json.load(response)["choices"][0]["message"]["content"])
        break
    except urllib.error.HTTPError as error:
        body = error.read().decode("utf-8", errors="replace")
        retryable = error.code in (500, 502, 503) or (
            error.code == 429 and retry_temporary_429
        )
        if not retryable or attempt == 3:
            raise RuntimeError(f"HTTP {error.code}: {body}") from error
        delay = random.uniform(0, min(8.0, 2.0 ** attempt))
        retry_after = error.headers.get("Retry-After")
        if retry_after:
            delay = max(delay, retry_after_seconds(retry_after))
        if delay > 30:
            raise RuntimeError("Retry-After exceeds this retry budget") from error
        time.sleep(delay)
```

**JavaScript**

```javascript theme={null}
const retryTemporary429 = false; // Enable only after diagnosing the returned limit.
const payload = {
  model: process.env.BETTERTOKEN_MODEL_ID,
  messages: [{ role: "user", content: "Reply with one word: OK" }],
};
for (let attempt = 0; attempt < 4; attempt++) {
  const response = await fetch("https://bettertoken.ai/v1/chat/completions", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.BETTERTOKEN_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(payload),
    signal: AbortSignal.timeout(120000),
  });
  const body = await response.text();
  if (response.ok) {
    console.log(JSON.parse(body).choices[0].message.content);
    break;
  }
  const retryable = [500, 502, 503].includes(response.status) ||
    (response.status === 429 && retryTemporary429);
  if (!retryable || attempt === 3) {
    throw new Error(`HTTP ${response.status}: ${body}`);
  }
  let delay = Math.random() * Math.min(8000, 1000 * 2 ** attempt);
  const retryAfter = response.headers.get("Retry-After");
  if (retryAfter !== null) {
    const seconds = Number(retryAfter);
    const wait = Number.isFinite(seconds)
      ? seconds * 1000 : Date.parse(retryAfter) - Date.now();
    if (!Number.isFinite(wait)) throw new Error("Invalid Retry-After header");
    delay = Math.max(delay, wait, 0);
  }
  if (delay > 30000) throw new Error("Retry-After exceeds this retry budget");
  await new Promise(resolve => setTimeout(resolve, delay));
}
```

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

## Найдите инструкцию по симптому

| Симптом | Куда перейти |
| - | - |
| Ошибка авторизации, URL или модели в Claude Code | [Частые ошибки Claude Code](/ai-tools/claude-code.md#частые-ошибки) |
| Codex просит войти или игнорирует смену provider | [Частые ошибки Codex CLI / App](/ai-tools/codex.md#частые-ошибки) |
| В Cursor не включается ключ или перестают работать встроенные модели | [Частые ошибки Cursor](/ai-tools/cursor.md#частые-ошибки) |
| Ошибка авторизации, `404` или модели в Cline | [Частые ошибки Cline](/ai-tools/cline.md#частые-ошибки) |
| Ошибка provider, модели или настроек проекта в OpenCode | [Частые ошибки OpenCode](/ai-tools/opencode.md#частые-ошибки) |
| Claude Desktop Gateway не подключается | [Частые ошибки Claude Desktop](/faq/claude-desktop-bettertoken-api.md#частые-ошибки) |
| Предупреждение официального Codex о лимите или API `429` | [Лимит использования и лимит частоты API](/faq/codex/usage-limit-vs-api-rate-limit.md) |
| Изменения не действуют | [Очистка конфликтующих переменных окружения](/best-practices.md#очистите-конфликтующие-переменные-окружения) |
| Обрезанный ответ или ошибка лимита вывода | [Лимит выходных токенов](/faq/model-calling/max-tokens.md) |

## Проверьте исправление

Отправьте короткий некритичный запрос через тот же клиент, Base URL и Model ID, с которыми возникла ошибка. Убедитесь, что получили нормальный ответ. Найдите соответствующую запись в **панели управления** и проверьте модель, статус, расход токенов и списание, прежде чем возвращаться к большому сценарию.

## Частые вопросы

### Любая ошибка 429 означает, что нужно подождать и повторить?

По [FAQ о диагностике лимитов](/faq/codex/usage-limit-vs-api-rate-limit.md) определите, что проверить и подходит ли повтор для полученного ответа.

### Нужно ли увеличивать тайм-аут после одного сбоя?

Сначала выясните, кто перестал ждать: клиент, прокси или upstream-сервис. Используйте [рекомендации по тайм-аутам](/best-practices.md#задайте-большой-timeout), затем проверьте небольшой запрос.

## См. также

* [Примеры запросов через SDK](/guides/sdk-examples.md)
* [Потоковые ответы и инструменты](/guides/streaming-and-tool-calling.md)
* [Справочник API](/api-reference/introduction.md)
* [Поддерживаемые инструменты](/ai-tools/overview.md)
* [FAQ по оплате кэша](/faq/service-assurance/cache-billing.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.