Accepting payments over SBP: how it works and what to allow for in the integration
· 6 min read
How an SBP QR payment goes through, why confirmation arrives with a delay, how it differs from cards, and what all of that means for your integration.
Russia’s Faster Payments System — SBP — behaves noticeably differently from card payments, and the differences are not cosmetic: they change how your integration has to be built. Let’s walk through what happens after the payer sees the QR code.
SBP is usually the first method a project switches on, and especially often by those whose a bank turned down your acquiring application: cards need a contract with a bank, while here a gateway is enough.
How a payment goes through
- You create a payment and receive the address of the checkout page.
- The payer opens it and picks SBP.
- An NSPK QR code is generated. On a phone, a link into the banking app takes the place of scanning.
- The payer confirms the transfer inside their own banking app — not on your site and not on our page.
- The money moves from the payer’s account to the recipient’s account directly, bypassing the card infrastructure.
- You receive a webhook with the final status.
Step 4 is the crux. The payer leaves for another application, and at that moment your site knows nothing about them.
How this differs from cards
No 3-D Secure. The confirmation is the fact that the payer pressed a button in a banking app they are already signed into. There is no separate SMS code and no separate redirect to a bank page.
Practically no disputes. SBP is a transfer, not a card operation, and there is no chargeback mechanism here in the usual sense. For a seller that is the main economic difference: a refund is possible, but only on your initiative.
The money arrives faster. The transfer settles almost instantly, whereas a card operation is held first and captured later.
No callback from the payer to you. And this is what changes the technical side.
Why confirmation does not arrive immediately
A card payment has a browser return: the payer passes 3-D Secure and gets redirected back — there is an event to hook onto. In SBP no such event exists at all. The payer confirmed the transfer in a banking app, and there is physically nobody to tell your site about it.
The only confirmation channel, therefore, is the gateway polling the processor. Two practical consequences follow.
First: the status changes with a delay. Usually seconds, but the integration has to be ready for it and must not read the absence of a confirmation two seconds in as a failure.
Second: a payment must not be expired blindly on a timeout. If a payment is already being
processed, killing it on expires_at without a final poll is not allowed — otherwise a late payment
the processor has already confirmed is lost. The gateway handles this, but the same rule applies on
your side: do not close an order as unpaid merely because half an hour has passed.
What this means for the integration
Do not rely on return_url. The payer coming back to your site is not proof of payment. They may
close the tab right after confirming in the bank, and the money will still arrive. The confirmation is
the webhook and nothing else.
Do not build polling instead of webhooks. The payment status request exists to recover state when a notification did not arrive, not as the primary channel. Polling every order once a second creates load and still loses to webhooks on latency.
Make the handler idempotent. The notification about the move to succeeded may arrive twice —
that is normal behaviour on a retry after a network timeout.
Verify the signature. Since payment confirmation arrives over the network rather than from the payer, it is the sole grounds for shipping the goods — which means forging it is a way to get goods for free. A walkthrough of how to verify a webhook signature is a separate article.
Read expires_at from the response instead of hardcoding a constant. SBP has a 30-minute window,
but other methods differ: crypto, for instance, has an hour, because the transfer has to be confirmed
by the network. The value comes back in the create-payment response.
takemypay works the same way: HMAC-SHA256 over the body, replay protection, retries until 2xx on a fixed schedule. Your key starts in test mode, so the whole integration can be built against simulated payments while activation is pending.
Read the docs →When SBP is not the right fit
The payer needs a Russian bank connected to SBP and its app to hand. For an audience outside Russia this does not work — there you need cards or crypto. This is also why the payment method is not set in the create request: you create a payment, and the payer picks what they can actually pay with.
What the create request looks like is in Creating a payment.
Frequently asked questions
Does the payer need a QR code when paying from a phone?
No. On a phone, scanning is replaced by a link that opens the banking app with the payment already filled in. The QR matters when the checkout page is on a desktop screen and the payment happens on a phone.
How quickly does the money arrive over SBP?
The transfer itself settles almost instantly — unlike a card operation, which is held first. The status on your side, however, does not change in the same instant: confirmation comes from polling the processor, usually within seconds.
Are there disputes over SBP?
Not in the usual card sense: SBP is a transfer, not a card operation, and no chargeback mechanism exists here. A refund is possible, but only on your initiative. For a seller that is the main economic difference from cards.
Can the payer’s return to return_url be treated as confirmation?
No. The payer may close the tab right after confirming in the banking app and the money will still arrive; and the other way round — they may come back having confirmed nothing. The only proof of payment is the webhook.
What should I do if a webhook never arrived?
Request the payment status over the API. That is a state-recovery channel, not a replacement for notifications: polling every order once a second creates load and still loses to webhooks on latency.
How long does an SBP payment live?
The window is 30 minutes, but hardcoding it is a mistake: other methods differ — crypto, for example,
has an hour. The value arrives as expires_at in the create-payment response. And a payment the
processor has already started must not be closed on a timeout without a final poll, or a late payment
is lost.
takemypay is a payment gateway for the merchant account you never got. SBP, Mir cards, Visa/Mastercard and USDT behind one API, a 18% fee, payouts in USDT TRC20 from $100. Sign up with a magic link and get a test key immediately. Questions — ask support.
Get an API key →Read next
· 7min read
Fee, conversion and payouts: what accepting payments through a gateway costs
How the amount on your balance follows from the amount paid: an 18% fee on gross, who pays it, conversion at the central bank rate plus a markup, the payout threshold and the transfer fee.
· 6min read
The bank refused your acquiring application: why it happens and what to do next
The reasons acquirers turn down online payment applications, and the working ways to keep taking money while the conversation with the bank is still going.
· 6min read
How to verify a webhook signature: HMAC-SHA256 in practice
Why payment notifications are signed, how an HMAC-SHA256 signature is built, the four mistakes that stop it from matching, and defence against replays.