29 апреля 2025
Автор: Екатерина Ананьева
REST API
Интеграции
Проектирование API – это не только про описание успешных запросов и ответов, но и продуманная обработка ошибок.
Зачастую ошибки начинают всерьез обсуждать лишь после того, как тестировщик пишет в чат «ничего не работает» или «а это нормальное поведение?». Однако прорабатывать возможные ошибки и формат ответов на них нужно заранее, на этапе системного анализа и разработки контрактов REST API методов. Да и в целом, не только REST, а любого API.
В этой статье мы обсудим, почему это так важно, как должна выглядеть стандартная структура ошибки, разберём разницу между HTTP-кодами и внутренними кодами ошибок, а также распространенные ошибки (400, 401, 403, 404, 409, 500) с пояснениями и примерами.
Оглавление:
Важность продуманного описания ошибок на этапе анализа
HTTP-коды ошибок
Структура JSON-сообщений об ошибках в REST API
HTTP-коды и внутренние коды ошибок: зачем нужны оба и в чём разница
Стандарт «Problem Details» (RFC 7807/9457)
Примеры документирования ошибок в API на реальных проектах
Заключение
Проектирование обработки ошибок в API с самого начала – залог единообразия и предсказуемости поведения API.
Если отложить эту задачу «на потом», велика вероятность получить разношерстные, неинформативные сообщения об ошибках, которые запутывают разработчиков и пользователей. Непродуманные ошибки могут приводить к длительному поиску причин сбоев, ухудшению опыта пользователей, потере времени и денег.
Системный аналитик, описывая требования к API, должен включить типы возможных ошибок и требования к их обработке со стороны API.
Предусмотрев требования к структуре сообщений об ошибках заранее, все ответы API в случае сбоев будут иметь единообразную, логичную структуру.
Разработчики клиентских приложений, которые будут использовать ваш API, с первого взгляда поймут, что произошло, а тестировщики – получат достаточно информации для анализа. Это снижает нагрузку на команду: вместо размытых сообщений «Error: Something went wrong» API вернет чётко структурированное описание проблемы.
Кроме того, хорошо задокументированные ошибки – часть контракта API.
В постановке задачи на Backend-разработчика и в документации необходимо зафиксировать:
Такой системный подход предотвращает ситуацию, когда ошибки выявляются и уточняются стихийно на этапе тестирования.
Наконец, продуманная схема ошибок помогает выстроить эффективный процесс отладки и поддержки. Если в ответе API возвращается, например, идентификатор ошибки или traceId
, то при возникновении проблемы можно быстро сопоставить её с логами на сервере. Планируя это на этапе анализа, вы закладываете возможности для быстрого отслеживания и мониторинга сбоев.
HTTP-код ответа на запрос – часть протокола HTTP.
Он возвращается «снаружи» тела ответа (строка статуса). Список HTTP-кодов стандартизирован (RFC 9110):
Использование правильных кодов – основа REST API.
Клиентские библиотеки и разработчики ориентируются на них автоматически. Например, 404 – значит ресурс отсутствует, можно не повторять запрос без изменений; 401 – нужно заново аутентифицироваться.
Скриншот из Postman - ошибка вызова API-метода
Список всех возможных HTTP статус-кодов и их расшифровку на русском языке можно найти в статье Wikipedia.
Основные коды, которые должны знать системные аналитики и разработчики, и почти всегда обрабатывать в API:
Неправильный выбор кода вводит в заблуждение.
Например, возвращать 200 OK при ошибке – грубая ошибка.
Системный аналитик в спецификации должен задать, какой код возвращается при каждом типе ошибки. Это не значит, что нужно перечислять все 60 возможных кодов; достаточно определить применимые вашему случаю, но сделать это явно и однозначно.
В ответ на запрос с ошибкой HTTP 4XX/5XX рекомендуется добавлять JSON-тело ответа.
Пример 1. Ошибка “не найдено” (HTTP 404) - запрошенный ресурс отсутствует.
Допустим, клиент запрашивает пользователя по ID, которого нет в системе.
API возвращает HTTP-код 404 Not Found.
Тело ответа (body/JSON) может выглядеть так:
Status Code: HTTP-404
Response Body:
{
"errorCode": "1001_USER_NOT_FOUND",
"message": "Пользователь с ID 12345 не найден.",
"traceId": "af34c1de-7b29-4d6e-809f-5f7d9eaeae11"
}
Здесь "errorCode"
– внутренний код ошибки, "message"
– описание, и traceId
поможет отследить запрос на сервере.
Клиент, получив такой ответ, поймет, что означают код 404 и контекст USER_NOT_FOUND
(если это описано в документации).
Пример 2. Ошибка валидации запроса (HTTP 400) – клиент отправил некорректные данные.
Допустим, при регистрации не прошла валидация поля email и возраста.
API возвращает 400 Bad Request.
Пример тела ответа:
Status Code: HTTP-400
Response Body:
{
"error": "2020_VALIDATION_ERROR",
"message": "Данные не прошли валидацию.",
"details": {
"email": "Некорректный формат email.",
"age": "Возраст должен быть положительным числом."
},
"traceId": "c82f3d9b-12f0-487b-9eae-1d234e9f9123"
}
В поле "details"
перечислены конкретные ошибки по каждому полю ввода.
Это удобно: фронтенд может подсветить пользователю, какие поля требуется исправить.
Внутренний код VALIDATION_ERROR
общий для всех ошибок валидации данного эндпоинта, а подробности уже в details
.
В документации системный аналитик должен указать, что при ошибке 400 возвращается именно такой формат, какие возможны подкоды (email_invalid
, age_negative
и т.д. – либо как здесь, тексты), чтобы у интеграторов было однозначное понимание.
Оба примера иллюстрируют единый подход:
четкая структура, понятные коды и сообщения, наличие идентификатора для отладки.
Такие ответы гораздо информативнее, чем просто {"error": "Bad Request"}
или HTML-страница ошибки по умолчанию.
Стандартная структура сообщения об ошибке делает API понятным и удобным. Хорошо продуманный ответ должен ясно объяснять проблему разработчику клиентского приложения, который использует API, и, косвенно, конечному пользователю.
Проработайте шаблоны JSON-ответов для основных категорий ошибок еще при проектировании API, и опишите их в спецификации задачи на разработчиков и в API-документации.
Итого, на основе описанных выше примеров, что можно включить в API документацию по ошибке в ответ на запрос:
Статус запроса: HTTP-код
Указывается в заголовке ответа. Он отражает общий класс ошибки (например, 400 для ошибок клиента, 500 для ошибок сервера). Правильно выставленный код сразу укажет на тип сбоя (клиентская ошибка, проблема с авторизацией, внутренняя ошибка сервера и т.д.).
Список всех возможных кодов и их расшифровку на русском языке можно найти в статье Wikipedia.
Внутренний код ошибки
Машиночитаемый код, специфичный для вашего приложения или домена. Он передается в теле ответа, например в поле "error"
или "code"
.
Внутренний код служит для детальной идентификации проблемы, отличая, скажем, ошибку валидации email от ошибки формата даты, даже если для обеих используется HTTP 400.
Это может быть строковый идентификатор ("USER_NOT_FOUND"
, "VALIDATION_ERROR"
) или числовой код. Главное, чтобы он был устойчивым и уникальным для каждого вида ошибки.
Такой код API предназначен для программистов – по нему можно программно обрабатывать разные случаи и искать описание в документации.
Сообщение об ошибке
Человекочитаемое описание, объясняющее суть проблемы. Оно должно быть кратким, но информативным, чтобы разработчик/пользователь понимал, что пошло не так.
Сообщения должны быть понятными и по возможности указывать, как исправить ошибку.
Например:"message": "Пользователь с ID '12345' не найден."
"message": "Не задан обязательный параметр email."
Недопустимо выводить внутренняя информация (стектрейсы, SQL-запросы и пр.) – это путает пользователей и может раскрывать уязвимости.
Детали ошибки
Дополнительный контекст, обычно в виде объекта или списка. Здесь можно передать специфическую информацию: какие поля не прошли валидацию и почему, какие допустимые значения ожидаются, и прочее.
Например, для ошибки валидации запрос может вернуть объект "details"
с перечислением проблем по каждому полю. Это помогает программе-клиенту API точнее обработать ошибку или отобразить пользователю конкретные подсказки. Необязательно использовать именно ключ "details"
– в разных API встречаются поля "errors"
, "fields"
, но принцип один: структурированные подробности ошибки.
Идентификатор ошибки или traceId
Уникальный идентификатор, привязанный к данному инциденту (конкретному запросу или ошибке). Он служит для отладки: по traceId
разработчики бэкенда могут найти подробный лог на сервере.
Клиенту этот идентификатор прямо не помогает решить проблему, но очень полезен для сопровождения – например, пользователь может сообщить support’у: “я получил ошибку №1234-5678”, и по ней легко отыскать событие в логах.
Часто используется GUID или UUID. Иногда также добавляют метку времени (timestamp
) возникновения ошибки.
Прочие поля контекста
В зависимости от требований, можно включить и другую информацию. Например, URI запроса ("path"
), метод, идентификатор пользователя, ссылку на документацию по данной ошибке или даже рекомендацию, что делать.
В продуманных API встречается поле "suggestion"
или "hint"
, где сообщается, как исправить ошибку.
Подобные поля не обязательны, но могут улучшить UX интеграторам (будущим пользователям) вашего API.
Важно, чтобы выбранная вами структура ошибок была единой для всех эндпоинтов API.
Все разработчики в команде Backend (API) должны знать формат и придерживаться его.
Например, если вы решили, что в ответах на ошибки всегда присутствуют поля "code"
(внутренний код) и "message"
, то это правило фиксируется в спецификации (гайд по дизайну REST API) и соблюдается во всех сервисах.
Единообразие облегчает жизнь и клиентским разработчикам, и тестировщикам: получив ошибку, они сразу находят нужные поля и могут их обработать.
Обратите внимание, что HTTP-код статуса и внутренний код ошибки дополняют друг друга, выполняя разные задачи.
Как уже частично говорилось, HTTP-статус и внутренний код ошибки – это два уровня идентификации проблемы, и оба должны быть определены в системе требований.
HTTP-код (например, HTTP-404 или HTTP-500) указывает тип проблемы на уровне протокола HTTP, а внутренний код подробно идентифицирует проблему на уровне бизнес-логики приложения.
Клиент видит HTTP 404 и понимает общую ситуацию («ресурс не найден»), а из тела ответа считывает внутренний код, уточняющий, что именно не найдено – пользователь, файл, заказ и т.д.
Внутренний код ошибки – определяется вами для классификации ошибок внутри вашего API. Почему недостаточно одного HTTP-кода? Потому что одного статуса 400 может быть мало, чтобы понять, что именно не так в запросе. Внутренние коды помогают детализировать: клиент получит, к примеру, 400 Bad Request с кодом "INVALID_EMAIL"
или "MISSING_REQUIRED_FIELD"
. Оба – ошибки HTTP-400, но причины разные и реагировать на них можно по-разному.
Кроме того, внутренние коды позволяют локализовать сообщения (UI может по коду подтянуть сообщение на нужном языке) или сгруппировать ошибки по смыслу. Это машиночитаемые индикаторы проблемы, тогда как сообщение – для человека.
Чтобы продемонстрировать разницу:
HTTP-код 404 Not Found – универсально означает, что ресурса нет.
Внутренний код "USER_NOT_FOUND"
– уточняет, что отсутствует именно пользователь.
Внутренний код "ORDER_NOT_FOUND"
при том же HTTP 404 – уже другая ситуация (нет заказа).
Status Code: HTTP-404
Response Body:
{
"errorCode": "USER_NOT_FOUND",
"message": "Пользователь с ID 12345 не найден.",
"traceId": "af34c1de-7b29-4d6e-809f-5f7d9eaeae11"
}
Оба этих кода нужно предусмотреть и задокументировать: HTTP-коды для каждого типа ошибок (их набор, как правило, ограничен стандартными значениями), и внутренние коды – в виде списка всех возможных ошибок вашего API с объяснениями.
Таким образом, HTTP-код отвечает на вопрос «что произошло в общем», а внутренний – «что произошло конкретно». Оба необходимо прорабатывать заранее: набор используемых HTTP-кодов – согласно REST-стандартам, и список внутренних кодов – индивидуально для вашего API. И оба фиксировать в документации для прозрачности.
Документация API должна содержать справочник кодов HTTP + внутренних кодов ошибок, чтобы разработчики знали, какие ошибки могут возвращаться и что они значат.
Системный аналитик должен создать и поддерживать этот справочник.
Стоит упомянуть, что в сообществе существует рекомендуемый стандарт для структуры ошибок – RFC 7807 “Problem Details for HTTP APIs”, обновленный в 2023 году как RFC 9457.
Он предлагает единый формат JSON для сообщений об ошибках (MIME-тип application/problem+json
).
Согласно RFC, ответ на ошибку содержит поля: type
(URI с описанием типа проблемы), title
(краткое описание ошибки), status
(HTTP-код), detail
(подробности для человека) и instance
(URI конкретного экземпляра ошибки). Также допускаются дополнительные поля.
Вот пример структуры по RFC 7807:
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
{
"type": "https://example.com/probs/out-of-credit",
"title": "You do not have enough credit.",
"detail": "Ваш баланс 30, а требуется 50 для этой операции.",
"instance": "/accounts/12345/transactions/67890",
"timestamp": "2025-04-29T23:15:32Z"
}
Заложить поддержку этого формата можно на этапе проектирования. Он хорошо документирован и поддерживается многими фреймворками. Однако, использовать именно его или ввести свою структуру – решать вам; главное, чтобы структура была последовательной и отвечала потребностям вашего API.
Несколько ссылок API-документацию, в которой четко описаны ошибки.
Сервис по работе с объявлениями о недвижимости ЦИАН:
https://public-api.cian.ru/docs/latest#tag/billing/paths/~1v1~1get-my-balance/get
Формат документации близок к OpenAPI/Swagger.
Маркетплейс (Интернет-магазин) Wieldberries
https://dev.wildberries.ru/openapi/orders-dbs#tag/Sborochnye-zadaniya-DBS/paths/~1api~1v3~1dbs~1orders/get
Обратите внимание на детализацию ошибки авторизации HTTP-401 и посмотрите, какие сообщения об ошибках возвращают для других HTTP-кодов.
Проектирование ошибок в API один из важнейших этапов процесса разработки и системный аналитик играет в этом ключевую роль.
Задача аналитика – на этапе проектирования предусмотреть возможные сбои, назначить корректные HTTP-коды для них, разработать удобную структуру ответа с необходимыми полями и добиться, чтобы всё это было отражено в спецификации и документации.
Хорошо спроектированные и задокументированные ошибки повышают качество API: улучшают опыт разработчиков, облегчают тестирование и сопровождение. Заранее проработав ошибки, вы избавите команду от множества проблем «в режиме пожара на проде» в будущем и сделаете свой API по-настоящему профессиональным и надежным.
Если вам интересна тема проектирования REST API с нуля для системных аналитиков, то более подробно мы разбираем её на программе Дизайн REST API, на примере реального проекта.
Получайте полезные материалы и учитесь новому каждый день в наших социальных сетях.
*Instagram и LinkedIn — запрещенные на территории РФ организации
Мы используем файлы cookie, для персонализации сервисов и повышения удобства пользования сайтом. Если вы не согласны на их использование, поменяйте настройки браузера.