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

Массовая выплата на карту

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

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

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

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

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

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

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

Подтверждение по OTP не применяется

Выплаты из реестра создаются без подтверждения одноразовым кодом, даже если для магазина включён OTP. Если выплаты нужно подтверждать кодом, используйте единичную выплату на карту.

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

URL

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

Заголовки

Название Тип Обязательно Описание
X-Api-Key string Да Идентификатор магазина.
X-Signature string Да Подпись тела запроса.

Формирование подписи

Запрос необходимо подписать электронной подписью RSA/SHA-256. Передайте результат в заголовке X-Signature.

Пошаговый алгоритм, требования к ключам, примеры для Python, PHP и OpenSSL, а также диагностика ошибки 20002 приведены в общем разделе «Формирование подписи для выплат».

Тело запроса

Параметр Тип Обязательно Описание
name string Да Название реестра в системе мерчанта. Используется для поиска реестра.
items array Да Список выплат, минимум один элемент. Структура элемента описана ниже.

Элемент массива items

Параметр Тип Обязательно Описание
recipient_pan string Да Номер карты получателя без пробелов и разделителей.
customer_card object Нет Привязанная карта покупателя: customer_key и customer_card_token. Передаётся вместо recipient_pan.
amount integer Да Сумма в копейках. Например, 15000 — 150 ₽.
transaction string Да Уникальный идентификатор операции в системе мерчанта.
description string Да Назначение выплаты, не более 210 символов.
customer string Нет Идентификатор плательщика, email или номер телефона.
extra_data object Нет Дополнительные данные мерчанта.
fiscal_data object Нет Данные для фискализации чека по 54-ФЗ.

Работа с номером карты

recipient_pan содержит платёжные данные. Не записывайте полный номер карты в логи и не храните его без необходимости. Соблюдайте применимые требования PCI DSS.

Пример

{
  "name": "Реестр выплат за 10.08.2026",
  "items": [
    {
      "recipient_pan": "4111111111111111",
      "amount": 15000,
      "transaction": "payout-card-20260810-0001",
      "description": "Выплата по договору 42"
    },
    {
      "recipient_pan": "5555555555554444",
      "amount": 27000,
      "transaction": "payout-card-20260810-0002",
      "description": "Выплата по договору 43"
    }
  ]
}
curl --request POST \
  --url 'https://api.pay.stage.kvell.group/v1/orders/account2card/bulk' \
  --header 'X-Api-Key: <api-key>' \
  --header 'X-Signature: <signature>' \
  --header 'Content-Type: application/json' \
  --data '{"name":"Реестр выплат за 10.08.2026","items":[{"recipient_pan":"4111111111111111","amount":15000,"transaction":"payout-card-20260810-0001","description":"Выплата по договору 42"}]}'

Ответ

Выберите HTTP-код, чтобы посмотреть пример, параметры ответа и рекомендуемые действия.

Если HTTP-ответ не получен

Таймаут или разрыв соединения обрабатывайте так же, как ответ 5XX: неизвестно, была ли задача поставлена в очередь. Не отправляйте реестр повторно, пока не убедитесь, что выплаты по его transaction не создавались.

Пример ответа 200 (OK)
{
  "id": "8f0f5f4b-6f6d-4f4f-9a2a-0d1a1f6b0b21",
  "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": 20020,
      "message": "Получатель не задан"
    }
  ]
}

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

Параметр Тип Описание
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/account2card/bulk/{task_id}
GET https://api.pay.stage.kvell.group/v1/orders/account2card/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/account2card/bulk/8f0f5f4b-6f6d-4f4f-9a2a-0d1a1f6b0b21' \
  --header 'X-Api-Key: <api-key>' \
  --header 'X-Signature: <signature>'

Ответ

Выберите HTTP-код, чтобы посмотреть пример, параметры ответа и рекомендуемые действия.

Если HTTP-ответ не получен

Метод только читает состояние задачи и не меняет состояние выплат. При 5XX, таймауте или разрыве соединения безопасно повторите тот же запрос с тем же task_id.

Пример ответа 200 (OK)
{
  "state": "SUCCESS",
  "response": [
    {
      "order": {
        "id": "3b3c19f4-c680-4f5d-bf2e-c0835439cf12",
        "status": "processing",
        "transaction": "payout-card-20260810-0001",
        "amount": 15000,
        "commission": 150,
        "description": "Выплата по договору 42",
        "additional_data": {
          "auth_code": null,
          "rrn": null
        },
        "error_code": null,
        "error_message": null,
        "created_at": "2026-08-10T09:15:27.231000+00:00"
      },
      "transaction": "payout-card-20260810-0001",
      "status": "processing"
    },
    {
      "transaction": "payout-card-20260810-0002",
      "code": "20019",
      "message": "Превышен лимит выплат по магазину"
    }
  ]
}

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

Параметр Тип Описание
state string Состояние задачи. Возможные значения приведены в разделе «Состояния задачи».
response array | null Результаты по выплатам. Заполняется только при state = SUCCESS, в остальных случаях — null.
∟ order object | null Созданная выплата. Отсутствует в элементе с ошибкой.
 ∟ id string Идентификатор выплаты в KVELL.
 ∟ status string Текущий статус выплаты. Возможные значения приведены в разделе «Статусы выплаты».
 ∟ transaction string Идентификатор операции, переданный мерчантом.
 ∟ amount integer Сумма выплаты в копейках.
 ∟ commission integer Комиссия в копейках.
 ∟ description string | null Назначение выплаты. Может включать префикс, настроенный для магазина.
 ∟ additional_data object | null Дополнительные данные, полученные при обработке выплаты.
  ∟ auth_code string | null Код авторизации, если его вернул банк.
  ∟ rrn string | null Идентификатор банковской транзакции, который генерирует банк-эквайер.
 ∟ error_code string | null Код причины отклонения. Возможные значения приведены в разделе «Коды ошибок транзакции».
 ∟ error_message string | null Описание причины отклонения. Для неотклонённой выплаты возвращается null.
 ∟ created_at string Дата и время создания выплаты в формате ISO 8601.
∟ transaction string Идентификатор операции в системе мерчанта. Возвращается и в успешном элементе, и в элементе с ошибкой.
∟ status string Текущий статус выплаты; совпадает с order.status.
∟ code string Код ошибки выплаты. Присутствует только в элементе с ошибкой. Коды приведены в справочнике «Ошибки HTTP-ответов».
∟ message string Описание ошибки выплаты. Присутствует только в элементе с ошибкой.

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

Ответ 200 возвращается на любом состоянии задачи, в том числе пока реестр ещё не обработан. Порядок элементов response совпадает с порядком items в запросе реестра. Сопоставляйте элементы по transaction, а не по индексу.

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

  1. Если state не равен SUCCESS или FAILURE, повторите запрос позднее.
  2. При SUCCESS разберите response: элементы с order — созданные выплаты, элементы с 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.