API приёма платежей

Один метод создаёт заявку, дальше всё приходит вебхуками. Адрес, ключи и список доступных методов выдаются при подключении — они индивидуальны для каждого партнёра.

Документация общая для мерчантов и для провайдеров-агрегаторов: контракт один, различается только то, чей трафик вы передаёте.
Все суммы — целые числа в минимальных единицах валюты (копейки для RUB, 1e-6 для USDT). Дробных чисел в API нет: они округляются по-разному в разных языках и ломают сверку.

Подпись запросов

Каждый запрос подписывается ключом, выданным при подключении. Подпись покрывает метод, путь, метку времени, одноразовое значение, идентификатор ключа и хеш тела.

ЗаголовокЗначение
X-Payment-Keyидентификатор ключа, например acme-2026-01
X-Payment-Timestampвремя запроса в секундах Unix
X-Payment-Nonceодноразовое значение, уникальное в пределах окна
X-Payment-SignatureHMAC-SHA256 в hex

Строка для подписи собирается так:

METHOD + "\n" + PATH + "\n" + TIMESTAMP + "\n" + NONCE + "\n" + KEYID + "\n" + SHA256(BODY)

Допустимое расхождение часов — 60 секунд. Повтор того же nonce в пределах окна отклоняется.

signature = hex(hmac_sha256(secret,
  "POST\n/v1/orders\n1789900000\n7b12…\nacme-2026-01\n" + sha256_hex(body)))

Идемпотентность

Ключ идемпотентности — ваш partner_order_id. Повтор запроса с тем же значением возвращает тот же результат и не создаёт вторую заявку. Идентификатор сделки детерминирован: он вычисляется из пары «мерчант + ваш номер заказа», поэтому одинаков при любом повторе.

Сеть рвётся, ответы теряются — повторяйте запрос с тем же partner_order_id. Это безопасно и не создаст дубль платежа.

Создание заявки

POST/v1/orders

{
  "schema_version": "order.v1",
  "partner_order_id": "ACME-2026-0917-88431",
  "direction": "deposit",
  "amount": { "units": 1250000, "currency": "RUB", "scale": 2 },
  "method": "BT",
  "bank_hint": "sber",
  "payer_ref": "opaque-merchant-side-id",
  "callback_url": "https://acme.example/cb/payments",
  "sync_deadline_ms": 3000,
  "ttl_sec": 1200,
  "risk": { "ip": "203.0.113.7", "device_id": "d-88f1", "score": 0.12 }
}
ПолеОбязательноеОписание
partner_order_idдаваш номер заказа, он же ключ идемпотентности
directionдаdeposit — приём средств
amountдасумма в минимальных единицах, валюта и масштаб
methodдаспособ оплаты из выданного вам списка
callback_urlнетадрес для вебхуков; по умолчанию — адрес из настроек
ttl_secнетсколько заявка ждёт оплату
sync_deadline_msнетсколько ждать реквизит в синхронном ответе
bank_hint, payer_ref, riskнетподсказка банка, ваш идентификатор плательщика, данные для антифрода

Синхронный ответ

Код 200 — реквизит выдан сразу:

{
  "deal_id": "0f5a2b6e-…",
  "accepted": true,
  "async": false,
  "amount": { "units": 1250000, "currency": "RUB", "scale": 2 },
  "requisite": {
    "requisite_id": "rq-8842",
    "method": "BT",
    "kind": "card",
    "value": "2200 7708 1234 5678",
    "holder": "IVAN I.",
    "bank": "sber"
  },
  "expires_at": "2026-09-20T12:31:00Z"
}
Реквизит покидает систему ровно один раз — в этом ответе либо в событии order.allocated. Показывайте плательщику именно ту сумму, что вернулась в amount.

Асинхронная выдача

Код 202 означает, что реквизит подбирается и придёт вебхуком order.allocated. В ответе будет "async": true и deal_id, по которому вы свяжете событие со своим заказом.

Коды отказа

Отказ приходит с кодом и коротким описанием. Внутренняя причина наружу не раскрывается.

{ "code": "NO_REQUISITE", "message": "no requisite available" }
КодЧто делать
NO_REQUISITEсвободных реквизитов нет — повторить позже или предложить другой метод
AMOUNT_LIMITсумма вне разрешённого диапазона
RATE_LIMITEDслишком часто — снизить темп, повторить с задержкой
IDEMPOTENCY_KEY_REUSEDтот же номер заказа с другими параметрами
UNAUTHORIZEDподпись не сошлась или ключ отозван
BAD_REQUESTтело не прошло проверку
DEGRADED, INTERNALвременная деградация — повторить с задержкой
INDETERMINATEрезультат неизвестен — повторить тот же запрос с тем же partner_order_id

Вебхуки

События приходят POST-запросом на ваш callback_url, подписанные тем же способом, что и запросы к нам. Проверяйте подпись до обработки.

{
  "event": "order.paid",
  "event_id": "ev-01J8…",
  "deal_id": "0f5a2b6e-…",
  "amount": { "units": 1250000, "currency": "RUB", "scale": 2 },
  "paid_amount": { "units": 1250000, "currency": "RUB", "scale": 2 },
  "occurred_at": "2026-09-20T12:22:41Z"
}

Отвечайте 2xx — иначе событие будет повторено.

Список событий

СобытиеСмысл
order.allocatedреквизит подобран (при асинхронной выдаче)
order.paidоплата подтверждена полностью
order.partially_paidпришла меньшая сумма
order.overpaidпришла большая сумма
order.expiredсрок заявки истёк без оплаты
order.cancelledзаявка отменена
order.disputedоткрыт спор по сделке
order.forwardedзаявка передана другому обработчику

Повторы и дедупликация

Одно и то же событие может прийти несколько раз — это нормальное поведение доставки. Дедуплицируйте по event_id: обработали один раз, дальше отвечайте 200 без повторной обработки. Порядок событий не гарантирован, ориентируйтесь на occurred_at и текущее состояние сделки.

Формат денег

Сумма — это тройка: целое число, валюта и масштаб. {"units": 1250000, "currency": "RUB", "scale": 2} — это 12 500,00 ₽. Не приводите суммы к числам с плавающей точкой ни на одном шаге.

Методы оплаты

КодЧто это
BTперевод по реквизиту: карта, телефон или счёт
FARMперевод на счёт из выделенного пула

Точный список доступных вам методов и банков выдаётся при подключении и виден в кабинете.

Чек-лист подключения

ШагЧто сделать
1Получить адрес, идентификатор ключа и секрет
2Реализовать подпись и проверить её на тестовом запросе
3Создать заявку и показать плательщику реквизит и точную сумму
4Принять вебхуки, проверять подпись и дедуплицировать по event_id
5Повторять неуспешные запросы с тем же partner_order_id
6Сверять обороты в кабинете и по выгрузке

Вопросы по интеграции — поддержка в Telegram или [email protected].