Ошибки
Формат отказа, все коды error_code и частые ошибки интеграции.
Отказ приходит с HTTP-статусом 4xx или 5xx и телом {"error": "текст", "error_code": "snake_case"}. Ветвитесь по error_code: он стабилен, а error написан для разработчика и может меняться. Пользователю показывайте своё сообщение.
Часть отказов несёт подробности: у validation_error (422) в details список полей с причинами, у insufficient_balance (402) могут быть required_minor и balance_minor.
Можно ли повторить запрос как есть, подсказывает столбец «Повтор» в таблице ниже. Денежную операцию повторяйте только с тем же custom_id. 429 rate_limited приходит с заголовком Retry-After: подождите столько секунд. 503 и 500 повторяйте с растущей паузой; у 503 upstream_unavailable есть Retry-After, раньше него не повторяйте. Повтор всегда с тем же custom_id: новый custom_id на каждой попытке при сбое поставщика это новая покупка на каждой попытке.
Коды ошибок
| Код | HTTP | Что случилось | Что делать | Повтор |
|---|---|---|---|---|
unauthorized | 401 | Неверный или отсутствующий API-ключ | Проверьте заголовок Authorization: Bearer <ключ>. Ключ выпускается в кабинете. | нет, нужны изменения |
key_revoked | 401 | Этот ключ отозван: выпущен новый | Возьмите действующий ключ в кабинете и подставьте его во все свои скрипты. Отозванный ключ не заработает снова. | нет, нужны изменения |
api_disabled | 403 | Доступ к API для этого аккаунта закрыт | Напишите в поддержку площадки. | нет, нужны изменения |
key_read_only | 403 | Этот ключ только для чтения | Для покупок, продлений и других изменений возьмите полный ключ. Ключ для чтения принимают только GET-запросы. | нет, нужны изменения |
ip_not_allowed | 403 | Адрес запроса не входит в список разрешённых | Добавьте адрес сервера в кабинете (раздел «Ключ и вебхук», «Разрешённые адреса») или вызывайте API с разрешённого сервера. Адрес, с которого пришёл запрос, указан в тексте ошибки. | нет, нужны изменения |
partner_blocked | 403 | Аккаунт партнёра заблокирован | Напишите в поддержку площадки. | нет, нужны изменения |
forbidden | 403 | Объект принадлежит другому аккаунту | Проверьте идентификатор: бот или подписка не ваши. | нет, нужны изменения |
trial_disabled | 403 | Пробный период выключен в настройках партнёра | Включите пробный период в кабинете, раздел «Маркетинг». | нет, нужны изменения |
trial_channel_required | 403 | Пробный период у этого бота только подписчикам канала | Партнёр включил «Пробник только подписчикам канала». Попросите пользователя подписаться на каналы из поля channels и повторите запрос. Пользователю без telegram_id пробник этого бота недоступен. | да, тот же запрос |
not_found | 404 | Объект не найден | Проверьте идентификатор. | нет, нужны изменения |
plan_not_found | 404 | Тариф не найден или недоступен | Возьмите plan_uuid из GET /plans. | нет, нужны изменения |
subscription_not_found | 404 | Подписка не найдена | Проверьте subscription_id. Чужие подписки тоже отвечают этим кодом. | нет, нужны изменения |
operation_not_found | 404 | Операция с таким custom_id не найдена | Запрос с этим custom_id до нас не дошёл: его можно отправить снова тем же custom_id. | нет, нужны изменения |
deposit_not_found | 404 | Пополнение не найдено | Проверьте custom_id пополнения. | нет, нужны изменения |
device_not_found | 404 | Устройство не найдено | Список устройств: GET /subscriptions/{id}/devices. | нет, нужны изменения |
device_block_not_found | 404 | Отключённое устройство не найдено | Список отключённых: GET /subscriptions/{id}/devices/blocked. | нет, нужны изменения |
trial_plan_missing | 404 | Пробный тариф временно недоступен | Повторите позже или продайте платный тариф. | да, тот же запрос |
insufficient_balance | 402 | Недостаточно средств на депозите | Пополните депозит: POST /deposit или кабинет. В ответе есть required_minor и balance_minor. | нет, нужны изменения |
max_charge_exceeded | 409 | Цена операции выше max_charge_minor | Цена изменилась с момента расчёта. Перечитайте цену (GET /plans, renew-quote, upgrade-quote) и повторите с новым custom_id. В ответе есть charge_minor и max_charge_minor. Деньги не списаны. | нет, нужны изменения |
custom_id_conflict | 409 | Этот custom_id уже использован с другими параметрами | Для новой операции возьмите новый custom_id. | нет, нужны изменения |
operation_in_progress | 409 | Операция с этим custom_id ещё выполняется | Повторите тот же запрос через секунду: вернётся результат первой попытки. | да, тот же запрос |
subscription_state | 409 | Операция не подходит к текущему состоянию подписки | Проверьте статус: GET /subscriptions/{id}. | нет, нужны изменения |
unsupported_for_product | 409 | Это действие не подходит к этому виду подписки | Бессрочную подписку («Навсегда») не продлевают, не замораживают и не переводят на другой тариф, трафик и устройства к ней докупаются через POST /subscriptions/{id}/addons. Подписке на срок докупки этого вида недоступны, трафик ей докупается через POST /subscriptions/{id}/traffic. | нет, нужны изменения |
addon_unavailable | 409 | Эту докупку сейчас нельзя оформить | Докупки есть только у действующей платной бессрочной подписки, не у пробной. Проверьте подписку: GET /subscriptions/{id}. | нет, нужны изменения |
subscription_frozen | 409 | Подписка заморожена | Сначала разморозьте: POST /subscriptions/{id}/unfreeze. | нет, нужны изменения |
subscription_expired | 409 | Подписка истекла | Продлите подписку, после этого операция станет доступна. | нет, нужны изменения |
trial_already_used | 409 | Этот пользователь уже получал пробный период | Пробный период выдаётся один раз на external_user_id. | нет, нужны изменения |
trial_not_renewable | 409 | Пробную подписку нельзя продлить | Купите платный тариф: POST /subscriptions или апгрейд. | нет, нужны изменения |
trial_not_freezable | 409 | Пробную подписку нельзя заморозить | Заморозка доступна только платным подпискам. | нет, нужны изменения |
trial_no_traffic | 409 | К пробной подписке нельзя докупить трафик | Пакеты трафика доступны только платным подпискам. Купите тариф: POST /subscriptions или апгрейд. | нет, нужны изменения |
special_plan_used | 409 | Спецтариф этому пользователю уже выдавался | Выберите обычный тариф. | нет, нужны изменения |
external_user_conflict | 409 | telegram_id или external_user_id уже привязан к другому пользователю | Используйте тот external_user_id, под которым этот Telegram уже заведён: его видно в GET /clients?telegram_id=…. Если ваш external_user_id уже занят другим человеком, двух клиентов API не склеивает: напишите в поддержку. | нет, нужны изменения |
webhook_not_configured | 409 | Адрес вебхука не задан | Сохраните URL: PUT /webhook. | нет, нужны изменения |
too_many_open_deposits | 409 | Слишком много неоплаченных пополнений | Оплатите или дождитесь истечения открытых счетов. | да, тот же запрос |
validation_error | 422 | Неверные параметры запроса | Смотрите details: там поле и причина. | нет, нужны изменения |
upstream_rejected | 422 | Поставщик VPN отклонил запрос | Проверьте параметры. Если всё верно, напишите в поддержку. | нет, нужны изменения |
rate_limited | 429 | Слишком много запросов | Подождите Retry-After секунд. Лимит: 60 запросов в минуту на ключ. | да, тот же запрос |
upstream_unavailable | 503 | Поставщик VPN временно недоступен | Повторите через минуту с тем же custom_id: двойного списания не будет. | да, тот же запрос |
provider_unavailable | 503 | Платёжный способ временно недоступен | Выберите другой способ из GET /deposit/providers. | да, тот же запрос |
maintenance | 503 | API на обслуживании | Повторите через несколько минут. | да, тот же запрос |
internal_error | 500 | Внутренняя ошибка | Повторите с тем же custom_id. Если повторяется, напишите в поддержку. | да, тот же запрос |
unauthorized401Неверный или отсутствующий API-ключ
Проверьте заголовок Authorization: Bearer <ключ>. Ключ выпускается в кабинете.
Повтор: нет, нужны изменения
key_revoked401Этот ключ отозван: выпущен новый
Возьмите действующий ключ в кабинете и подставьте его во все свои скрипты. Отозванный ключ не заработает снова.
Повтор: нет, нужны изменения
api_disabled403Доступ к API для этого аккаунта закрыт
Напишите в поддержку площадки.
Повтор: нет, нужны изменения
key_read_only403Этот ключ только для чтения
Для покупок, продлений и других изменений возьмите полный ключ. Ключ для чтения принимают только GET-запросы.
Повтор: нет, нужны изменения
ip_not_allowed403Адрес запроса не входит в список разрешённых
Добавьте адрес сервера в кабинете (раздел «Ключ и вебхук», «Разрешённые адреса») или вызывайте API с разрешённого сервера. Адрес, с которого пришёл запрос, указан в тексте ошибки.
Повтор: нет, нужны изменения
partner_blocked403Аккаунт партнёра заблокирован
Напишите в поддержку площадки.
Повтор: нет, нужны изменения
forbidden403Объект принадлежит другому аккаунту
Проверьте идентификатор: бот или подписка не ваши.
Повтор: нет, нужны изменения
trial_disabled403Пробный период выключен в настройках партнёра
Включите пробный период в кабинете, раздел «Маркетинг».
Повтор: нет, нужны изменения
trial_channel_required403Пробный период у этого бота только подписчикам канала
Партнёр включил «Пробник только подписчикам канала». Попросите пользователя подписаться на каналы из поля channels и повторите запрос. Пользователю без telegram_id пробник этого бота недоступен.
Повтор: да, тот же запрос
not_found404Объект не найден
Проверьте идентификатор.
Повтор: нет, нужны изменения
plan_not_found404Тариф не найден или недоступен
Возьмите plan_uuid из GET /plans.
Повтор: нет, нужны изменения
subscription_not_found404Подписка не найдена
Проверьте subscription_id. Чужие подписки тоже отвечают этим кодом.
Повтор: нет, нужны изменения
operation_not_found404Операция с таким custom_id не найдена
Запрос с этим custom_id до нас не дошёл: его можно отправить снова тем же custom_id.
Повтор: нет, нужны изменения
deposit_not_found404Пополнение не найдено
Проверьте custom_id пополнения.
Повтор: нет, нужны изменения
device_not_found404Устройство не найдено
Список устройств: GET /subscriptions/{id}/devices.
Повтор: нет, нужны изменения
device_block_not_found404Отключённое устройство не найдено
Список отключённых: GET /subscriptions/{id}/devices/blocked.
Повтор: нет, нужны изменения
trial_plan_missing404Пробный тариф временно недоступен
Повторите позже или продайте платный тариф.
Повтор: да, тот же запрос
insufficient_balance402Недостаточно средств на депозите
Пополните депозит: POST /deposit или кабинет. В ответе есть required_minor и balance_minor.
Повтор: нет, нужны изменения
max_charge_exceeded409Цена операции выше max_charge_minor
Цена изменилась с момента расчёта. Перечитайте цену (GET /plans, renew-quote, upgrade-quote) и повторите с новым custom_id. В ответе есть charge_minor и max_charge_minor. Деньги не списаны.
Повтор: нет, нужны изменения
custom_id_conflict409Этот custom_id уже использован с другими параметрами
Для новой операции возьмите новый custom_id.
Повтор: нет, нужны изменения
operation_in_progress409Операция с этим custom_id ещё выполняется
Повторите тот же запрос через секунду: вернётся результат первой попытки.
Повтор: да, тот же запрос
subscription_state409Операция не подходит к текущему состоянию подписки
Проверьте статус: GET /subscriptions/{id}.
Повтор: нет, нужны изменения
unsupported_for_product409Это действие не подходит к этому виду подписки
Бессрочную подписку («Навсегда») не продлевают, не замораживают и не переводят на другой тариф, трафик и устройства к ней докупаются через POST /subscriptions/{id}/addons. Подписке на срок докупки этого вида недоступны, трафик ей докупается через POST /subscriptions/{id}/traffic.
Повтор: нет, нужны изменения
addon_unavailable409Эту докупку сейчас нельзя оформить
Докупки есть только у действующей платной бессрочной подписки, не у пробной. Проверьте подписку: GET /subscriptions/{id}.
Повтор: нет, нужны изменения
subscription_frozen409Подписка заморожена
Сначала разморозьте: POST /subscriptions/{id}/unfreeze.
Повтор: нет, нужны изменения
subscription_expired409Подписка истекла
Продлите подписку, после этого операция станет доступна.
Повтор: нет, нужны изменения
trial_already_used409Этот пользователь уже получал пробный период
Пробный период выдаётся один раз на external_user_id.
Повтор: нет, нужны изменения
trial_not_renewable409Пробную подписку нельзя продлить
Купите платный тариф: POST /subscriptions или апгрейд.
Повтор: нет, нужны изменения
trial_not_freezable409Пробную подписку нельзя заморозить
Заморозка доступна только платным подпискам.
Повтор: нет, нужны изменения
trial_no_traffic409К пробной подписке нельзя докупить трафик
Пакеты трафика доступны только платным подпискам. Купите тариф: POST /subscriptions или апгрейд.
Повтор: нет, нужны изменения
special_plan_used409Спецтариф этому пользователю уже выдавался
Выберите обычный тариф.
Повтор: нет, нужны изменения
external_user_conflict409telegram_id или external_user_id уже привязан к другому пользователю
Используйте тот external_user_id, под которым этот Telegram уже заведён: его видно в GET /clients?telegram_id=…. Если ваш external_user_id уже занят другим человеком, двух клиентов API не склеивает: напишите в поддержку.
Повтор: нет, нужны изменения
webhook_not_configured409Адрес вебхука не задан
Сохраните URL: PUT /webhook.
Повтор: нет, нужны изменения
too_many_open_deposits409Слишком много неоплаченных пополнений
Оплатите или дождитесь истечения открытых счетов.
Повтор: да, тот же запрос
validation_error422Неверные параметры запроса
Смотрите details: там поле и причина.
Повтор: нет, нужны изменения
upstream_rejected422Поставщик VPN отклонил запрос
Проверьте параметры. Если всё верно, напишите в поддержку.
Повтор: нет, нужны изменения
rate_limited429Слишком много запросов
Подождите Retry-After секунд. Лимит: 60 запросов в минуту на ключ.
Повтор: да, тот же запрос
upstream_unavailable503Поставщик VPN временно недоступен
Повторите через минуту с тем же custom_id: двойного списания не будет.
Повтор: да, тот же запрос
provider_unavailable503Платёжный способ временно недоступен
Выберите другой способ из GET /deposit/providers.
Повтор: да, тот же запрос
maintenance503API на обслуживании
Повторите через несколько минут.
Повтор: да, тот же запрос
internal_error500Внутренняя ошибка
Повторите с тем же custom_id. Если повторяется, напишите в поддержку.
Повтор: да, тот же запрос
Частые ошибки интеграции
Придумываете его вы. Ретрай упавшего запроса с тем же custom_id безопасен, новая операция требует новый custom_id. Один custom_id на все типы операций: повторно использовать его для другого действия нельзя.
GET /balance перед оформлением у себя: 402 после того, как покупатель у вас уже заплатил, оставляет его без подписки. Держите запас и подписку на deposit.credited.
Продление и апгрейд не выдают новую subscription_url: отдайте её один раз и не просите пользователя переустанавливать конфиг. Новую выдаёт только rotate-link, после него старая ссылка перестаёт работать.
Срок замороженной подписки стоит на месте, купленные дни сгорели бы незаметно. API отвечает 409 subscription_frozen: сначала unfreeze.
Складывайте *_minor, показывайте *_usd. Арифметика во float даёт 0.30000000000000004 и расхождение в цент с вашим биллингом.
Доставка может опоздать или не дойти. Перед действием по событию перечитайте GET /subscriptions/{id}: там актуальный статус и end_date.
Поле error написано для интегратора. Переведите error_code в своё сообщение и решите сами, повторять ли запрос (столбец «повтор» в таблице кодов).