Перейти к содержанию

Массовая выплата через СБП

Раздел описывает два метода: создание реестра выплат через СБП и получение его результата. Реестр обрабатывается асинхронно: в ответ на создание возвращается только идентификатор задачи, а результат по каждой выплате запрашивается отдельно.

Сценарий интеграции

  1. Получите bank_id банка-получателя для каждой выплаты из общего списка банков.
  2. Подготовьте список выплат. Для каждой выплаты сформируйте собственный уникальный transaction.
  3. Подпишите точное тело запроса и отправьте реестр.
  4. Сохраните id из ответа — это идентификатор задачи (task_id), по которому запрашивается результат.
  5. Опрашивайте результат массовой выплаты, пока задача не перейдёт в состояние SUCCESS или FAILURE.
  6. Финальный статус каждой выплаты получайте по её transaction через статус транзакции или колбэк.

Ответ 200 не подтверждает создание выплат

Ответ 200 означает только, что реестр сохранён и задача поставлена в очередь. На этом шаге не создаётся ни одной выплаты и ни одной транзакции. Выплаты создаются в фоне — по одной, последовательно, в порядке элементов items.

Лимиты и ошибки отдельных выплат

Лимиты магазина проверяются для каждой выплаты отдельно в момент её создания. Ошибка по одной выплате не останавливает обработку реестра: остальные выплаты обрабатываются, а ошибочный элемент попадает в результат задачи с кодом и описанием ошибки.

Магазины с подтверждением выплат по OTP

Реестр не поддерживает подтверждение выплат одноразовым кодом: шага подтверждения для массовой выплаты нет. Если для магазина включён OTP, используйте единичную выплату через СБП и подтверждение выплаты.

Создание реестра

URL

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

Заголовки

Название Тип Обязательно Описание
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 не создавались.

Пример ответа 200 (OK)
{
  "id": "1d5b2f5a-8f0a-4c27-9c53-2f7a8a1b4d10",
  "status": "PENDING"
}

Параметры ответа

Параметр Тип Описание
id string Идентификатор задачи (task_id). Передаётся в метод получения результата.
status string Состояние задачи в момент постановки в очередь. Значения приведены в разделе «Состояния задачи».

Что означает ответ

Реестр сохранён, задача поставлена в очередь. Выплаты ещё не созданы, транзакций в системе KVELL нет.

Что делать дальше

  1. Сохраните id на своей стороне: без него результат реестра получить нельзя.
  2. Опрашивайте результат массовой выплаты до состояния SUCCESS или FAILURE.
Пример ответа 400 (Bad Request)
{
  "errors": [
    {
      "code": 20003,
      "message": "Payout профиль не привязан к магазину"
    }
  ]
}

Параметры ответа

Параметр Тип Описание
errors array Список ошибок. Коды и рекомендации по обработке приведены в разделе «Ошибки HTTP-ответов».
∟ code integer Код ошибки.
∟ message string Описание причины отклонения запроса.
Пример ответа 404 (Not Found)
{
  "errors": [
    {
      "code": 20006,
      "message": "Магазин не найден"
    }
  ]
}

Параметры ответа

Параметр Тип Описание
errors array Список ошибок. Коды и рекомендации по обработке приведены в разделе «Ошибки HTTP-ответов».
∟ code integer Код ошибки.
∟ message string Описание причины, по которой ресурс не найден.
Пример ответа 422 (Unprocessable Entity)
{
  "errors": [
    {
      "code": 20098,
      "message": "items.0.phone: Field required"
    }
  ]
}

Параметры ответа

Параметр Тип Описание
errors array Список ошибок валидации. Коды и рекомендации по обработке приведены в разделе «Ошибки HTTP-ответов».
∟ code integer Код ошибки.
∟ message string Причина ошибки валидации с указанием поля.

Что означает ответ

Реестр не прошёл проверку формата: достаточно одного некорректного элемента items, чтобы весь запрос был отклонён. Реестр не сохранён, выплаты не создавались.

Что делать дальше

  1. Исправьте поля, перечисленные в errors[].message, и убедитесь, что items содержит минимум один элемент.
  2. Сформируйте новую подпись по исправленному телу и отправьте реестр заново с теми же transaction.
Пример ответа 5XX (Internal Server Error)
{
  "errors": [
    {
      "code": 20000,
      "message": "Неизвестная ошибка"
    }
  ]
}

Параметры ответа

Параметр Тип Описание
errors array Список ошибок. Коды и рекомендации по обработке приведены в разделе «Ошибки HTTP-ответов».
∟ code integer Код ошибки.
∟ message string Описание технической ошибки.

5XX, таймаут и разрыв соединения

Результат запроса считается неопределённым: задача могла быть поставлена в очередь, даже если клиент не получил ответ. Повторная отправка того же реестра без проверки приведёт к дублирующим попыткам выплат.

Единый алгоритм обработки

  1. Не считайте реестр ни принятым, ни отклонённым только на основании технической ошибки.
  2. Если id задачи получен не был, проверьте статус транзакции по transaction из реестра.
  3. Если ни одна транзакция не найдена, отправьте реестр повторно с теми же transaction.
  4. Если транзакции найдены, не отправляйте реестр заново: дождитесь их финальных статусов.
  5. Если запросы продолжают завершаться ошибкой, обратитесь в поддержку и передайте название реестра и время запроса.

Не создавайте дублирующие выплаты

Не меняйте transaction при повторной отправке реестра. Выплата с уже использованным transaction отклоняется с кодом 20007, и это защищает от двойной выплаты.

Получение результата

Метод возвращает состояние задачи обработки реестра и, после её завершения, результат по каждой выплате. Метод не изменяет состояние операций.

Интервал опроса

Рекомендуемый интервал между запросами — не менее 1 минуты. Реестр обрабатывается последовательно, поэтому время обработки растёт пропорционально количеству выплат.

Состояние SUCCESS относится к задаче, а не к выплатам

SUCCESS означает, что реестр обработан до конца. Отдельные выплаты внутри реестра могли завершиться ошибкой или ещё находиться в обработке на стороне банка.

URL

GET https://api.pay.kvell.group/v1/orders/payout/sbp/bulk/{task_id}
GET https://api.pay.stage.kvell.group/v1/orders/payout/sbp/bulk/{task_id}

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.

SHA256(X-Api-Key + task_id + secret_key)

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.

Пример ответа 200 (OK)
{
  "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, а не по индексу.

Что делать дальше

  1. Если state не равен SUCCESS или FAILURE, повторите запрос позднее.
  2. При SUCCESS разберите response: элементы с id — созданные выплаты, элементы с code и message — выплаты, которые создать не удалось.
  3. Выплаты из ошибочных элементов не созданы. Устраните причину и отправьте их новым реестром с теми же transaction.
  4. Для созданных выплат дождитесь финального статуса completed или canceled.
Пример ответа 400 (Bad Request)
{
  "errors": [
    {
      "code": 20002,
      "message": "Неверная подпись"
    }
  ]
}

Параметры ответа

Параметр Тип Описание
errors array Список ошибок. Коды и рекомендации по обработке приведены в разделе «Ошибки HTTP-ответов».
∟ code integer Код ошибки.
∟ message string Описание причины отклонения запроса.
Пример ответа 404 (Not Found)
{
  "errors": [
    {
      "code": 20006,
      "message": "Магазин не найден"
    }
  ]
}

Параметры ответа

Параметр Тип Описание
errors array Список ошибок. Коды и рекомендации по обработке приведены в разделе «Ошибки HTTP-ответов».
∟ code integer Код ошибки.
∟ message string Описание причины, по которой ресурс не найден.

Что означает ответ

Не найден магазин с переданным X-Api-Key. Неизвестный или устаревший task_id ответом 404 не возвращается — см. раздел «Состояния задачи».

Пример ответа 5XX (Internal Server Error)
{
  "errors": [
    {
      "code": 20000,
      "message": "Неизвестная ошибка"
    }
  ]
}

Параметры ответа

Параметр Тип Описание
errors array Список ошибок. Коды и рекомендации по обработке приведены в разделе «Ошибки HTTP-ответов».
∟ code integer Код ошибки.
∟ message string Описание технической ошибки.

Что означает ответ

Техническая ошибка самого запроса результата. Она не меняет состояние задачи и не определяет результат выплат реестра.

Что делать дальше

  1. Безопасно повторите тот же запрос с тем же task_id через рекомендованный интервал.
  2. Если ошибка повторяется, получите статусы выплат по их transaction через статус транзакции.
  3. Если и эти запросы завершаются ошибкой, обратитесь в поддержку и передайте task_id.

Состояния задачи

Состояние Финальное Что делать
PENDING Нет Реестр ещё не обработан. Продолжайте опрос. То же состояние возвращается для неизвестного task_id.
SUCCESS Да Реестр обработан. Разберите response.
FAILURE Да Обработка реестра прервана ошибкой. response возвращается как null.

PENDING для неизвестного task_id

Задача хранится ограниченное время, а неизвестный идентификатор не отличается от ещё не начатой задачи: в обоих случаях возвращается PENDING. Если состояние не меняется дольше ожидаемого времени обработки реестра, проверьте task_id и получите статусы выплат по их transaction.

Другие состояния

Кроме перечисленных могут возвращаться служебные состояния очереди задач. Любое состояние, кроме SUCCESS и FAILURE, считайте промежуточным и продолжайте опрос.

Что делать при FAILURE

Часть выплат реестра могла быть создана до прерывания обработки. Не отправляйте реестр повторно, пока не проверите по статусу транзакции каждый transaction из него. Повторно отправляйте только те выплаты, транзакции по которым не найдены, сохраняя их исходные transaction.