# Ошибки API: коды и обработка

> OpenAI-формат ошибок, честная таблица кодов по факту бэкенда, rate limit c Retry-After и x-ratelimit-заголовками, правила ретраев.

Веб-версия: https://ai.trackly.one/developers/docs/errors · Индекс документации: https://ai.trackly.one/llms.txt

Все dev-эндпоинты отдают ошибки в OpenAI-формате: JSON
`{"error": {"message", "type", "code", "param"}}` плюс честный HTTP-статус.
Ретраить имеет смысл 429 (после паузы из `Retry-After`), 502 и 504.
Остальные коды — проблема самого запроса, повтор без изменений не поможет.
При любой ошибке деньги с баланса не списываются.

## Как выглядит ошибка?

```json
{
  "error": {
    "message": "Model 'openai/gpt-99' does not exist or is not available",
    "type": "invalid_request_error",
    "code": "model_not_found",
    "param": "model"
  }
}
```

- `message` — что случилось, человеческим языком;
- `type` — класс ошибки (`invalid_request_error`, `rate_limit_error`,
  `insufficient_quota`, `upstream_error`, `upstream_timeout`);
- `code` — машиночитаемый код для ветвления в вашем коде;
- `param` — какое поле запроса виновато (когда применимо, иначе `null`).

OpenAI SDK превращает эти ответы в свои исключения
(`openai.NotFoundError`, `openai.RateLimitError` и т.д.) — готовый код
обработки ошибок OpenAI работает без переделки.

Ошибки валидации тела (битый JSON, не тот тип поля) на dev-ручках тоже
приходят в этом формате — 400 `invalid_request_error` с `param`, а не
«голый» 422 FastAPI.

## Какие коды бывают?

Таблица по факту бэкенда — ровно те коды, которые API реально возвращает:

| HTTP | `code` | `type` | Когда |
| --- | --- | --- | --- |
| 400 | `null` | `invalid_request_error` | Ошибки валидации тела запроса: битый JSON, неверный тип поля |
| 400 | `invalid_request_error` | `invalid_request_error` | Невалидная комбинация параметров: `max_tokens` и `max_completion_tokens` одновременно с разными значениями, отсутствие обязательных файлов |
| 400 | `unsupported_capability` | `invalid_request_error` | Модель не умеет запрошенное: картинка в text-only модель, текстовая модель в images-эндпоинте |
| 401 | `invalid_api_key` | `invalid_request_error` | Ключ не передан, неверный или отозван |
| 402 | `insufficient_quota` | `insufficient_quota` | Не хватает баланса — проверка происходит до запуска генерации |
| 404 | `model_not_found` | `invalid_request_error` | Модели с таким id нет (`param` = `model`) |
| 404 | `not_found` | `invalid_request_error` | Ресурс не существует или принадлежит другому аккаунту (например, видео-задача) |
| 409 | `video_not_ready` | `invalid_request_error` | Запрос `/content` до завершения генерации видео |
| 429 | `rate_limit_exceeded` | `rate_limit_error` | Превышен лимит запросов, см. `Retry-After` |
| 502 | `upstream_error` | `upstream_error` | Провайдер модели ответил ошибкой |
| 504 | `upstream_timeout` | `upstream_timeout` | Провайдер модели не ответил вовремя |

Заголовка `Idempotency-Key` и кода `duplicate_request` в dev-API нет —
дедупликацию повторных отправок делайте на своей стороне.

## Как работает rate limit?

Лимит — 60 запросов в минуту, общий bucket на аккаунт для всех модальностей
(текст, картинки, видео, озвучка). Каждый ответ несёт заголовки:

```text
x-ratelimit-limit-requests: 60
x-ratelimit-remaining-requests: 42
x-ratelimit-reset-requests: 1752345660
```

`reset` — unix-время начала следующего минутного окна. Классические
`X-RateLimit-*` заголовки тоже присылаются — для старых клиентов. При
превышении приходит 429 с заголовком `Retry-After` (секунды до
следующей попытки).

## Что ретраить, а что нет?

- **429** — подождать `Retry-After` секунд и повторить.
- **502, 504** — повторить с экспоненциальной паузой; списания не было,
  повтор безопасен.
- **4xx кроме 429** — не ретраить: запрос не изменится сам. 401 — проверить
  [ключ](https://ai.trackly.one/developers/docs/authentication), 402 — пополнить баланс в
  [кабинете](https://ai.trackly.one/account/billing), 404 `model_not_found` — свериться со
  списком в [/v1/models](https://ai.trackly.one/developers/docs/models).
- **409 `video_not_ready`** — не ошибка ретрая, а сигнал «опрашивай статус
  дальше», см. [гайд по видео](https://ai.trackly.one/developers/docs/video).

OpenAI SDK ретраит 429 и 5xx сам (по умолчанию два повтора) — чаще всего
достаточно его штатного поведения.

## Списываются ли деньги при ошибке?

Нет. Списание происходит только после успешного ответа — по фактическому
usage или тарифу модели. Ошибка провайдера (502/504), нехватка баланса,
неверные параметры — транзакции не будет. У видео своя точка списания:
момент перехода задачи в `completed`, упавшая генерация бесплатна. Тарифы
моделей — на странице [цен для разработчиков](https://ai.trackly.one/developers/pricing).
