Массовая выплата через СБП
Раздел описывает два метода: создание реестра выплат через СБП и получение его результата. Реестр обрабатывается асинхронно: в ответ на создание возвращается только идентификатор задачи, а результат по каждой выплате запрашивается отдельно.
Сценарий интеграции
- Получите
bank_idбанка-получателя для каждой выплаты из общего списка банков. - Подготовьте список выплат. Для каждой выплаты сформируйте собственный уникальный
transaction. - Подпишите точное тело запроса и отправьте реестр.
- Сохраните
idиз ответа — это идентификатор задачи (task_id), по которому запрашивается результат. - Опрашивайте результат массовой выплаты, пока задача не перейдёт в состояние
SUCCESSилиFAILURE. - Финальный статус каждой выплаты получайте по её
transactionчерез статус транзакции или колбэк.
Ответ 200 не подтверждает создание выплат
Ответ 200 означает только, что реестр сохранён и задача поставлена в очередь. На этом шаге не создаётся
ни одной выплаты и ни одной транзакции. Выплаты создаются в фоне — по одной, последовательно, в порядке
элементов items.
Лимиты и ошибки отдельных выплат
Лимиты магазина проверяются для каждой выплаты отдельно в момент её создания. Ошибка по одной выплате не останавливает обработку реестра: остальные выплаты обрабатываются, а ошибочный элемент попадает в результат задачи с кодом и описанием ошибки.
Магазины с подтверждением выплат по OTP
Реестр не поддерживает подтверждение выплат одноразовым кодом: шага подтверждения для массовой выплаты нет. Если для магазина включён OTP, используйте единичную выплату через СБП и подтверждение выплаты.
Создание реестра
URL
Заголовки
| Название | Тип | Обязательно | Описание |
|---|---|---|---|
X-Api-Key |
string | Да | Идентификатор магазина. |
X-Signature |
string | Да | Подпись тела запроса. |
Формирование подписи
Запрос необходимо подписать электронной подписью RSA/SHA-256. Передайте результат в заголовке X-Signature.
Пошаговый алгоритм, требования к ключам, примеры для Python, PHP и OpenSSL, а также диагностика ошибки 20002
приведены в общем разделе «Формирование подписи для выплат».
Тело запроса
| Параметр | Тип | Обязательно | Описание |
|---|---|---|---|
name |
string | Да | Название реестра в системе мерчанта. Используется для поиска реестра. |
items |
array | Да | Список выплат, минимум один элемент. Структура элемента описана ниже. |
Элемент массива items
| Параметр | Тип | Обязательно | Описание |
|---|---|---|---|
phone |
string | Да | Номер телефона получателя: 11 цифр, без +, пробелов и разделителей. Пример: 79991234567. |
fio |
string | Да | ФИО получателя. Для банков, не принимающих Ё/ё, используйте согласованный вариант с Е/е. |
bank_id |
string | Да | Идентификатор банка из списка банков. |
amount |
integer | Да | Сумма в копейках. Например, 15000 — 150 ₽. |
transaction |
string | Да | Уникальный идентификатор операции в системе мерчанта. |
description |
string | Да | Назначение выплаты, не более 110 символов. |
fio_check |
boolean | Нет | true — проверить совпадение переданного ФИО с ФИО, полученным от НСПК. |
bank_bic |
string | Условно | БИК из ответа метода получения банков. Требование зависит от настроенного банка-эквайера. |
nspk_id |
string | Условно | Платёжная ссылка, полученная при проверке возможности выплаты. Действует не более 180 секунд с момента проверки. |
request_id |
string | Условно | Идентификатор запроса проверки возможности выплаты. Требование зависит от настроенного банка-эквайера. |
customer |
string | Нет | Email или телефон клиента в системе мерчанта. |
extra_data |
object | Нет | Дополнительные данные мерчанта. |
fiscal_data |
object | Нет | Данные для фискализации чека по 54-ФЗ. |
Условные параметры
Необходимость request_id и bank_bic зависит от банка-эквайера, через который настроены выплаты магазина.
Если схема интеграции неизвестна, уточните её у менеджера KVELL до запуска в Production.
Пример
{
"name": "Реестр выплат СБП за 10.08.2026",
"items": [
{
"phone": "79991234567",
"fio": "Иванов Иван Иванович",
"bank_id": "100000000008",
"amount": 15000,
"transaction": "payout-sbp-20260810-0001",
"description": "Выплата по договору 42"
},
{
"phone": "79997654321",
"fio": "Петров Пётр Петрович",
"bank_id": "100000000008",
"amount": 27000,
"transaction": "payout-sbp-20260810-0002",
"description": "Выплата по договору 43"
}
]
}
curl --request POST \
--url 'https://api.pay.stage.kvell.group/v1/orders/payout/sbp/bulk' \
--header 'X-Api-Key: <api-key>' \
--header 'X-Signature: <signature>' \
--header 'Content-Type: application/json' \
--data '{"name":"Реестр выплат СБП за 10.08.2026","items":[{"phone":"79991234567","fio":"Иванов Иван Иванович","bank_id":"100000000008","amount":15000,"transaction":"payout-sbp-20260810-0001","description":"Выплата по договору 42"}]}'
Ответ
Выберите HTTP-код, чтобы посмотреть пример, параметры ответа и рекомендуемые действия.
Если HTTP-ответ не получен
Таймаут или разрыв соединения обрабатывайте так же, как ответ 5XX: неизвестно, была ли задача поставлена
в очередь. Не отправляйте реестр повторно, пока не убедитесь, что выплаты по его transaction не создавались.
Параметры ответа
| Параметр | Тип | Описание |
|---|---|---|
id |
string | Идентификатор задачи (task_id). Передаётся в метод получения результата. |
status |
string | Состояние задачи в момент постановки в очередь. Значения приведены в разделе «Состояния задачи». |
Что означает ответ
Реестр сохранён, задача поставлена в очередь. Выплаты ещё не созданы, транзакций в системе KVELL нет.
Что делать дальше
- Сохраните
idна своей стороне: без него результат реестра получить нельзя. - Опрашивайте результат массовой выплаты до состояния
SUCCESSилиFAILURE.
{
"errors": [
{
"code": 20003,
"message": "Payout профиль не привязан к магазину"
}
]
}
Параметры ответа
| Параметр | Тип | Описание |
|---|---|---|
errors |
array | Список ошибок. Коды и рекомендации по обработке приведены в разделе «Ошибки HTTP-ответов». |
∟ code |
integer | Код ошибки. |
∟ message |
string | Описание причины отклонения запроса. |
Параметры ответа
| Параметр | Тип | Описание |
|---|---|---|
errors |
array | Список ошибок. Коды и рекомендации по обработке приведены в разделе «Ошибки HTTP-ответов». |
∟ code |
integer | Код ошибки. |
∟ message |
string | Описание причины, по которой ресурс не найден. |
{
"errors": [
{
"code": 20098,
"message": "items.0.phone: Field required"
}
]
}
Параметры ответа
| Параметр | Тип | Описание |
|---|---|---|
errors |
array | Список ошибок валидации. Коды и рекомендации по обработке приведены в разделе «Ошибки HTTP-ответов». |
∟ code |
integer | Код ошибки. |
∟ message |
string | Причина ошибки валидации с указанием поля. |
Что означает ответ
Реестр не прошёл проверку формата: достаточно одного некорректного элемента items, чтобы весь запрос
был отклонён. Реестр не сохранён, выплаты не создавались.
Что делать дальше
- Исправьте поля, перечисленные в
errors[].message, и убедитесь, чтоitemsсодержит минимум один элемент. - Сформируйте новую подпись по исправленному телу и отправьте реестр заново с теми же
transaction.
{
"errors": [
{
"code": 20000,
"message": "Неизвестная ошибка"
}
]
}
Параметры ответа
| Параметр | Тип | Описание |
|---|---|---|
errors |
array | Список ошибок. Коды и рекомендации по обработке приведены в разделе «Ошибки HTTP-ответов». |
∟ code |
integer | Код ошибки. |
∟ message |
string | Описание технической ошибки. |
5XX, таймаут и разрыв соединения
Результат запроса считается неопределённым: задача могла быть поставлена в очередь, даже если клиент не получил ответ. Повторная отправка того же реестра без проверки приведёт к дублирующим попыткам выплат.
Единый алгоритм обработки
- Не считайте реестр ни принятым, ни отклонённым только на основании технической ошибки.
- Если
idзадачи получен не был, проверьте статус транзакции поtransactionиз реестра. - Если ни одна транзакция не найдена, отправьте реестр повторно с теми же
transaction. - Если транзакции найдены, не отправляйте реестр заново: дождитесь их финальных статусов.
- Если запросы продолжают завершаться ошибкой, обратитесь в поддержку и передайте название реестра и время запроса.
Не создавайте дублирующие выплаты
Не меняйте transaction при повторной отправке реестра. Выплата с уже использованным transaction
отклоняется с кодом 20007, и это защищает от двойной выплаты.
Получение результата
Метод возвращает состояние задачи обработки реестра и, после её завершения, результат по каждой выплате. Метод не изменяет состояние операций.
Интервал опроса
Рекомендуемый интервал между запросами — не менее 1 минуты. Реестр обрабатывается последовательно, поэтому время обработки растёт пропорционально количеству выплат.
Состояние SUCCESS относится к задаче, а не к выплатам
SUCCESS означает, что реестр обработан до конца. Отдельные выплаты внутри реестра могли завершиться ошибкой
или ещё находиться в обработке на стороне банка.
URL
Path-параметры
| Параметр | Тип | Обязательно | Описание |
|---|---|---|---|
task_id |
string | Да | Идентификатор задачи — поле id из ответа массовой выплаты. |
Заголовки
| Название | Тип | Обязательно | Описание |
|---|---|---|---|
X-Api-Key |
string | Да | Идентификатор магазина. |
X-Signature |
string | Да | Подпись запроса. |
Формирование подписи
Объедините X-Api-Key, task_id и secret_key без разделителей, вычислите SHA-256 от полученной строки
в кодировке UTF-8 и передайте hex-результат в нижнем регистре в заголовке X-Signature.
secret_key находится в настройках магазина. Порядок значений изменять нельзя. Запрашивайте результат тем же
X-Api-Key, которым создавался реестр.
Пример
curl --request GET \
--url 'https://api.pay.stage.kvell.group/v1/orders/payout/sbp/bulk/1d5b2f5a-8f0a-4c27-9c53-2f7a8a1b4d10' \
--header 'X-Api-Key: <api-key>' \
--header 'X-Signature: <signature>'
Ответ
Выберите HTTP-код, чтобы посмотреть пример, параметры ответа и рекомендуемые действия.
Если HTTP-ответ не получен
Метод только читает состояние задачи и не меняет состояние выплат. При 5XX, таймауте или разрыве соединения
безопасно повторите тот же запрос с тем же task_id.
{
"state": "SUCCESS",
"response": [
{
"id": "3b3c19f4-c680-4f5d-bf2e-c0835439cf12",
"status": "processing",
"transaction": "payout-sbp-20260810-0001",
"amount": 15000,
"commission": 150,
"description": "Выплата по договору 42",
"additional_data": null,
"error_code": null,
"error_message": null,
"created_at": "2026-08-10T09:15:27.231000+00:00"
},
{
"transaction": "payout-sbp-20260810-0002",
"code": "20019",
"message": "Превышен лимит выплат по магазину"
}
]
}
Параметры ответа
| Параметр | Тип | Описание |
|---|---|---|
state |
string | Состояние задачи. Возможные значения приведены в разделе «Состояния задачи». |
response |
array | null | Результаты по выплатам. Заполняется только при state = SUCCESS, в остальных случаях — null. |
∟ id |
string | Идентификатор выплаты в KVELL. Отсутствует в элементе с ошибкой. |
∟ status |
string | Статус выплаты. Возможные значения приведены в разделе «Статусы выплаты». |
∟ transaction |
string | Идентификатор операции в системе мерчанта. Возвращается и в успешном элементе, и в элементе с ошибкой. |
∟ amount |
integer | Сумма выплаты в копейках. |
∟ commission |
integer | Комиссия в копейках. |
∟ description |
string | null | Назначение выплаты. Может включать префикс, настроенный для магазина. |
∟ additional_data |
object | null | Дополнительные данные операции, если они сформированы при обработке. |
∟ error_code |
string | null | Код причины отмены. Возможные значения приведены в разделе «Коды ошибок транзакции». Для незавершённой выплаты возвращается null. |
∟ error_message |
string | null | Описание причины отмены. Для незавершённой выплаты возвращается null. |
∟ created_at |
string | Дата и время создания выплаты в формате ISO 8601. |
∟ code |
string | Код ошибки выплаты. Присутствует только в элементе с ошибкой. Коды приведены в справочнике «Ошибки HTTP-ответов». |
∟ message |
string | Описание ошибки выплаты. Присутствует только в элементе с ошибкой. |
Что означает ответ
Ответ 200 возвращается на любом состоянии задачи, в том числе пока реестр ещё не обработан.
Порядок элементов response совпадает с порядком items в запросе реестра. Сопоставляйте элементы
по transaction, а не по индексу.
Что делать дальше
- Если
stateне равенSUCCESSилиFAILURE, повторите запрос позднее. - При
SUCCESSразберитеresponse: элементы сid— созданные выплаты, элементы сcodeиmessage— выплаты, которые создать не удалось. - Выплаты из ошибочных элементов не созданы. Устраните причину и отправьте их новым реестром
с теми же
transaction. - Для созданных выплат дождитесь финального статуса
completedилиcanceled.
Параметры ответа
| Параметр | Тип | Описание |
|---|---|---|
errors |
array | Список ошибок. Коды и рекомендации по обработке приведены в разделе «Ошибки HTTP-ответов». |
∟ code |
integer | Код ошибки. |
∟ message |
string | Описание причины отклонения запроса. |
Параметры ответа
| Параметр | Тип | Описание |
|---|---|---|
errors |
array | Список ошибок. Коды и рекомендации по обработке приведены в разделе «Ошибки HTTP-ответов». |
∟ code |
integer | Код ошибки. |
∟ message |
string | Описание причины, по которой ресурс не найден. |
Что означает ответ
Не найден магазин с переданным X-Api-Key. Неизвестный или устаревший task_id ответом 404
не возвращается — см. раздел «Состояния задачи».
{
"errors": [
{
"code": 20000,
"message": "Неизвестная ошибка"
}
]
}
Параметры ответа
| Параметр | Тип | Описание |
|---|---|---|
errors |
array | Список ошибок. Коды и рекомендации по обработке приведены в разделе «Ошибки HTTP-ответов». |
∟ code |
integer | Код ошибки. |
∟ message |
string | Описание технической ошибки. |
Что означает ответ
Техническая ошибка самого запроса результата. Она не меняет состояние задачи и не определяет результат выплат реестра.
Что делать дальше
- Безопасно повторите тот же запрос с тем же
task_idчерез рекомендованный интервал. - Если ошибка повторяется, получите статусы выплат по их
transactionчерез статус транзакции. - Если и эти запросы завершаются ошибкой, обратитесь в поддержку и передайте
task_id.
Состояния задачи
| Состояние | Финальное | Что делать |
|---|---|---|
PENDING |
Нет | Реестр ещё не обработан. Продолжайте опрос. То же состояние возвращается для неизвестного task_id. |
SUCCESS |
Да | Реестр обработан. Разберите response. |
FAILURE |
Да | Обработка реестра прервана ошибкой. response возвращается как null. |
PENDING для неизвестного task_id
Задача хранится ограниченное время, а неизвестный идентификатор не отличается от ещё не начатой задачи:
в обоих случаях возвращается PENDING. Если состояние не меняется дольше ожидаемого времени обработки
реестра, проверьте task_id и получите статусы выплат по их transaction.
Другие состояния
Кроме перечисленных могут возвращаться служебные состояния очереди задач. Любое состояние, кроме SUCCESS
и FAILURE, считайте промежуточным и продолжайте опрос.
Что делать при FAILURE
Часть выплат реестра могла быть создана до прерывания обработки. Не отправляйте реестр повторно, пока
не проверите по статусу транзакции каждый transaction из него. Повторно
отправляйте только те выплаты, транзакции по которым не найдены, сохраняя их исходные transaction.