# Ошибки

> Как выглядит ошибка, что значит каждый код и когда повторять запрос.

> Оглавление документации для агентов: https://kinodata.space/ru/llms.txt — вся документация одним файлом: https://kinodata.space/ru/llms-full.txt

Если запрос не прошёл, API отвечает статусом 4xx или 5xx и объектом `error`. Код говорит, что случилось, а поля рядом — какой параметр виноват и какие значения допустимы. Например, в типе каталога опечатка — `tmbd` вместо `tmdb`:

```bash
curl -H "X-API-Key: $KINODATA_KEY" \
  "https://api.kinodata.space/v1.3/ids/tmbd/27205"
```

Ответ `400`:

```json
{
  "error": {
    "code": "invalid_request",
    "message": "unknown type \"tmbd\"",
    "field": "type",
    "allowed": [
      "imdb",
      "kp",
      "tmdb",
      "tmdb_tv",
      "kinorium"
    ],
    "hint": "did you mean \"tmdb\"?"
  }
}
```

## Поля ошибки

| поле | есть всегда | что это |
|---|---|---|
| `code` | да | Машинный код. По нему и ветвитесь. |
| `message` | да | Объяснение для человека, по-английски. Текст может уточняться, не разбирайте его в коде. |
| `field` | нет | Параметр, из-за которого запрос отклонён. |
| `allowed` | нет | Допустимые значения этого параметра. |
| `hint` | нет | Подсказка, если значение похоже на допустимое (`tmbd` → `tmdb`) или входит в него целиком (`sort=kp` → `rating_kp` или `votes_kp`). |

Ветвитесь по `code`, а не по статусу: один статус бывает у разных причин.

## Коды

### invalid_request

- **Статус:** 400.
- **Когда:** неизвестный параметр или значение, ID не в формате каталога, повторённый параметр, `limit` не целое число от 1.
- **Что делать:** прочитайте `field`, `allowed` и `hint` и исправьте запрос.

### unauthorized

- **Статус:** 401.
- **Когда:** нет заголовка `X-API-Key`, ключ неизвестен или отозван.
- **Что делать:** проверьте, что заголовок называется `X-API-Key` и ключ скопирован целиком.

### forbidden

- **Статус:** 403.
- **Когда:** запросы с вашего адреса закрыты: с него перебирали ключи или иначе нарушали правила. `message` — `this address is blocked`. Бан за подбор ключей снимается сам через сутки.
- **Что делать:** если адрес закрыт по ошибке — например, он общий у офиса или оператора, — [напишите нам](https://kinodata.space/ru/contacts).

### not_found

- **Статус:** 404.
- **Когда:** тайтла или человека с таким ID нет, подборки с таким `slug` нет, такого адреса нет.
- **Что делать:** проверьте тип и ID. `tmdb` и `tmdb_tv` легко перепутать: это разные ID.

### rate_limited

- **Статус:** 429.
- **Когда:** исчерпан предел в секунду или квота на сутки. `message` уточняет, какой: `rate limit exceeded` — секунда, `quota limit exceeded` — сутки.
- **Что делать:** подождите столько секунд, сколько указано в заголовке `Retry-After`. Квота на сутки обновляется в полночь по UTC.
- **Как не упереться:** остаток виден в каждом ответе. `X-RateLimit-Remaining` — сколько запросов осталось в текущей секунде, `X-Quota-Remaining` — на сутки, `X-Quota-Reset` — когда квота обновится (Unix-время). У ключа без предела этих заголовков нет.

### internal

- **Статус:** 500.
- **Когда:** сбой на нашей стороне.
- **Что делать:** повторите запрос с паузой. Если ошибка повторяется, напишите нам и приложите `X-Request-Id`.

### source_unavailable

- **Статус:** 502.
- **Когда:** каталог, из которого мы дополняли данные, не ответил.
- **Что делать:** повторите запрос позже.

## Повторять ли запрос

| код | повторять |
|---|---|
| `rate_limited` | да, через `Retry-After` секунд |
| `internal`, `source_unavailable` | да, с растущей паузой: 1, 2, 4 секунды |
| остальные | нет: запрос не станет верным сам |

Все запросы API — `GET`, поэтому повтор ничего не меняет и безопасен.

## Если не получается

С каждым ответом приходит заголовок `X-Request-Id`. Приложите его к обращению — по нему мы найдём ваш запрос.

## Дальше

- [Ключ и лимиты](https://kinodata.space/ru/docs/keys.md) — как не упираться в `429`.
- [Списки и пагинация](https://kinodata.space/ru/docs/lists.md) — правила `limit`, `offset` и `cursor`.
