API приёма платежей
Один метод создаёт заявку, дальше всё приходит вебхуками. Адрес, ключи и список доступных методов выдаются при подключении — они индивидуальны для каждого партнёра.
Подпись запросов
Каждый запрос подписывается ключом, выданным при подключении. Подпись покрывает метод, путь, метку времени, одноразовое значение, идентификатор ключа и хеш тела.
| Заголовок | Значение |
|---|---|
X-Payment-Key | идентификатор ключа, например acme-2026-01 |
X-Payment-Timestamp | время запроса в секундах Unix |
X-Payment-Nonce | одноразовое значение, уникальное в пределах окна |
X-Payment-Signature | HMAC-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].
