Making a payment via SBP
This method creates a payment via the Faster Payments System (SBP) and returns a payment link. The amount, payment purpose, and additional data are taken from a previously created payment session. The payment result is later determined via the transaction status or a callback.
Integration flow
- Create a payment session with a unique
transaction, amount, and payment description. - Generate a signature from
X-Api-Key,transaction, andsecret_key, then send the request to create the payment. - Upon receiving
200, openform_urlin the browser, including on a mobile device. To pay from another device, generate a QR code from theform_urlvalue. - Determine the payment result via the transaction status or use a callback.
URL
Request
Headers
| Name | Type | Required | Description |
|---|---|---|---|
X-Api-Key |
string | Yes | Shop identifier. |
X-Signature |
string | Yes | Request signature. |
Building the signature
Concatenate X-Api-Key, transaction, and secret_key with no separators, compute the SHA-256 hash of the
resulting UTF-8 string, and pass the lowercase hex hash in the X-Signature header.
secret_key can be found in the shop's settings. Do not add spaces, line breaks, or other separators.
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
transaction |
string | Yes | Unique transaction identifier in the merchant's system. Must match the transaction from the payment session. |
customer |
string | null | No | Payer identifier — an email or phone number. |
Example
Response
Choose an HTTP code to see an example, response parameters, and recommended actions.
Response parameters
| Parameter | Type | Description |
|---|---|---|
form_url |
string | SBP link for opening a banking app or generating a QR code. |
What to do next
- Open
form_urlin the browser, including on a mobile device. To pay from another device, generate a QR code from the full, unmodifiedform_urlvalue. - After the payer completes the action, obtain the transaction status or handle the callback.
{
"errors": [
{
"code": 20007,
"message": "The transaction has already been made"
}
]
}
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 — 20007. |
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. For access denial — 20037. |
errors[].message |
string | Description of the reason access was denied. |
What this response means
The shop is inactive or is denied access to the API. The session was not created.
What to do next
Check the shop's status and retry the request only after access is restored.
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 a shop not found — 20006. |
errors[].message |
string | Description of why the shop was not found. |
What this response means
The shop for the passed X-Api-Key was not found in the selected environment. The payment was not created.
What to do next
Check the X-Api-Key and the Stage/Production environment.
{
"errors": [
{
"code": 20098,
"message": "transaction: 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 | Validation error code. For a field error — 20098. |
errors[].message |
string | Field name and the reason for the validation error. |
What this response means
The request headers or body failed validation of required fields and format. The payment was not created.
What to do next
Fix the fields listed in errors[].message, regenerate the signature, and retry the request with the same transaction.
{
"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 payment may have been created even if the client did not receive a response. Keep the operation in your system in a "processing" state until you receive a confirmed result from KVELL.
Unified handling algorithm
- Do not create a new payment and do not change
transaction. - Request the transaction status using the original
transaction. - If the transaction is found, poll it every 2 minutes until a final status is reached, or wait for the callback.
- If status requests keep failing with a technical error, contact support and provide the
transaction.
Binding an account
Requires recurring payments via SBP to be enabled
Account binding and subsequent debits are only available for transactions with recurring payments via SBP enabled. Check availability with your KVELL account manager.
The decision to bind the account is made by the payer in the bank's interface: they can confirm or decline the binding, and later unbind the account themselves and prohibit further debits without confirmation.
Binding without a payment
When creating a payment session, pass amount: 0, then call this method and
redirect the user to form_url. In parent_transaction for subsequent debits, pass the transaction of the
binding operation. After successful binding, you can use the recurring payment method to
debit funds without confirmation and without the customer present.
Binding with a payment
When creating a payment session, pass amount greater than 0, then call this method and
redirect the user to form_url. In parent_transaction for subsequent debits, pass the transaction of the
binding operation. After successful binding, you can use the recurring payment method to
debit funds without confirmation and without the customer present.