Skip to content

SBP payout with currency conversion

A payout to an individual via SBP with the option to specify the amount in a currency other than the shop's currency. If currency is passed, the amount is automatically converted into the shop's currency before being sent to the bank — in logic and request parameters, this method is identical to «Making a payout via SBP», plus a conversion step.

When to use this method instead of the base one

Use this method if the payout amount is originally in a currency other than the shop's currency (for example, the shop settles in dollars, but payouts go out in rubles). If currency is not passed, the method behaves identically to the base SBP payout method — no conversion is performed.

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 with conversion and wait for the result via the check status method.
  3. Generate a unique transaction. If the payout amount is in a currency other than the shop's currency, pass its numeric ISO 4217 code in the currency field — the amount will be automatically recalculated before the payout. See «Currency codes».
  4. Sign the exact request body (including the currency field, if passed) and send the payout.
  5. 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/v2/orders/payout/sbp
POST https://api.pay.stage.kvell.group/v2/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. The exact bytes of the request body being sent are signed, including the currency field, if passed. 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 the minor units of the currency specified in currency (kopecks for rubles, cents for dollars, etc.). If currency is not passed, the amount is in the minor units of the shop's payout profile currency. For example, 15000 is 150.00 in the corresponding currency.
transaction string Yes Unique operation identifier in the merchant's system.
description string Yes Purpose of the payout, no more than 110 characters.
currency string No Numeric ISO 4217 code of the source currency as a string, e.g. "840" for USD. If not passed, amount is assumed to be in the shop's currency — no conversion is performed. See «Currency codes».
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 account manager before launching in Production.

request_id from a preliminary check without currency

If you called the payout feasibility check with conversion and received a request_id, when creating the payout itself you still need to pass amount in the source currency together with the currency field — request_id does not automatically carry over the conversion result.

Example

{
  "phone": "79991234567",
  "fio": "Иванов Иван Иванович",
  "bank_id": "100000000008",
  "amount": 10000,
  "currency": "840",
  "transaction": "payout-20260806-0001",
  "description": "Выплата по договору 42",
  "nspk_id": "<nspk-id>",
  "request_id": "<request-id>"
}
{
  "phone": "79991234567",
  "fio": "Иванов Иван Иванович",
  "bank_id": "100000000008",
  "amount": 15000,
  "transaction": "payout-20260806-0002",
  "description": "Выплата по договору 42"
}

Response

Select the HTTP code to see an example, the response parameters, and recommended actions.

If no HTTP response is received

Handle a timeout or connection loss 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 (OK) response
{
  "id": "3b3c19f4-c680-4f5d-bf2e-c0835439cf12",
  "status": "processing",
  "transaction": "payout-20260806-0001",
  "amount": 853846,
  "commission": 8538,
  "description": "Выплата по договору 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. Possible values are given in «Payout statuses».
transaction string Operation identifier passed by the merchant in the request.
amount integer Payout amount in the minor units of the shop's currency. If currency was passed, this is the conversion result, not the value from the request.
commission integer Commission in the minor units of the shop's currency.
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. Possible values are given 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 Date and time the payout was created, in ISO 8601 format.

The conversion result is not returned in the response

The response does not contain an fx_conversion object — use the amount field to find out the amount actually paid out in the payout profile currency. If you need the rate and intermediate conversion values right before the payout, call «Payout feasibility check with conversion» in advance — it returns an fx_conversion object in the response.

Example 400 (Bad Request) response
{
  "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. In the example — 20019.
errors[].message string Description of why the request was rejected.

The limit is checked already in the payout profile currency

If currency was passed, the shop's payout limit check is performed after conversion — against the final amount in the payout profile currency, not against the amount value from the request.

Example 403 (Forbidden) response
{
  "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. In the example — 20037.
errors[].message string Description of why access was denied.
Example 404 (Not Found) response: shop not found
{
  "errors": [
    {
      "code": 20006,
      "message": "Shop not found"
    }
  ]
}
Example 404 (Not Found) response: payout profile has no currency set
{
  "errors": [
    {
      "code": 20045,
      "message": "The shop's payout profile has no currency set"
    }
  ]
}
Example 404 (Not Found) response: Montra integration not configured
{
  "errors": [
    {
      "code": 20044,
      "message": "The integration with Montra is not configured for the shop"
    }
  ]
}

Response parameters

Parameter Type Description
errors array List of errors. Codes and handling recommendations are given in «HTTP response errors».
errors[].code integer 20006 — shop not found; 20045 — the shop's payout profile has no currency set; 20044 — the integration with the rates provider is not configured.
errors[].message string Description of why the resource was not found.

What this response means

20006 — the shop with the given X-Api-Key was not found in the selected environment, the payout was not created.

20045 and 20044 occur only if currency was passed: the amount cannot be converted, the payout was not created. For 20045, contact KVELL support to set the payout profile currency. For 20044, contact KVELL support to connect the rates provider integration for the shop.

Example 422 (Unprocessable Entity) response
{
  "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. For a field error — 20098.
errors[].message string Reason for the validation error.

Currency field format

currency must consist of 1-3 digits (^\d{1,3}$). Letter currency codes ("USD") are rejected with error 20098.

Example 5XX (Internal Server Error) response
{
  "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. For an unknown error — 20000.
errors[].message string Description of the technical error.

5XX, timeout, and connection loss

In all of 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 loss, 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. Keep the payout in your system 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 the 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 established.

Payout statuses

The full status reference is given in the «Payout statuses» section of the base method — for payouts with currency conversion, they are no different.

Confirmation via OTP

Used only for shops with OTP enabled

Payout confirmation via a one-time code is not part of the main flow. This option is enabled individually in the shop 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 waiting for OTP confirmation.
transaction string Operation identifier that must be passed to the confirmation method.

What this response means

The request has been accepted, but the payout is awaiting confirmation and has not yet moved to bank processing. That's why the response does not contain id, amount, commission, or created_at.

The conversion result is preserved until confirmation

If currency was passed, the conversion result is stored together with the confirmation session and is automatically applied when calling the confirmation method — there is no need to pass currency again.

What to do next

  1. Obtain the OTP code from the user.
  2. Pass transaction and the OTP code to the payout confirmation method (this method is shared for payouts with and without currency conversion; there is no separate v2 confirmation method).
  3. After confirmation, retrieve the final status.