Making a payout via SBP
Creates a payout to an individual by phone number and the selected recipient bank.
Payout in another currency
If the payout amount is originally in a currency other than the shop's currency,
use «SBP payout with conversion» — the same method with an
additional currency field that converts the amount before the payout.
Integration flow
- Get the recipient bank's
bank_idfrom the general list of banks or from the list of banks by phone number. - If needed, call the payout feasibility check and wait for the result via the check status method.
- Generate a unique
transaction, sign the exact request body, and send the payout. - Poll the operation status by
transactionuntil you receivecompletedorcanceled.
When a preliminary check is needed
A check lets you make sure in advance that the bank can accept the payout, and lets you obtain nspk_id and
request_id. For payouts via Alfa-Bank, pass the obtained nspk_id if a check was performed before creating
the payout.
URL
Request
Headers
| Name | Type | Required | Description |
|---|---|---|---|
X-Api-Key |
string | Yes | Shop identifier |
X-Signature |
string | Yes | Signature of the request body |
Building the signature
The request must be signed with an RSA/SHA-256 electronic signature. Pass the result in the X-Signature
header.
The step-by-step algorithm, key requirements, examples for Python, PHP and OpenSSL, and troubleshooting for
error 20002 are given in the general section «Building a signature for payouts».
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
phone |
string | Yes | Recipient's phone number: 11 digits, without +, spaces, or separators. Example: 79991234567. |
fio |
string | Yes | Recipient's full name. For banks that don't accept Ё/ё, use the agreed-upon variant with Е/е. |
bank_id |
string | Yes | Bank identifier from the list of banks or the list of banks by phone. |
amount |
integer | Yes | Amount in kopecks. For example, 15000 is 150 RUB. |
transaction |
string | Yes | Unique operation identifier in the merchant's system. |
description |
string | Yes | Purpose of the payout, no more than 110 characters. |
fio_check |
boolean | No | true — check that the passed full name matches the full name received from NSPK. |
bank_bic |
string | Conditional | BIC from the response of the bank list method. Whether it's required depends on the configured acquiring bank. |
nspk_id |
string | Conditional | Payment link obtained at the stage of calling the payout feasibility check status method. If not included in the request, the link will be obtained via a separate request to NSPK as part of processing the payment. Required for working via Alfa-Bank if payout feasibility check methods were called beforehand. |
request_id |
string | Conditional | Identifier of the payout feasibility check request. Whether it's required depends on the configured acquiring bank. |
customer |
string | No | Customer's email or phone number in the merchant's system. |
extra_data |
object | No | Additional merchant data. |
fiscal_data |
object | No | Data for receipt fiscalization under 54-FZ. |
Conditional parameters
Whether request_id and bank_bic are required depends on the acquiring bank through which the shop's
payouts are configured. If the integration scheme is unknown, check with your KVELL manager before going live
in Production.
Example
Response
Select the HTTP code to see the example, response parameters, and recommended actions.
If no HTTP response is received
Handle a timeout or connection drop the same way as a 5XX response: the result of the operation is unknown,
so first check the status by the original transaction. Do not create a new payout with a different
identifier.
{
"id": "3b3c19f4-c680-4f5d-bf2e-c0835439cf12",
"status": "processing",
"transaction": "payout-20260806-0001",
"amount": 15000,
"commission": 150,
"description": "Payout under contract 42",
"additional_data": null,
"error_code": null,
"error_message": null,
"created_at": "2026-08-06T09:15:27.231000+00:00"
}
Response parameters
| Parameter | Type | Description |
|---|---|---|
id |
string | Payout identifier in KVELL. |
status |
string | Payout status. See possible values in «Payout statuses». |
transaction |
string | Operation identifier passed by the merchant in the request. |
amount |
integer | Payout amount in kopecks. |
commission |
integer | Commission in kopecks. |
description |
string | null | Purpose of the payout. |
additional_data |
object | null | Additional operation data, if generated during processing. |
error_code |
string | null | Cancellation reason code. See possible values in «Transaction error codes». null for an incomplete payout. |
error_message |
string | null | Description of the cancellation reason. null for an incomplete payout. |
created_at |
string | Payout creation date and time in ISO 8601 format. |
{
"errors": [
{
"code": 20019,
"message": "Shop payout limit exceeded"
}
]
}
Response parameters
| Parameter | Type | Description |
|---|---|---|
errors |
array | List of errors. Codes and handling recommendations are given in «HTTP response errors». |
errors[].code |
integer | Error code. 20019 in the example. |
errors[].message |
string | Description of why the request was rejected. |
Response parameters
| Parameter | Type | Description |
|---|---|---|
errors |
array | List of errors. Codes and handling recommendations are given in «HTTP response errors». |
errors[].code |
integer | Error code. 20037 in the example. |
errors[].message |
string | Description of the reason access was denied. |
Response parameters
| Parameter | Type | Description |
|---|---|---|
errors |
array | List of errors. Codes and handling recommendations are given in «HTTP response errors». |
errors[].code |
integer | Error code. 20006 in the example. |
errors[].message |
string | Description of why the resource was not found. |
What this response means
A shop with the passed X-Api-Key was not found in the selected environment. The payout was not created.
{
"errors": [
{
"code": 20098,
"message": "amount: Field required"
}
]
}
Response parameters
| Parameter | Type | Description |
|---|---|---|
errors |
array | List of validation errors. Codes and handling recommendations are given in «HTTP response errors». |
errors[].code |
integer | Error code. 20098 for a field error. |
errors[].message |
string | Reason for the validation error. |
{
"errors": [
{
"code": 20000,
"message": "Unknown error"
}
]
}
Response parameters
| Parameter | Type | Description |
|---|---|---|
errors |
array | List of errors. Codes and handling recommendations are given in «HTTP response errors». |
errors[].code |
integer | Error code. 20000 for an unknown error. |
errors[].message |
string | Description of the technical error. |
5XX, timeout, and connection drop
In all these cases, the result of the request is considered undefined: the payout may have been created even if the client did not receive a response. Keep the transaction in your system in a "processing" state until you receive a confirmed result from KVELL.
This scenario can occur due to a network failure, connection drop, timeout, or a technical error on the server or client side.
Unified handling algorithm
- Do not mark the payout as successful or rejected based solely on a technical error.
- Store the payout on your side in a "processing" state.
- Request the transaction status using the original
transactionvalue. - If the transaction is found, keep checking it until you get a final status.
- If status requests keep failing, contact support and provide
transaction.
Do not create a duplicate payout
Do not resend the payout with a new transaction until the result of the original operation has been
determined.
Payout statuses
| Status | Final | What to do |
|---|---|---|
new |
No | Request the transaction status. |
processing |
No | Request the transaction status. Do not create a new payout. |
completed |
Yes | The payout was completed. |
canceled |
Yes | The payout was rejected. |
The full reference of common operation statuses is given in «Transaction statuses».
OTP confirmation
Only used for shops with OTP enabled
Confirming a payout with a one-time code is not part of the main flow. The option is enabled individually in the shop's settings. If it is not enabled for you, you can skip this section.
With OTP enabled, instead of the created payout object the API returns:
Response parameters
| Parameter | Type | Description |
|---|---|---|
status |
string | Status wait_confirm: the payout is awaiting OTP code confirmation. |
transaction |
string | Operation identifier that must be passed to the confirmation method. |
What this response means
The request was accepted, but the payout is awaiting confirmation and has not yet moved to bank processing.
That's why the response has no id, amount, commission, or created_at.
What to do next
- Get the OTP code from the user.
- Pass
transactionand the OTP code to the payout confirmation method. - After confirmation, get the final status.