Коды ошибок API
Единый формат ошибки API MeerPartners, HTTP-коды и таблица доменных кодов с пояснениями. Как клиенту реагировать на 401, 403, 409, 422, 429 и 5xx при интеграции.
API MeerPartners возвращает ошибки в едином формате со стабильным строковым кодом. Роутьте логику по полю code, а не по тексту сообщения: текст может меняться и локализоваться, код — нет.
Формат ошибки
{
"error": {
"code": "POSTBACK_BAD_SIGNATURE",
"message": "Подпись неверна",
"details": {}
}
}| Поле | Значение |
|---|---|
code | Стабильная константа в SCREAMING_SNAKE_CASE — по ней клиент принимает решение |
message | Человекочитаемое пояснение (может меняться) |
details | Доп. контекст: для валидации — карта полей; иногда limit, tenants и т.п. |
Главное правило
Никогда не парсите message для логики. Ветвитесь по code и HTTP-статусу. message — только для логов и показа человеку.
HTTP-коды
| HTTP | Смысл | Что делать клиенту |
|---|---|---|
400 | Некорректный запрос (синтаксис/семантика, устаревший timestamp) | Исправить запрос, не ретраить вслепую |
401 | Не аутентифицирован: нет/битый токен или подпись | Проверить ключ/подпись/токен |
403 | Нет прав: скоуп, роль, чужой tenant | Проверить скоуп ключа / роль / tenant |
404 | Ресурс не найден или невидим | Проверить идентификатор |
409 | Конфликт состояния/идемпотентности (в т.ч. replay) | Пересобрать запрос (новый timestamp/ключ идемпотентности) |
410 | Ресурс «протух» или отключён (ссылка/оффер неактивны) | Не ретраить |
422 | Ошибка валидации полей | Исправить тело по details |
429 | Превышен лимит частоты | Ретрай с backoff, смотреть Retry-After |
500 | Внутренняя ошибка | Ретрай с backoff; если повторяется — эскалация |
503 | Зависимость недоступна (fail-closed) | Ретрай позже с backoff |
Доменные коды
Аутентификация и ключи
| Код | HTTP | Когда |
|---|---|---|
TENANT_API_KEY_INVALID | 401 | Ключ неизвестен, неактивен, отозван или истёк; нет X-Api-Key-Id |
TENANT_API_KEY_SCOPE_DENIED | 403 | У ключа нет нужного скоупа (postback / sso) |
TENANT_SUSPENDED | 403 | Бизнес (tenant) неактивен |
TOKEN_EXPIRED | 401 | JWT истёк |
TOKEN_INVALID | 401 | JWT не разобрался/невалиден |
TOKEN_WRONG_TYPE | 401 | Ожидался refresh, пришёл другой тип (или наоборот) |
TOKEN_REVOKED | 401 | Refresh-токен уже использован/отозван |
ACCESS_REVOKED | 401 | Доступ отозван на стороне MeerID (бан/удаление) |
EMBED_SCOPE_DENIED | 403 | Действие требует полного токена, а пришёл embed-scoped |
Postback
| Код | HTTP | Когда |
|---|---|---|
POSTBACK_BAD_SIGNATURE | 401 | HMAC-подпись не сошлась |
POSTBACK_STALE_TIMESTAMP | 400 | X-Timestamp вне окна ±300 с |
POSTBACK_REPLAY | 409 | Повтор той же подписи в окне памяти |
POSTBACK_TENANT_MISMATCH | 403 | X-Tenant-Id не совпал с tenant ключа |
POSTBACK_MISSING_FIELD | 422 | Нет обязательного поля для event_type (или невалидное тело) |
POSTBACK_UNKNOWN_REF | 200 | Нет атрибутируемого клика — accepted:false (не ошибка) |
POSTBACK_REFUND_NO_CONVERSION | 200 | Refund на несуществующую конверсию — accepted:false |
POSTBACK_RATE_LIMITED | 429 | Слишком много postback на ключ |
Коды на 200 — не сбой
POSTBACK_UNKNOWN_REF и POSTBACK_REFUND_NO_CONVERSION приходят с HTTP 200 и accepted:false. Это штатные исходы (органика / неприменимый refund), а не ошибки связи — не ретрайте их.
Token-exchange (SSO)
| Код | HTTP | Когда |
|---|---|---|
EXCHANGE_DENIED | 401 | Невалидная подпись, нет/просрочен X-Timestamp, tenant неактивен |
EXCHANGE_REPLAY | 401 | Повтор той же подписи |
USER_BANNED | 403 | Пользователь заблокирован |
Вебхуки
| Код | HTTP | Когда |
|---|---|---|
DEPOSIT_WEBHOOK_UNCONFIGURED | 503 | Секрет вебхука депозита не задан (fail-closed) |
DEPOSIT_WEBHOOK_SIGNATURE_INVALID | 401 | Нет заголовков / неверная подпись / timestamp вне окна / replay |
DEPOSIT_WEBHOOK_REPLAY_STORE_UNAVAILABLE | 503 | Хранилище replay-защиты недоступно |
INVALID_PAYLOAD | 400 | Невалидный JSON в теле |
LOGOUT_TOKEN_INVALID | 401 | Невалидный logout_token (back-channel logout MeerID) |
WEBHOOK_TIMESTAMP_STALE | 401 | Identity-вебхук MeerID вне окна свежести |
Трекинг
| Код | HTTP | Когда |
|---|---|---|
TRACKING_LINK_NOT_FOUND | 404 | Неизвестный {code} ссылки |
LINK_INACTIVE | 410 | Ссылка отключена (без fallback) |
OFFER_INACTIVE | 410 | Оффер неактивен (без fallback) |
TRACKING_RATE_LIMITED | 429 | Явный флуд по трекинг-эндпоинту |
Общие
| Код | HTTP | Когда |
|---|---|---|
VALIDATION_ERROR | 422 | Ошибка валидации тела (карта полей в details) |
FORBIDDEN | 403 | Недостаточно прав/роли |
TENANT_HEADER_REQUIRED | 400 | Несколько бизнесов и не указан X-Tenant-Id (details.tenants) |
TOO_MANY_REQUESTS | 429 | Превышен лимит (заголовок Retry-After) |
SERVICE_UNAVAILABLE | 503 | Зависимость недоступна (fail-closed) |
INTERNAL_SERVER_ERROR | 500 | Необработанная ошибка |
Пользовательские ошибки кабинета
Коды, которые видит человек в интерфейсе кабинета (например BELOW_MIN_PAYOUT, KYC_REQUIRED, INSUFFICIENT_BALANCE, OFFER_PAUSED, SELF_REFERRAL_FORBIDDEN), описаны в пользовательском справочнике. Полный перечень с человеческими формулировками — на странице Справочник ошибок.