# Errors

Формат ошибок и список кодов

Все ошибки API возвращаются в едином формате с HTTP-статусом ≥ 400:

```json
{
  "error": {
    "code": "INSUFFICIENT_BALANCE",
    "message": "Недостаточно средств на балансе",
    "requestId": "req_01HX5Y3KJ8...",
    "timestamp": "2026-04-30T12:00:42.123Z"
  }
}
```

`requestId` — идентификатор запроса для саппорта. Сохраняйте его в логах: с ним мы быстрее найдём проблему.

## HTTP-статусы

| Код | Что означает |
|---|---|
| `400 Bad Request` | Неверные параметры запроса (см. `code`) |
| `401 Unauthorized` | Отсутствует или невалиден API-ключ |
| `403 Forbidden` | Ключ есть, но нет прав на ресурс |
| `404 Not Found` | Ресурс не существует или принадлежит другому пользователю |
| `409 Conflict` | Конфликт состояния (например, уже выполняется идемпотентный запрос) |
| `422 Unprocessable Entity` | Параметры провалили валидацию модели |
| `429 Too Many Requests` | Превышен лимит — см. [Rate limits](/docs/rate-limits) |
| `500 Internal Server Error` | Внутренняя ошибка |
| `502 Bad Gateway` | Провайдер модели недоступен |
| `503 Service Unavailable` | Сервис временно недоступен или в maintenance |

## Коды ошибок (`error.code`)

### Аутентификация и авторизация
- `UNAUTHORIZED` — нет/невалиден ключ.
- `API_KEY_REVOKED` — ключ отозван.
- `FORBIDDEN` — нет прав.

### Валидация
- `VALIDATION_ERROR` — параметры не прошли схему (детали в `error.details`).
- `MODEL_NOT_FOUND` — `modelSlug` не существует или модель деактивирована.
- `INVALID_INPUT` — параметр в недопустимом диапазоне для этой модели.

### Биллинг
- `INSUFFICIENT_BALANCE` — баланс ниже стоимости запроса.
- `BILLING_LOCKED` — аккаунт заблокирован (свяжитесь с саппортом).

### Лимиты
- `RATE_LIMITED` — превышен RPS-лимит. См. заголовок `Retry-After`.
- `CONCURRENT_LIMIT` — превышено число одновременных генераций (по умолчанию 5).

### Провайдер
- `PROVIDER_ERROR` — общая ошибка провайдера.
- `PROVIDER_TIMEOUT` — провайдер не ответил за лимит времени.
- `CONTENT_POLICY` — промпт нарушает политику модели (NSFW, насилие и т.п.).

### Идемпотентность
- `IDEMPOTENCY_CONFLICT` — тот же `idempotencyKey` использован с другим телом запроса.

## Ретраи и автоматический refund

Если задача провалилась с **финальной** ошибкой провайдера (3 попытки worker исчерпаны), деньги автоматически возвращаются на баланс. Возврат отражается в `BalanceLedger` с типом `REFUND`. Идемпотентность гарантирует, что одна задача = одно списание + одно возможное возмещение.

## Что делать с ошибкой

1. Логируйте `requestId` и `code`.
2. Для `RATE_LIMITED` и `PROVIDER_TIMEOUT` — повторите запрос с экспоненциальной задержкой.
3. Для `CONTENT_POLICY`, `INVALID_INPUT`, `VALIDATION_ERROR` — исправьте параметры.
4. Для `INSUFFICIENT_BALANCE` — пополните баланс.
5. Если непонятно — напишите в саппорт с `requestId`.
