Skip to content

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

  1. Get the recipient bank's bank_id from the general list of banks or from the list of banks by phone number.
  2. If needed, call the payout feasibility check and wait for the result via the check status method.
  3. Generate a unique transaction, sign the exact request body, and send the payout.
  4. Poll the operation status by transaction until you receive completed or canceled.

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

POST https://api.pay.kvell.group/v1/orders/payout/sbp
POST https://api.pay.stage.kvell.group/v1/orders/payout/sbp

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

{
  "phone": "79991234567",
  "fio": "Иванов Иван Иванович",
  "bank_id": "100000000008",
  "amount": 15000,
  "transaction": "payout-20260806-0001",
  "description": "Payout under contract 42",
  "nspk_id": "<nspk-id>",
  "request_id": "<request-id>"
}

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.

Example 200 response (OK)
{
  "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.
Example 400 response (Bad Request)
{
  "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.
Example 403 response (Forbidden)
{
  "errors": [
    {
      "code": 20037,
      "message": "Access 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. 20037 in the example.
errors[].message string Description of the reason access was denied.
Example 404 response (Not Found)
{
  "errors": [
    {
      "code": 20006,
      "message": "Shop not found"
    }
  ]
}

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.

Example 422 response (Unprocessable Entity)
{
  "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.
Example 5XX response (Internal Server 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

  1. Do not mark the payout as successful or rejected based solely on a technical error.
  2. Store the payout on your side in a "processing" state.
  3. Request the transaction status using the original transaction value.
  4. If the transaction is found, keep checking it until you get a final status.
  5. 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:

{
  "status": "wait_confirm",
  "transaction": "payout-20260806-0001"
}

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

  1. Get the OTP code from the user.
  2. Pass transaction and the OTP code to the payout confirmation method.
  3. After confirmation, get the final status.