Перейти к содержанию

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

В каждом запросе к /api/v1 передавайте свой API-ключ мерчанта в заголовке x-api-key. Ни логина, ни обмена токенами, ни сессии, которую надо поддерживать, здесь нет. Двум эндпоинтам вне этого префикса — /docs и /health — ключ не нужен.

curl https://api.pay.nullswap.com/api/v1/invoices?limit=20 \
  -H "x-api-key: sk_live_2f8b1c0d4e5a69738f2a1b0c9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b2c1d0e"

Ключ состоит из префикса sk_live_ и 64 шестнадцатеричных символов. Это не bearer-токен: заголовок Authorization: Bearer ... просто игнорируется, и API ответит 401, как если бы ключ не передавали вовсе.

Один ключ — один мерчант

Ключ однозначно определяет мерчанта. Отсюда следует правило, которое действует на всех остальных страницах:

Ни один маршрут в этом API не принимает id мерчанта

Ни в пути, ни в query-параметрах, ни в теле. Любая выборка заранее ограничена вашим мерчантом, и всё, что вы создаёте, создаётся от его имени. Если вы ищете, куда подставить merchantId, — такого поля нет.

В ответах merchantId всё же попадается — у инвойса или статического кошелька, — но лишь справочно: там всегда будет ваш собственный идентификатор.

Посмотреть, какому мерчанту принадлежит ключ:

curl https://api.pay.nullswap.com/api/v1/merchant \
  -H "x-api-key: sk_live_..."
{
  "id": "9f1d2c3b-4a5e-4f60-8b71-2c3d4e5f6a7b",
  "name": "Acme Store",
  "status": "ACTIVE",
  "createdAt": "2026-01-01T12:00:00.000Z",
  "updatedAt": "2026-01-01T12:00:00.000Z",
  "feePercentage": "150"
}

feePercentage — комиссия мерчанта, которую мы берём с ваших платежей, в базисных пунктах ("150" — это 1.50%). Её устанавливаем мы; маршрута, чтобы её изменить, нет. Она удерживается из каждого свипа на ваш баланс — см. комиссию мерчанта.

Чего ключ не может

Администрирование мерчанта в это API не входит. Участники, API-ключи, белые списки IP, белый список адресов для вывода, правила автоконвертации и подписки на вебхуки заводятся и меняются вручную в кабинете. Маршрутов для вебхуков в API нет вовсе: через него нельзя ни создать, изменить или удалить подписку, ни прочитать её, её историю доставок или секрет, которым вы проверяете подписи, — его смотрят в кабинете.

Если точнее, данные меняют всего шесть маршрутов, и это весь их список:

Метод Путь
POST /api/v1/invoices
POST /api/v1/invoices/{invoiceId}/payments/{paymentId}/resolve
POST /api/v1/invoices/{invoiceId}/payments/{paymentId}/refund
POST /api/v1/static-wallets
POST /api/v1/wallets/{walletId}/sweep
POST /api/v1/merchant/withdrawals

Маршрутов PUT, PATCH и DELETE нет.

Держите ключ на сервере

Ключ работает на предъявителя в самом прямом смысле: кто им владеет, тот может создавать инвойсы, выводить ваши деньги и читать всю историю ваших платежей.

Никогда не передавайте ключ в браузер или мобильное приложение

Обращайтесь к API только со своего бэкенда. Если ключ утёк, перевыпустите его в кабинете: старый перестанет работать уже со следующего запроса, потому что ключи нигде не кешируются.

Ключ у мерчанта один, он находится в кабинете в разделе Настройки → API-ключ. У нового мерчанта ключа нет: первый выпускает владелец кнопкой Выпустить ключ. Перевыпустить его может только владелец — старый ключ при этом сразу отзывается. Выпуск и перевыпуск требуют двухфакторного кода, если у владельца включена двухфакторная аутентификация.

Ключ показывается один раз

Полностью кабинет показывает ключ только сразу после выпуска или перевыпуска. Тогда же скопируйте его в хранилище секретов вашего бэкенда: мы храним только последние четыре символа, поэтому дальше любой участник видит ключ замаскированным (••••1d0e), и показать его снова не может никто, включая нас. Если ключ потерян, перевыпустите его и обновите интеграции.

Белый список IP

Доступ к API можно дополнительно ограничить списком адресов, с которых разрешены запросы, — на карточке Доступ к API по IP в разделе Настройки → API-ключ. Список принадлежит мерчанту, а не ключу, поэтому переживает перевыпуск ключа. Менять его может только владелец. Настройки → Белые списки — это другой список: адреса для вывода.

  • Пустой белый список фильтрацию не включает — ключ работает откуда угодно.
  • Как только в списке появится хотя бы одна запись, запросы со всех остальных адресов начнут получать 403 CALLER_IP_NOT_ALLOWED, даже если сам ключ полностью корректен.
  • Запись — это IPv4-адрес, в котором любой октет может быть * (203.0.113.*), точный IPv6-адрес или одиночная * для любого адреса. Диапазоны CIDR не принимаются, а в IPv6 подстановки нельзя.

Заблокированный мерчант получает отказ MERCHANT_BLOCKED ещё до проверки его белого списка.

Сверяемся мы с реальным адресом, с которого установлено TCP-соединение. Заголовок X-Forwarded-For подделывается и потому не учитывается. Если ваш трафик выходит через NAT или egress-прокси, в белый список нужно добавлять адрес этого узла, а не адрес сервера приложения.

Ошибки

Статус message Причина
401 INVALID_API_KEY Заголовка нет, он повреждён, ключ неизвестен или отозван. Различить эти четыре случая по ответу нельзя — так задумано.
403 CALLER_IP_NOT_ALLOWED Ключ верный, но запрос пришёл с адреса, которого нет в его белом списке.
403 MERCHANT_BLOCKED Мерчант заблокирован.
403 PERMISSION_DENIED Ресурс, который вы запросили, принадлежит другому мерчанту.

Заблокированный мерчант не может и читать

MERCHANT_BLOCKED возникает на этапе аутентификации, ещё до того, как начнёт выполняться сам маршрут, — а значит, затрагивает вообще все эндпоинты, включая чтение. Если у вас 403 трактуется как «запись отклонена», эту трактовку надо расширить.

Стоит различать 403 PERMISSION_DENIED и 404. Инвойс, который существует, но принадлежит другому мерчанту, вернёт 403, а не 404. Запрос идентификатора, которого нет вообще нигде, — это 404.