Документация LMS версия 2026.09.180

Документация/API/Ошибки

Раздел описывает первый рабочий срез API. Срез в разработке: маршрутов ещё нет, экран ключей появится вместе с ним — до выкатки проверить запросы не обо что.

Ошибки

Модель, не знающая формы ошибки, не умеет её обработать — и человек тоже. Поэтому ошибки описаны наравне с успехом, а не в примечании.

Эта страница — одна из трёх в разделе, которые описаны по-настоящему и не изменятся: форма ошибки задана целиком, и реализация её не поменяет.

Код отвечает за результат, тело — за детали #

Никаких 200 OK с {"success": false} внутри. Если запрос не выполнен, это видно по коду HTTP, а не по разбору тела.

{
  "error": {
    "type": "validation_error",
    "code": "invalid_field",
    "message": "Поле email имеет неверный формат",
    "field": "email",
    "doc_url": "https://docs-school.sersidteh.ru/api/errors/",
    "request_id": "req_01HQZXA7M3PK9E"
  }
}
Поле Что это
type Класс ошибки. По нему ветвится обработчик
code Конкретная ошибка внутри класса
message Текст на языке школы. Для человека, а не для условия в коде
field Поле, вызвавшее ошибку валидации
doc_url Ссылка на объяснение
request_id Идентификатор запроса. Он же в заголовке X-Request-Id

Ветвиться в коде надо по type и code, а не по message: текст сообщения переводится и уточняется, коды — нет.

Полный список кодов #

Код Когда Что делать
400 bad_request Синтаксис запроса неверен Чинить запрос. Повтор без правки бессмыслен
401 unauthorized Токен отсутствует, недействителен или отозван Проверить заголовок и не отозван ли ключ. Повтор бессмыслен
403 forbidden Токену не хватает права В ответе сказано, какого именно. Выдать право или использовать другой ключ
404 not_found Объекта нет или он вне видимости токена Различить это снаружи нельзя намеренно: иначе перебором можно узнать, какие объекты существуют
409 conflict Конфликт состояния: заказ уже оплачен, доступ уже выдан Прочитать текущее состояние объекта и решить. Повтор даст тот же ответ
422 unprocessable Синтаксис верен, бизнес-правило нарушено Читать code: причина в нём
429 rate_limited Превышен лимит Ждать столько, сколько сказано в Retry-After, и повторить
500 internal_error Наша ошибка Повторить позже. request_id обязателен в ответе — с ним и приходить
503 unavailable Плановые работы или перегрузка Повторить позже, уважая Retry-After, если он есть

Разница между 400 и 422 стоит того, чтобы её знать. 400 — запрос не разобрался: не тот тип, сломанный JSON, отсутствует обязательное поле. 422 — разобрался и не прошёл по правилу: заказ уже отменён, доступ уже отозван, сумма возврата больше платежа. Первое чинится в коде клиента, второе — решением, что делать дальше.

Ошибок может быть несколько #

Возвращать по одной ошибке валидации и заставлять клиента исправлять их по очереди — плохой тон: за пять полей клиент сделает пять запросов и получит пять отказов.

Поэтому у ошибок валидации в теле массив:

{
  "errors": [
    {
      "type": "validation_error",
      "code": "invalid_field",
      "message": "Поле email имеет неверный формат",
      "field": "email",
      "request_id": "req_01HQZXA7M3PK9E"
    },
    {
      "type": "validation_error",
      "code": "required",
      "message": "Поле first_name обязательно",
      "field": "first_name",
      "request_id": "req_01HQZXA7M3PK9E"
    }
  ]
}

request_id одинаковый: это один запрос с двумя претензиями к нему.

Идентификатор запроса #

request_id есть в каждом ответе, включая успешные, в заголовке X-Request-Id. По нему в журнале находится полная трассировка запроса.

Практически: логируйте его на своей стороне рядом с каждым вызовом. Именно это превращает разбор случая «в четверг у клиента не выдался доступ» из гадания в работу — без него остаётся сравнивать время и надеяться.

Что вернётся в четырёх частых случаях #

Прав не хватило. 403, и в ответе сказано, какого права не хватило. Не «доступ запрещён» вообще, а конкретика: иначе интегратор перебирает права наугад.

Объект удалён. 404. Мягко удалённый объект от несуществующего снаружи неотличим — и это намеренно.

Превышен лимит. 429 и заголовок Retry-After в секундах. Клиент обязан его уважать; в наших клиентских библиотеках это встроено. Игнорирование Retry-After и повтор в цикле — самый быстрый способ получить более жёсткий лимит.

Тело не прошло проверку. 400 или 422 — см. разницу выше, — и, если ошибок несколько, все сразу.

Обработчик на клиенте #

Минимум, который стоит написать один раз:

# Повторять можно: 429, 500, 503 — с задержкой из Retry-After или с ростом.
# Повторять бессмысленно: 400, 401, 403, 404, 409, 422 — ответ не изменится.

Разделение простое: повторять имеет смысл там, где виноваты нагрузка или мы. Там, где виноват запрос, повтор даст тот же ответ и потратит лимит.

Эта страница в Markdown