Перейти к содержимому

API

На странице

Коды ошибок

Обрабатывайте ошибки Merchant API по стабильным машинным кодам, деталям валидации полей и документированным сценариям восстановления.

Каталог кодов

Стабильные машинно-читаемые идентификаторы возвращаются в code (а при ошибке по конкретному полю — в errors[].code). Список — фактически выдаваемый набор: каждый код ниже реально отдаёт хотя бы один обработчик, валидатор или middleware в API. Список только пополняется: семантика существующих кодов не меняется, новые коды добавляются под новые сценарии.

Используйте code для программной обработки. detail приходит только на английском — для логов и запасного UI; локализуйте на клиенте по code.

Коды поля

Возвращаются при валидации запроса. У кодов уровня поля (ниже) field содержит имя поля, не прошедшего проверку, в snake_case. Когда сразу несколько полей не проходят проверку, код верхнего уровня — validation_failed, а разбивка по полям лежит в errors[].

Code Когда Что делать
validation_failed Сразу несколько полей не прошли валидацию. Это код верхнего уровня; разбивка по полям — у каждого свой code и field — лежит в errors[]. Разберите errors[] и поправьте каждое перечисленное field.
field_required Обязательное поле пустое, null или состоит только из пробелов. Передайте значение в field.
field_too_long Поле длиннее допустимого максимума. Обрежьте до лимита, указанного для этого эндпоинта.
field_out_of_range Числовое значение вне допустимого диапазона. Приведите значение к документированному диапазону.
field_invalid_enum Значение не входит в набор допустимых значений enum (например, незнакомая currency / network, или токен не включён в проекте). Сверьтесь со справочником допустимых значений; для токенов — убедитесь, что пара токен+сеть включена в проекте.
field_invalid_format Значение не соответствует формату поля: либо не парсится как id (например, invoice_id без префикса inv_…), либо amount передан не простой decimal-строкой вида "10.00". Передавайте поле в документированном формате; id — ровно в том виде, в каком их вернул API.
entity_id_empty Переданный id — это нулевой (пустой) GUID (00000000-0000-…). field указывает на конкретный id — например, invoice_id или withdrawal_id. Передавайте id ровно в том виде, в каком его вернул API; не отправляйте пустой или обнулённый id.
field_must_be_positive Десятичное или целое число должно быть больше 0. Передайте положительное значение.
field_percentage_out_of_range Процент должен быть в диапазоне [0, 100] включительно. Приведите значение к диапазону [0, 100].
query_parameter_unknown В list-запросе передан query-параметр, которого нет у этого эндпоинта. Удалите параметр или используйте его документированное имя в snake_case.
pagination_cursor_invalid Курсор повреждён, истёк, подделан, относится к другому ресурсу или совмещён с другими фильтрами. Начните пагинацию без cursor, затем сохраняйте фильтры при переходе по next_cursor.
amount_too_many_decimals Для инвойса с суммой в фиатной валюте amount содержит больше знаков после запятой, чем допускает минимальная единица валюты (например, 23.345 для USD, 23.01 для JPY). Округлите до минимальной единицы валюты.
amount_too_large amount при создании инвойса или выплаты выходит за поддерживаемый диапазон — выше потолка в 20 целых знаков, который хранит API. Передайте сумму в пределах поддерживаемого диапазона.

Резервные коды по HTTP-статусу

Возвращаются, когда у ошибки нет своего бизнес-кода. Каждый код — резервный вариант для HTTP-статуса: запрос не прошёл, а описать причину точнее было нечем.

Code HTTP Когда Что делать
forbidden 403 Аутентификация прошла, но этому ключу операция не разрешена: не хватает возможностей (scope) или не то окружение — например, Sandbox-ключ на эндпоинте только для Production. Используйте ключ с нужными возможностями и в нужном окружении. Владение никогда не даёт 403: чужой ресурс возвращает not_found (404), а не forbidden.
payment_key_required 403 Эндпоинту нужен Payment-ключ (pk_), а запрос пришёл с Payout-ключом (rk_) — например, получение списка инвойсов. Вызовите его Payment-ключом.
payout_key_required 403 Эндпоинту нужен Payout-ключ (rk_), а запрос пришёл с Payment-ключом (pk_) — например, чтение балансов. Вызовите его Payout-ключом. Учтите: Payout-ключу также нужен IP-whitelist, иначе он не работает.
internal_error 500 Непредвиденная ошибка или баг на нашей стороне. Повторите один раз. Если не проходит — обратитесь в поддержку и укажите время ответа.
validation_failed 400 Запрос не прошёл валидацию, но кода под конкретное поле не нашлось. Смотрите поле detail — там написано, что отклонено.

Аутентификация

Возвращается только на 401 Unauthorized от обработчика HMAC. Каждый код указывает на конкретную точку отказа — клиент может показать осмысленное сообщение вместо общего «auth failed».

Code HTTP Когда Что делать
unauthorized 401 Запасной код, когда не подошёл ни один из кодов ниже — обычно запрос к эндпоинту с обязательной аутентификацией без заголовка Authorization (или с нераспознанной схемой). Отправьте корректный заголовок HMAC Authorization; проверьте всю сборку подписи.
authorization_missing 401 Заголовок Authorization есть, но его значение пустое. Отправьте полный заголовок Authorization: HMAC-SHA256 {apiKeyId}:{base64signature}.
authorization_malformed 401 Заголовок есть, но его формат нарушен: схема распознана, но в учётных данных нет двоеточия, не разбирается id API-ключа или пустая подпись. Соберите заголовок по разделу Authentication; чаще всего — опечатка в id API-ключа.
timestamp_missing 401 Заголовок X-Request-Timestamp отсутствует или не разбирается как положительное целое. Передайте текущую Unix-метку в секундах.
timestamp_expired 401 Метка вышла за допустимое окно расхождения часов (по умолчанию ±5 минут — слишком в прошлом или слишком в будущем). Синхронизируйте часы по NTP; пересчитайте подпись со свежей меткой.
invalid_credentials 401 Ключ использовать нельзя: id не найден, ключ отозван, префикс окружения или типа не совпадает с сохранённым ключом либо подпись не сходится. Один код на все четыре случая — намеренно: разные ответы позволили бы тому, у кого нет секрета, выяснить, какие id ключей существуют. Проверьте, что id ключа верный и ключ активен, а подпись считается секретом того же ключа. Чаще всего причина в подписи: сверьте сборку строки для подписи ({ts}\n{METHOD}\n{path}\n{query}\n{bodyHash}) и то, что для пустого тела bodyHash — пустая строка (не хешируйте пустую строку).
ip_not_allowed 401 Для Payout-ключа задан белый список IP, и адрес клиента в него не входит. Проверка по IP есть только у Payout-ключей — Payment-ключи вызываются с любого адреса. Идёт после успешной подписи, поэтому корректная подпись с «не той» сети всё равно вернёт 401. Добавьте IP клиента (или его CIDR-блок) в белый список Payout-ключа в дашборде.
payout_whitelist_required 401 У только что созданного Payout-ключа ещё не задан белый список IP. Payout-ключи остаются неактивными, пока мерчант не добавит хотя бы один разрешённый IP — код отделён от ip_not_allowed, чтобы клиент мог отличить «не настроены параметры в дашборде» от «не тот адрес-источник». Откройте дашборд, перейдите на страницу API-ключей и добавьте хотя бы один IP или CIDR в белый список Payout-ключа.

Лимит запросов

Возвращается при 429 Too Many Requests, когда запрос превышает лимит для мерчанта. Лимит считается на мерчанта, в окне в одну секунду — не на IP и не на ключ API.

Code HTTP Когда Что делать
rate_limited 429 Превышен лимит запросов для мерчанта. Действуют два лимита: общий на все эндпоинты (по умолчанию 30 запросов в секунду) и строже — на создание инвойса, POST /v1/invoices (по умолчанию 5 запросов в секунду). В ответе указано, какой лимит сработал и на каком значении. Прочитайте заголовок Retry-After (пауза в секундах) и повторите запрос после неё. Большинство HTTP-клиентов с повторами учитывают Retry-After автоматически.

Транспорт и системные ошибки

Возвращаются системным обработчиком ошибок, когда запрос не дошёл до обработчика самого эндпоинта.

Code HTTP Когда Что делать
malformed_request 400 Тело запроса не удалось разобрать — повреждённый JSON. Проверьте, что тело — валидный JSON.
payload_too_large 413 Тело запроса превышает лимит в 1 MiB. Отправьте payload поменьше; разбейте крупные объёмы на отдельные запросы.
unsupported_media_type 415 Content-Type не application/json. Выставьте Content-Type: application/json.
method_not_allowed 405 Путь существует, но не для этого HTTP-метода. Используйте метод, указанный для эндпоинта (например, POST для создания).
route_not_found 404 Ни один эндпоинт не подходит под этот путь. Сверьте URL со справочником API.

Инвойсы

Code HTTP Когда Что делать
invoice_not_found 404 Инвойс с таким id не существует или принадлежит другому мерчанту. Используйте id, возвращённый POST /v1/invoices, без изменений.
project_not_found 404 project_id в запросе на создание инвойса не существует или не виден вызывающему. Используйте project id из дашборда (проект должен быть активен и принадлежать тому же мерчанту, что и API-ключ).
invoice_terminal 410 confirm-payment вызван на инвойсе со статусом expired или cancelled. (Инвойс paid возвращает invoice_not_awaiting_client, 409, а не этот код.) Обновите статус инвойса; делать больше нечего.
invoice_deadline_passed 410 confirm-payment вызван после истечения срока инвойса. Создайте новый инвойс.
requested_amount_invalid 400 amount в запросе на создание инвойса отсутствует, не разбирается, выходит за поддерживаемый диапазон десятичных значений или не положителен. Передайте amount положительной десятичной строкой вместе с выбранной currency и при необходимости — network.
invoice_amount_below_minimum 400 USD-эквивалент инвойса ниже минимума для токена/сети из каталога. Увеличьте сумму выше минимума, возвращённого для выбранного токена.
deposit_amount_exceeds_limit 400 USD-эквивалент ожидаемого платежа превышает лимит на один платёж MaxDepositAmount из политики мерчанта. Ограничивает рассчитанную сумму инвойса при подтверждении, а не фактический приход в блокчейне. Уменьшите сумму инвойса или запросите повышение лимита в поддержке.
currency_not_enabled_for_project 400 Запрошенная криптовалюта не входит в enabled_tokens проекта (ни в одной сети). Включите валюту в проекте либо выберите из enabled_tokens.
tokens_required 409 Создание инвойса или подтверждение платежа для проекта, где не включён ни один токен. Включите в проекте хотя бы один токен через дашборд.
acceptance_disabled 503 Приём запрошенного токена сейчас отключён глобально. Используйте другой токен или дождитесь возобновления.
exchange_rate_unavailable 503 Нет свежего курса для пары токен/фиат. Повторите запрос; курсы обновляются часто.
network_unavailable 503 При автоподтверждении не удалось зарезервировать адрес: пул адресов сети или сама сеть недоступны. Откажитесь от автоподтверждения; дайте клиенту выбрать токен на странице оплаты Paymos.
no_available_address 503 Нет свободного адреса для токена/сети. Повторите запрос.
address_lease_failed 503 Не удалось зарезервировать адрес для зачисления платежа. Повторите запрос.
bridge_unavailable 503 Мост для выбранной сети временно недоступен, поэтому при подтверждении не удалось выделить в ней адрес для зачисления. Повторите запрос — перебой временный.
client_confirmation_failed 409 Подтверждение со стороны клиента (выбор токена, автоподтверждение) отклонено. detail содержит причину. Смотрите detail; типично — инвойс уже не в awaiting_client или токен не разрешён.
invoice_not_awaiting_client 409 confirm-payment вызван на инвойсе, уже вышедшем из awaiting_client. Обновите статус инвойса; клиент уже прошёл выбор.
invoice_cannot_be_cancelled 409 Инвойс уже не в awaiting_client — клиент выбрал токен либо инвойс уже paid или expired. Повторная отмена уже отменённого инвойса возвращает 200, а не эту ошибку. Проверьте статус; отмена работает только в awaiting_client.
simulate_payment_failed 409 Вызов simulate_payment для тестового режима отклонён. Смотрите detail; обычно — несоответствие статуса или суммы.
not_sandbox 403 simulate-payment вызван для счёта рабочего режима. Симуляция доступна только для тестового счёта. Для рабочего счёта отправьте реальный перевод в выбранной сети.

Инвойсы через виджет

Эти коды возвращает эндпоинт POST /public/v1/sdk — создание счёта через виджет-SDK.

Code HTTP Когда Что делать
widget_key_missing 401 Заголовок X-Sdk-Key отсутствует или пуст на эндпоинте, где нужна авторизация виджета. Передайте публичный SDK-ключ в заголовке X-Sdk-Key.
widget_key_invalid 401 X-Sdk-Key передан, но не распознаётся как идентификатор ключа Paymos. Скопируйте ключ из панели управления; проверьте префикс и что в значение не попали лишние пробелы или URL-кодирование.
widget_key_not_found 401 Ключ распознан, но активной записи за ним нет: он отозван, удалён или это не Payment-ключ (ключи Payout виджетом не управляют). Возьмите активный Payment-ключ из панели управления.
widget_inactive 403 Виджет проекта выключен или ещё ни разу не был инициализирован. Включите виджет в настройках проекта.
pos_not_enabled 403 Запрос пришёл с source=pos, но у виджета проекта режим POS не включён. Включите POS в настройках виджета или передавайте source=embed.
origin_not_allowed 401 / 403 Браузерный Origin не входит в список разрешённых доменов. Проверок две: 401 на уровне авторизации, где origin сверяется с объединённым списком всех проектов ключа с активным виджетом, и 403 в обработчике, где сверка идёт с конкретным проектом запроса. Добавьте домен в разрешённые источники виджета. Запросы с того же домена — например, с POS-терминала на том же хосте — проверку пропускают.

Выводы

Code HTTP Когда Что делать
withdrawal_not_found 404 Вывода с таким id нет либо он принадлежит другому мерчанту. Используйте id, который вернул POST /v1/withdrawals, без изменений.
insufficient_balance 409 Доступный баланс мерчанта ниже amount + fee. Пополните баланс или уменьшите сумму вывода.
whitelist_required 403 Адрес назначения не добавлен в белый список для выбранной сети. (Сеть белый список поддерживает — просто этот адрес ещё не внесён.) Добавьте адрес в белый список и повторите запрос.
destination_address_invalid 400 Адрес не проходит проверку формата или контрольной суммы для этой сети. Сверьте адрес со спецификацией сети.
withdrawal_amount_below_minimum 400 Сумма ниже минимума для выбранного токена. Увеличьте сумму выше минимума (возвращается в detail).
withdrawal_quota_exceeded 409 Достигнут лимит активных выводов. Дождитесь завершения текущих или запросите повышение лимита.
withdrawal_amount_exceeds_limit 400 USD-эквивалент тела вывода превышает лимит на один платёж MaxWithdrawalAmount из политики мерчанта. Уменьшите сумму или запросите повышение лимита в поддержке.
exchange_rate_unavailable 503 У мерчанта задан лимит MaxWithdrawalAmount, но свежего курса токен/USD для проверки тела вывода нет — лимит не подтвердить, поэтому запрос отклоняется. Повторите запрос; курсы обновляются часто.
withdrawal_fee_not_configured 400 Paymos не выводит запрошенную пару токен/сеть. Пара названа в detail — например Withdrawals are not available for USDT on TRC20. Какие пары доступны для вывода, настраиваем мы, а не вы. Выведите токен в сети, по которой Paymos делает выплаты, либо спросите в поддержке про нужную пару.
withdrawal_cannot_be_cancelled 409 Вывод уже вышел из состояния, в котором его можно отменить. Проверьте текущий статус: отмена работает только до отправки в сеть.
withdrawal_simulation_failed 409 Вызов simulate_completion для тестового режима отклонён. Смотрите detail.
merchant_suspended 403 Мерчант приостановлен для исходящих операций, поэтому создать вывод нельзя. Обратитесь в поддержку, чтобы снять приостановку.
outbound_frozen 503 Исходящие операции заморожены — либо на всей платформе, либо для той сети и токена, в которых вы выводите. Дождитесь снятия, попробуйте другую сеть или токен либо обратитесь в поддержку.
hot_wallet_insufficient_liquidity 503 В горячем кошельке целевой сети недостаточно ликвидности в блокчейне для этой выплаты. Попробуйте другую сеть назначения или обратитесь в поддержку.

Состояние проекта

Возвращается при создании инвойса или подтверждении платежа, если статус проекта не позволяет их выпускать.

Code HTTP Когда Что делать
project_state_invalid 409 Проект не в статусе Active — он Suspended или Archived. Какой именно, ответ не сообщает. Посмотрите статус проекта в дашборде: архивный — восстановите, приостановленный — активируйте. Либо отправьте запрос в уже активный проект.