Как устроены ответы LinkHarbor API с ошибками, что означают самые важные коды ошибок и как ваш код должен на них реагировать.
Каждый ответ API с ошибкой имеет один и тот же формат. Ваш код должен опираться на код ошибки в поле error, а не на текст в message: код стабилен, а текст может меняться и переводится на язык аккаунта.
Структура ответа с ошибкой
{
"error": "validation_failed",
"message": "Some of the information provided is invalid. Please check and try again.",
"details": [
{ "field": "title", "reason": "minLength", "message": "…" }
],
"request_id": "6b1f0c2e-…"
} - error
- Машиночитаемый код, например not_found. Для большинства ошибок он также передаётся в заголовке X-Error-Code — но опирайтесь на поле в теле.
- message
- Описание для человека на языке аккаунта: с API-ключом – владельца рабочего пространства, с подключённым приложением – того, кто его подключил. Без действительного токена – например, при 401 из проверки токена – язык следует Accept-Language, иначе текст на английском. Заголовок Content-Language называет язык.
- details
- Есть, только когда нужно сообщить что-то ещё. Для 422 из проверки входных данных это список с field, reason и message для каждой проблемы; для 422 из бизнес-логики и всех остальных ошибок — объект, например с reason, retry_after_sec или списком issues. При превышении размера в нём есть field, reason и limit, а для 413 request_too_large — max_bytes и max_kb. Поэтому проверяйте, является ли details списком.
- request_id
- ID запроса. Он также передаётся в заголовке X-Request-Id. Указывайте его, когда обращаетесь в поддержку.
Исключения: в ответе 429 rate_limited вместо details есть поле retry_after_sec; при 429 и 403 insufficient_scope в теле нет request_id. У 401 из проверки токена и 422 из проверки схемы нет заголовка X-Error-Code; при проверке схемы переводится только message верхнего уровня, тексты внутри details остаются на английском. Заголовок X-Request-Id есть всегда.
Самые важные коды
| HTTP | error | Значение | Что делать |
|---|---|---|---|
| 400 | invalid_json | Тело — некорректный JSON | Проверьте JSON |
| 400 | bad_request | Неверный Content-Type или некорректный запрос | Укажите Content-Type: application/json |
| 401 | missing_bearer_token | Нет токена в заголовке Authorization | Укажите заголовок Authorization: Bearer … |
| 401 | invalid_token | Токен истёк или недействителен, или ключ удалён | Получите новый токен; если не помогает, проверьте ключ |
| 401 | invalid_api_key | Неверный ID ключа или секрет при обмене токена | Проверьте учётные данные |
| 402 | plan_limit_reached | Достигнут лимит тарифа, например для коротких ссылок | Повысьте тариф или удалите записи |
| 403 | insufficient_scope | Нет области доступа или эндпоинт не открыт для API-ключей | Создайте ключ с нужной областью доступа |
| 403 | forbidden | Нет прав на это действие | Выполните его в панели управления |
| 403 | feature_not_available | Функция не входит в тариф | Проверьте тариф |
| 403 | block_type_requires_plan | Тип блока доступен только на более высоком тарифе | Выберите другой тип блока или повысьте тариф |
| 403 | template_locked | Премиум-шаблон недоступен на текущем тарифе | Выберите шаблон из GET /v1/templates/available |
| 403 | workspace_suspended, workspace_read_only, workspace_grace_expired | Рабочее пространство заблокировано или доступно только для чтения из-за неоплаченного счёта | Урегулируйте оплату в панели управления |
| 404 | not_found | Ресурс не существует или не принадлежит вашему рабочему пространству | Проверьте ID |
| 409 | conflict | Общий конфликт с текущим состоянием | Загрузите состояние заново, измените входные данные |
| 409 | workspace_template_in_use | Шаблон рабочего пространства ещё используется страницами; их число указано в details.count | Переведите страницы на другой шаблон, затем удалите его |
| 409 | handle_taken, slug_taken | Хэндл или слаг короткой ссылки уже занят | Выберите другое значение |
| 409 | form_in_use, page_not_private, page_not_published, never_published | Конфликт с состоянием: форма ещё размещена на странице, страница не приватная или не опубликована, ни разу не публиковалась | Измените состояние и повторите попытку |
| 409 | page_limit_reached, link_limit_reached, block_limit_reached, form_limit_reached, asset_limit_reached, asset_storage_limit_reached, workspace_template_limit_reached | Достигнут лимит тарифа по количеству или объёму хранилища | Удалите записи или повысьте тариф |
| 409 | draft_not_publishable | В черновике есть проблемы; список — в details.issues | Исправьте проблемы и опубликуйте снова |
| 413 | request_too_large | Тело больше допустимого для этого эндпоинта (64 КБ, 1 МБ или 2 МБ); лимит указан в details.max_kb | Отправляйте меньше данных за запрос, см. Лимиты запросов |
| 413 | payload_too_large | Загружаемый файл больше 10 МБ | Уменьшите файл |
| 422 | validation_failed | Недопустимые входные данные или неизвестное поле; подробности в details | Исправьте поля, как описано в details |
| 422 | handle_reserved, target_url_invalid, target_url_scheme, target_url_host | Хэндл зарезервирован, или целевой URL недопустим или не разрешён | Выберите другое значение |
| 422 | workspace_template_disabled | Выбранный шаблон рабочего пространства отключён | Включите шаблон в разделе «Домены и шаблоны» или выберите другой |
| 422 | template_css_external, template_section_invalid | Шаблон рабочего пространства: CSS загружает что-то с внешних серверов, или секция {{#if}}/{{#unless}}/{{#each}} расположена неправильно | Удалите внешние адреса или закройте секцию внутри того же тега или текста |
| 422 | custom_css_external | Собственный CSS загружает что-то с внешних серверов | Удалите внешние адреса из CSS |
| 429 | rate_limited, api_key_locked | Слишком много запросов, или ключ заблокирован после неудачных попыток | Подождите столько, сколько указано в Retry-After или details.retry_after_sec |
| 500 | internal_error | Непредвиденная ошибка | Повторите позже, сохраните request_id |
| 503 | service_unavailable | Сервис временно недоступен | Повторите после паузы |
Как читать ошибки во входных данных
При 422 validation_failed details перечисляет каждую проблему отдельно: field — путь к полю (со слешами для вложенных объектов, например theme_config/button_style), reason — нарушенное правило, например required, minLength, maxLength, enum или additionalProperties. При additionalProperties в message сказано, какие поля неизвестны, — часто это опечатка в имени поля.
Рекомендуемая обработка в коде
- 400, 413 и 422: не повторяйте, а исправьте запрос
- 401 invalid_token: один раз получите новый токен и повторите
- 403: не повторяйте; проверьте область доступа, тариф или то, кому разрешено это действие
- 404: проверьте ID; после удаления это нормально
- 409: загрузите состояние заново и решите, нужно ли ещё это действие
- 429: подождите столько, сколько указано в Retry-After, затем повторите — см. Лимиты запросов
- 500 и 503: повторите несколько раз с растущими паузами
Вам также может пригодиться
Ничего не нашли?
Напишите, что вам нужно, и наша служба поддержки поможет вам лично.