Коды ошибок и HTTP-статусы
Каждый отказ возвращает стабильный машиночитаемый код рядом с HTTP-статусом. Ветвитесь по коду, а не по тексту сообщения: сообщения написаны для людей и могут быть переформулированы, а коды — часть контракта.
Все коды (42), которые может вернуть реселлерский API, сгруппированы по типу сбоя. У каждой записи указан HTTP-статус, с которым она приходит, и изменение, которое её снимает.
Аутентификация (401)
| Код | HTTP | Что означает | Как исправить |
|---|---|---|---|
| MISSING_API_KEY | 401 | Нужен API-ключЗаголовок Authorization не передан или имеет неверный формат. | Добавь к запросу заголовок авторизации строго в таком формате: Authorization: Bearer <keyId>.<secret>action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_API_KEY | 401 | Неверный API-ключПереданный API-ключ не совпадает ни с одним активным ключом в системе. | Проверь ID ключа и секрет. Если нужно, создай новый ключ в панели API Access.action: FIX_INPUT · retryable: false · retry_after: null |
Авторизация (403)
| Код | HTTP | Что означает | Как исправить |
|---|---|---|---|
| ACCOUNT_DISABLED | 403 | Аккаунт отключёнБольше не возвращается. Если аккаунт не может оформлять заказы, придёт ACCOUNT_FROZEN (HTTP 403). | Обрабатывай вместо него ACCOUNT_FROZEN.Больше не возвращается, вместо него ACCOUNT_FROZEN |
| ACCOUNT_FROZEN | 403 | Аккаунт замороженТвой аккаунт временно заморожен. Обычно так бывает из-за подозрительной активности. | Напиши в поддержку, чтобы разморозить аккаунт.action: CONTACT_SUPPORT · retryable: false · retry_after: null |
| IP_NOT_ALLOWED | 403 | IP-адреса нет в белом спискеЗапрос пришёл с IP-адреса, которого нет в белом списке твоего API-ключа. | Добавь IP своего сервера в белый список в панели API Access или сними ограничения по IP.action: FIX_INPUT · retryable: false · retry_after: null |
Проверка запроса (400)
| Код | HTTP | Что означает | Как исправить |
|---|---|---|---|
| MISSING_REQUIRED_FIELD | 400 | Не заполнено обязательное полеВ теле запроса нет обязательного поля. Если речь о данных игрока, в details.field указано, какого поля не хватает. | Сверься с документацией эндпоинта, а поля игрока смотри в GET /catalog/category/:categoryId/requirements. Затем передай все обязательные поля.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_PARAMETER_FORMAT | 400 | Неверный формат параметраПоле из требований передано в неверном формате (например, текст в числовом поле). Какое именно, указано в details.field. | Ещё раз проверь требования категории и передай поле в формате, который ожидают его data_type и правила валидации.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_PARAMETER_VALUE | 400 | Недопустимое значение параметраЗначение поля из требований вне допустимых границ: меньше минимума, больше максимума или не входит в его select_options. Поле указано в details.field. | Передай значение, которое требования категории разрешают для этого поля.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_PARAMETER_LENGTH | 400 | Недопустимая длина параметраПоле из требований короче или длиннее допустимого. Название поля есть в details.field. | Проверь min_length / max_length в требованиях категории.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_UUID_FORMAT | 400 | Неверный формат UUIDorder_id не соответствует формату UUID. | Подойдёт UUID любой версии (v1, v4, v7 и т. д.), главное, чтобы он был корректным. Нужен строго такой вид (8-4-4-4-12 символов): xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_QUANTITY | 400 | Неверное количествоКоличество должно быть целым положительным числом. | Укажи целое количество >= 1.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_CATEGORY_ID | 400 | Неверный ID категорииПереданный categoryId не является корректным числом. | Действующие идентификаторы категорий смотри в Catalog Explorer или получай списком через запрос GET /catalog/categories.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_BIG_CATEGORY_ID | 400 | Неверный ID большой категорииbigCategoryId должен быть корректным числом, а пришло другое значение. | Список действующих идентификаторов крупных категорий есть в Catalog Explorer, его же отдаёт запрос GET /catalog/big-categories.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_ITEM_ID | 400 | Неверный ID товараУказанный ID товара недействителен. | Нужный идентификатор товара найдёшь в Catalog Explorer или в ответе на запрос GET /catalog/subcategories, там перечислены все действующие.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_SUBCATEGORY | 400 | Неверная подкатегорияПодкатегории с таким ID не существует. | Проверь sub_category_id через эндпоинты каталога.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_PRODUCT_CONFIG | 400 | Неверная конфигурация товараБольше не возвращается. Если не хватает поля из требований, теперь придёт MISSING_REQUIRED_FIELD, а если товар сейчас нельзя продать, придёт PRODUCT_UNAVAILABLE. | Вместо этого обрабатывай MISSING_REQUIRED_FIELD (не заполнено обязательное поле) и PRODUCT_UNAVAILABLE (товар недоступен).Больше не возвращается, вместо него MISSING_REQUIRED_FIELD |
| INVALID_PAGINATION | 400 | Неверные параметры пагинацииЗначение page или limit вне допустимого диапазона. | Передавай page не меньше 1, а limit от 1 до 100.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_DATE_FORMAT | 400 | Неверный формат датыВ параметре created_after или created_before указана дата, которая не соответствует формату ISO 8601. | Используй формат ISO 8601: 2024-01-01T00:00:00Z.action: FIX_INPUT · retryable: false · retry_after: null |
Проверка игрока (400 / 429 / 503)
| Код | HTTP | Что означает | Как исправить |
|---|---|---|---|
| PLAYER_NOT_FOUND | 400 | Игрок не найденИгра подтвердила, что такого ID игрока нет. Этот код приходит только при подтверждённом ответе. Если ID проверить не удалось, вместо него придёт PLAYER_CHECK_UNAVAILABLE. | Проверь, правильно ли указан ID игрока. Узнай, не нужен ли для этой игры zone_id.action: FIX_INPUT · retryable: false · retry_after: null |
| PLAYER_CHECK_UNAVAILABLE | 503 | Сейчас не получается проверить ID игроков в этой игреID игроков в этой игре пока недоступны для проверки. ID игрока НЕ отклонён. | Повтори тот же запрос через retry_after секунд. Не говори клиенту, что ID неверный.action: RETRY_LATER · retryable: true · retry_after: 60 |
| PLAYER_BUSY | 429 | Этот ID игрока уже проверяетсяДругой запрос с этим же ID игрока ещё на проверке. | Отправь запрос снова через retry_after секунд.action: RETRY_SOON · retryable: true · retry_after: 5 |
| PLAYER_VALIDATION_FAILED | 400 | Ошибка проверки игрокаБольше не возвращается. Если ID игрока сейчас нельзя проверить, придёт PLAYER_CHECK_UNAVAILABLE (HTTP 503). | В своей интеграции обрабатывай вместо этой ошибки код PLAYER_CHECK_UNAVAILABLE.Больше не возвращается, вместо него PLAYER_CHECK_UNAVAILABLE |
| REGION_MISMATCH | 400 | Этот товар недоступен для региона игрокаИгрок из региона, куда этот товар доставить нельзя. В ошибке приходят player_region и player_name. | Выбери товар для региона игрока.action: CHOOSE_OTHER · retryable: false · retry_after: null |
Бизнес-правила (400 / 409)
| Код | HTTP | Что означает | Как исправить |
|---|---|---|---|
| INSUFFICIENT_BALANCE | 400 | Недостаточно средств на кошелькеНа кошельке не хватает средств для этого заказа. | Пополни кошелёк на странице Reload, затем оформи заказ.action: TOP_UP · retryable: false · retry_after: null |
| OUT_OF_STOCK | 400 | Товара нет в наличииЗапрошенный товар сейчас закончился. | Попробуй позже или выбери другой товар.action: RETRY_LATER · retryable: true · retry_after: null |
| INSUFFICIENT_STOCK | 400 | В наличии меньше единиц, чем запрошеноДоступно меньше единиц, чем указано в заказе. В отличие от OUT_OF_STOCK, здесь можно что-то сделать: error.max_quantity показывает, сколько единиц можно заказать прямо сейчас. Средства не списаны. | Отправь заказ заново с количеством не больше error.max_quantity.action: FIX_INPUT · retryable: false · retry_after: null |
| PRODUCT_UNAVAILABLE | 409 | Товар временно недоступенТовар существует, но сейчас не продаётся. | Повтори попытку позже или возьми другой товар.action: RETRY_LATER · retryable: true · retry_after: null |
| PRICING_UPDATING | 409 | Цена товара обновляетсяЦена на этот товар сейчас пересчитывается. | Через retry_after секунд отправь тот же запрос ещё раз и заново проверь цену.action: RETRY_SOON · retryable: true · retry_after: 30 |
| OFFER_NOT_FOUND | 400 | Предложение недоступно для этого аккаунта игрокаРазовое предложение (например, бонус за первое пополнение) недоступно для этого аккаунта игрока. Возможно, его уже использовали. | Выбери для этого игрока другой товар.action: CHOOSE_OTHER · retryable: false · retry_after: null |
| DUPLICATE_ORDER | 409 | ID заказа уже используетсяЗаказ с таким UUID уже существует. Это защита по идемпотентности. | Для нового заказа сгенерируй новый UUID. Если ошибка пришла на повторный запрос, значит первая попытка прошла: получи этот заказ через GET /orders/{orderId}, а не создавай новый.action: CHECK_ORDER · retryable: false · retry_after: null |
| PRICE_INCREASED | 400 | Цена выросла выше ожидаемойТекущая цена за единицу выше, чем указанная тобой expected_unit_price. | Сначала запроси актуальную цену через GET /catalog/subcategory/:id/price. Потом обнови поле expected_unit_price: впиши туда значение, которое вернул запрос.action: FIX_INPUT · retryable: false · retry_after: null |
| SUBCATEGORY_DISABLED | 400 | Подкатегория отключенаБольше не возвращается. Если товар сейчас нельзя продать, приходит PRODUCT_UNAVAILABLE (HTTP 409). | Обрабатывай PRODUCT_UNAVAILABLE вместо этой ошибки.Больше не возвращается, вместо него PRODUCT_UNAVAILABLE |
Не найдено (404)
| Код | HTTP | Что означает | Как исправить |
|---|---|---|---|
| ORDER_NOT_FOUND | 404 | Заказ не найденЗаказа с указанным ID не существует. | Проверь, правильно ли указан ID заказа.action: FIX_INPUT · retryable: false · retry_after: null |
| ITEM_NOT_FOUND | 404 | Товар не найденЗапрошенного товара нет в каталоге. | Найди действующие ID товаров через эндпоинты каталога.action: FIX_INPUT · retryable: false · retry_after: null |
| NO_REQUIREMENTS_FOUND | 404 | Для этой категории нет требованийСейчас у этой категории нет требований к данным игрока. | Попробуй позже или выбери другую категорию.action: RETRY_LATER · retryable: true · retry_after: null |
| ITEM_NOT_AVAILABLE | 404 | Товар недоступенБольше не возвращается. Если товар существует, но сейчас не продаётся, приходит PRODUCT_UNAVAILABLE (HTTP 409). | Теперь вместо него приходит PRODUCT_UNAVAILABLE, обрабатывай его.Больше не возвращается, вместо него PRODUCT_UNAVAILABLE |
Проверка пакетного запроса (400)
| Код | HTTP | Что означает | Как исправить |
|---|---|---|---|
| INVALID_ORDER_IDS_FORMAT | 400 | Неверный формат order_idsПоле order_ids должно быть массивом строк. | Передай order_ids в таком виде: { "order_ids": ["uuid1", "uuid2"] }.action: FIX_INPUT · retryable: false · retry_after: null |
| EMPTY_ORDER_IDS | 400 | Пустой массив order_idsМассив order_ids не может быть пустым. | Укажи в массиве хотя бы один ID заказа.action: FIX_INPUT · retryable: false · retry_after: null |
| TOO_MANY_ORDER_IDS | 400 | Слишком много ID заказовЗа один запрос можно получить не больше 50 ID заказов. | Разбей запрос на пачки, не больше 50 в каждой.action: FIX_INPUT · retryable: false · retry_after: null |
Лимит запросов (429)
| Код | HTTP | Что означает | Как исправить |
|---|---|---|---|
| RATE_LIMIT_EXCEEDED | 429 | Превышен лимит запросовЛимит запросов к этому эндпоинту исчерпан. Для поминутных лимитов (каталог, заказы, аккаунт) в каждом ответе приходят заголовки X-RateLimit-Limit, X-RateLimit-Remaining и X-RateLimit-Reset, а в объекте details повторяются поля limit, remaining (со значением 0), retry_after и window_seconds. POST /player/validate работает иначе: запросы к нему списываются с твоей дневной квоты на проверку игроков. Заголовков X-RateLimit этот эндпоинт не отдаёт, а в ответе 429 поля limit, current, remaining, reset_at и reset_in_seconds приходят внутри объекта error. Сколько секунд подождать перед следующей попыткой, в обоих случаях показывают поле error.retry_after и заголовок Retry-After. | Перед повтором подожди столько секунд, сколько указано в retry_after или в заголовке Retry-After. На эндпоинтах с минутным лимитом следи за X-RateLimit-Remaining, чтобы вообще не упираться в лимит.action: RETRY_LATER · retryable: true · retry_after: сек. до сброса |
Ошибки сервера (5xx)
| Код | HTTP | Что означает | Как исправить |
|---|---|---|---|
| INTERNAL_ERROR | 500 | Внутренняя ошибка сервераНа сервере произошла непредвиденная ошибка. | Через retry_after секунд отправь запрос снова. Для POST /orders/create используй тот же order_id, тогда заказ точно не создастся дважды. Если ошибка повторяется, напиши в поддержку.action: RETRY_LATER · retryable: true · retry_after: 30 |
| SERVICE_UNAVAILABLE | 503 | Сервис временно недоступенБольше не возвращается. При сбое на стороне сервера приходит INTERNAL_ERROR (HTTP 500). Код 503 приходит только с PLAYER_CHECK_UNAVAILABLE, когда ID игрока сейчас не получается проверить. | Вместо этого обрабатывай INTERNAL_ERROR (внутренняя ошибка) и PLAYER_CHECK_UNAVAILABLE (проверка игрока недоступна).Больше не возвращается, вместо него INTERNAL_ERROR |
Впервые на платформе? Начните с обзора API пополнения игр для реселлеров, а затем прочитайте обзор реселлерской программы SHOP2TOPUP, чтобы понять, как устроен партнёрский аккаунт.