Перейти к документации
API

Ошибки

Одна структура, два уровня и идентификатор запроса на всём.

Конверт

type — замороженное множество, по которому можно ветвиться и которое никогда не будет расширяться. code конкретен и пополняется, поэтому незнакомый код трактуйте как его type. requestId есть в каждом ответе, включая успешные, и именно он связывает обращение с записью в журнале.

422 Unprocessable Entity
{  "error": {    "type": "validation_error",    "code": "invalid_email_address",    "message": "Not a valid email address: ada@",    "param": "to.0",    "docUrl": "https://openemail.uk/docs/api/errors#invalid_email_address",    "requestId": "req_e103790543af4…"  }}

param записан через точки и с индексами, поэтому указывает на конкретный элемент (to.0, attachments.2.filename), а не на поле, которое его содержит.

Коды статусов

СтатусtypeЧастые коды
400invalid_request_errormalformed_json, invalid_idempotency_key
401authentication_errormissing_api_key, invalid_api_key, revoked_api_key, invalid_credential_type
403permission_errorinsufficient_scope, from_address_forbidden
404not_found_errorresource_not_found
409conflict_erroremail_not_cancellable, translation_not_configured
422validation_errorinvalid_email_address, reserved_header, too_many_recipients, unknown_parameter, idempotency_key_reuse, label_not_directly_settable, unknown_language, translation_too_long
429rate_limit_errorsend_quota_exceeded, too_many_inboxes
500api_errorinternal_error
503api_errortranslation_failed

404 никогда не различает «не существует» и «принадлежит другому рабочему пространству». Это сделано намеренно: сама разница является информацией.

429 никогда не несёт Retry-After, поэтому выбирайте паузу сами. send_quota_exceeded — это месячный лимит отправки, и он сбрасывается первого числа месяца, поэтому покажите его человеку, а не уходите в отступление. too_many_inboxes — потолок на создание одноразовых ящиков, и продление уже имеющегося у вас ящика ничего из него не расходует.

500 и 503 имеют общий type, но означают для вызывающей стороны разное. 503 — это не ответившая зависимость (сегодня это переводчик), и запрос стоит повторить без изменений; 500 — наша ошибка, и о ней стоит сообщить вместе с её requestId.

Обработка ошибок

Ветвитесь по type ради поведения и читайте code ради сообщения, которое вы показываете человеку. Нераспознанный code — не ошибка в вашем клиенте. Он означает, что мы назвали сбой точнее, чем раньше.

TypeScript
const res = await fetch(`${BASE}/emails`, { method: 'POST', headers, body }); if (!res.ok) {  const { error } = await res.json();   switch (error.type) {    case 'rate_limit_error':      throw new RateLimited(error.code);    case 'validation_error':      // error.param points at the offending field      throw new BadRequest(`${error.param}: ${error.message}`);    case 'authentication_error':      // revoked_api_key and expired_api_key are worth telling an operator apart      throw new AuthFailed(error.code);    default:      // quote requestId when you report it      throw new Unexpected(error.message, error.requestId);  }}