Payment API · v1
Accept SBP and card payments through one API¶
You create a payment. The API issues the transfer requisites, watches for the money and sends you a signed callback when it arrives.
Integration in five steps¶
- Project and tokenCreate a project in the cabinet and issue an API token.
- Signing keyGenerate an Ed25519 key and upload the public part to the cabinet.
- CallbackSet a notification URL and issue a callback signing secret.
- PaymentSend a signed
POST /api/v1/paymentsand show the requisites to the payer. - ResultReceive the callback, verify its signature and mark the order as paid.
- Your server → API
POST /api/v1/payments, Ed25519 signature - API ⇢ Your server
201:status=processing, requisites, recipient and bank - Your server → PayerYou show the requisites, amount and deadline
- PayerTransfers via SBP or to the card in their bank app
- API → Your serverCallback
status=completed, HMAC-SHA256 signature - Your server ⇢ APIYou reply
2xx
Where to go next¶
-
Payment request, what to show the payer, statuses, polling and edge cases.
-
Transfer to a card: how it differs from SBP and what to show the payer.
-
RFC 9421 and Ed25519: ready-made functions and a shared test vector.
-
Result notifications and HMAC signature verification.
-
Every status, error code and when to retry.
-
llms.txt, Markdown pages and the docs MCP server.
Environments¶
Addresses in these docs are written as placeholders; substitute your own values:
{{base_url}}is the API address issued to you when you are connected. The sandbox and production each have their own. Request examples put{{base_url}}before the path:POST {{base_url}}/api/v1/payments.{{cabinet_url}}is the merchant cabinet address. You receive it together with your access.
| Environment | API address | Cabinet | Token prefix |
|---|---|---|---|
| Sandbox | sandbox {{base_url}} |
sandbox {{cabinet_url}} |
nl_test_ |
| Production | production {{base_url}} |
production {{cabinet_url}} |
nl_live_ |
Keep {{base_url}} in your app configuration, not in code: going live then changes one
setting.
The sandbox behaves like production: same signing, limits and errors. The only difference is that no money moves. See Sandbox.
General API conventions¶
- Format. Requests and responses are UTF-8 JSON. Parsing is strict: an unknown field
or trailing data after the object returns
400 bad_request. - Access. Every request carries
Authorization: Bearer <project token>. - Signature. Every write request is signed with an Ed25519 key per RFC 9421. Payments cannot be created without a signature, neither in the sandbox nor in production.
- Amounts.
amountis in major currency units:3400or"3400.50"roubles. USDT amounts inmerchant_informationare decimal strings:"34.0000"; the ratecourseand feerateare numbers with two decimals:100.00. - Time. All timestamps are RFC 3339 in UTC, for example
2026-09-28T12:00:00Z. - Errors. The error body is
{"error":"<code>"}. See Statuses and errors for the list. - Tracing. The
X-Request-IDrequest header is echoed in the response. Log it: support finds your request by it.
API methods¶
| Method | What it does | Signature |
|---|---|---|
POST /api/v1/payments |
Creates a pay-in | always |
GET /api/v1/payments/{id} |
Returns a payment by id |
if the project policy requires it |
GET /api/v1/project |
Shows the project and token scopes | if the project policy requires it |
Field-level details are in the API reference.