Обзор рекуррентных платежей
Один раз сохраните источник оплаты плательщика и списывайте по нему без его участия
Рекуррентные платежи позволяют повторно списывать деньги без участия плательщика: подписки, автопополнения, рассрочки. Плательщик один раз подтверждает связку — источник оплаты, сохранённый у платёжного провайдера. Дальше вы создаёте списания по ID связки; платёжную страницу плательщик не открывает.
Перед тем как начать
Авторизация
Как подписывать запросы API-токеном.
Рекуррентные платежи включаются для отдельных способов оплаты. Попросите менеджера включить их; сейчас они доступны для СБП-платежей в RUB. Заказы без объекта recurring работают как раньше.
Как это работает
Сохраните связку
Создайте первый платёж с recurring.saveBinding: true или связку без платежа. Связка создаётся в статусе PENDING; сохраните её id.
Плательщик подтверждает
Плательщик оплачивает первый заказ (и соглашается на подписку в банковском приложении) или подтверждает связку на странице провайдера. Связка становится ACTIVE, вам приходит вебхук RECURRING_BINDING_UPDATE.
Списывайте по связке
Создайте заказ с recurring.bindingId. Он списывается сразу, без ссылки на оплату; результат приходит обычным вебхуком заказа.
Удалите связку
Когда подписка закончилась, удалите связку: дальнейшие списания будут отклонены.
Связка с первым платежом
Обычный запрос на создание заказа с объектом recurring. Всё остальное — поля customer, ссылка на оплату, H2H QR-ссылка, вебхуки — как у способа оплаты.
POST /v1/orders| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
externalUserId | string | ✅ Да | ID плательщика в вашей системе, до 64 символов. Связка принадлежит этому плательщику |
recurring.saveBinding | boolean | ✅ Да | true — сохранить источник оплаты после успешного платежа |
recurring.purpose | string | ❌ Нет | Описание подписки в банковском приложении, до 255 символов. По умолчанию — purpose заказа |
recurring.externalId | string | ❌ Нет | ID связки в вашей системе, уникальный в пределах мерчанта, до 255 символов |
curl -X POST "https://api.1capital.capital/v1/orders" \
-H "Content-Type: application/json" \
-H "X-Api-Token: YOUR_API_TOKEN" \
-d '{
"amount": "990",
"currency": "RUB",
"serviceId": 12,
"purpose": "Подписка, октябрь",
"externalId": "order_1234",
"externalUserId": "user_987",
"customer": { "phone": "+79991234567", "ip": "198.51.100.24" },
"recurring": {
"saveBinding": true,
"purpose": "Ежемесячная подписка",
"externalId": "sub-42"
}
}'В ответе — объект заказа с ID связки в recurringBindingId. Заказ направляется только на те способы оплаты сервиса, которые поддерживают рекуррентные платежи.
Для СБП плательщик получает QR-ссылку подписки (https://sub.nspk.ru/...) вместо разовой: оплачивая её, он соглашается и на будущие списания. Когда заказ становится COMPLETED, связка становится ACTIVE. Если заказ завершился как FAILED, EXPIRED или CANCELED, связка становится FAILED.
Связка без платежа
Сохраняет источник оплаты, ничего не списывая, — например, для бесплатного пробного периода.
POST /v1/recurring/bindings| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
externalUserId | string | ✅ Да | ID плательщика в вашей системе, до 64 символов |
serviceId | integer / null | ❌ Нет | Сервис, способ оплаты которого сохранит связку. По умолчанию — сервис по умолчанию |
purpose | string / null | ❌ Нет | Описание подписки в банковском приложении |
externalId | string / null | ❌ Нет | ID связки в вашей системе, уникальный в пределах мерчанта |
callbackUrl | string / null | ❌ Нет | URL вебхуков этой связки |
curl -X POST "https://api.1capital.capital/v1/recurring/bindings" \
-H "Content-Type: application/json" \
-H "X-Api-Token: YOUR_API_TOKEN" \
-d '{
"externalUserId": "user_987",
"serviceId": 12,
"purpose": "Ежемесячная подписка",
"externalId": "sub-43"
}'В ответе — объект связки с confirmationUrl: перенаправьте туда плательщика, чтобы он подтвердил связку в своём банке. Связка остаётся PENDING до подтверждения и становится FAILED, если её не подтвердили за 24 часа.
Списание по связке
POST /v1/orders| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
amount | string | ✅ Да | Сумма списания |
recurring.bindingId | string (UUID) | ✅ Да | ID связки в статусе ACTIVE |
serviceId | integer / null | ❌ Нет | По умолчанию — сервис, через который создана связка. В сервисе должен быть способ оплаты связки |
externalUserId | string / null | ❌ Нет | Если передан, должен совпадать с плательщиком связки. По умолчанию — плательщик связки |
externalId | string / null | ❌ Нет | ID списания в вашей системе. Рекомендуем: защищает от двойных списаний |
purpose, currency, callbackUrl и остальные параметры заказа работают как обычно.
curl -X POST "https://api.1capital.capital/v1/orders" \
-H "Content-Type: application/json" \
-H "X-Api-Token: YOUR_API_TOKEN" \
-d '{
"amount": "990",
"currency": "RUB",
"purpose": "Подписка, ноябрь",
"externalId": "order_1235",
"recurring": { "bindingId": "0199a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b" }
}'Списание уходит провайдеру, пока обрабатывается запрос. В ответе — объект заказа:
PENDING— списание принято, результат придёт вебхукомORDER_UPDATE;COMPLETED— провайдер сразу подтвердил списание;FAILED— провайдер отказал, например из-за нехватки средств. Создайте новое списание позже.
У списания нет платёжной страницы: ссылка на оплату и H2H-ручки отвечают на него 400. Комиссии, лимиты, зачисление на баланс и вебхуки — как у любого заказа.
Ошибки
| HTTP-статус | Когда |
|---|---|
400 | Неверные параметры: saveBinding вместе с bindingId, нет externalUserId при saveBinding, externalUserId другого плательщика |
404 | Связка не найдена или принадлежит другому мерчанту; ни один способ оплаты сервиса не поддерживает рекуррентные платежи; сумма вне лимитов способа оплаты |
409 | Связка не в статусе ACTIVE; способ оплаты связки выключен или не входит в сервис; externalId уже занят |
Объект связки
{
"id": "0199a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b",
"status": "ACTIVE",
"isTest": false,
"merchantId": "0199a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5e",
"externalId": "sub-42",
"externalUserId": "user_987",
"purpose": "Monthly subscription",
"initialOrderId": "0199a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5c",
"confirmationUrl": null,
"bankName": "Sberbank",
"bankLogoUrl": null,
"callbackUrl": null,
"createdAt": "2026-10-21T12:34:56.000Z",
"updatedAt": "2026-10-21T12:36:10.512Z",
"activatedAt": "2026-10-21T12:36:10.512Z",
"closedAt": null
}| Поле | Тип | Описание |
|---|---|---|
id | string (UUID) | ID связки. Передавайте его в recurring.bindingId, чтобы списать по связке |
status | string | Текущий статус, см. Статусы связки |
isTest | boolean | Тестовая связка: создана на тестовом терминале, настоящий источник оплаты не сохраняется |
merchantId | string (UUID) | Ваш ID мерчанта |
externalId | string / null | ID связки в вашей системе (переданное значение) |
externalUserId | string | ID плательщика в вашей системе: связка принадлежит только ему |
purpose | string / null | Описание подписки, которое плательщик видит в банковском приложении |
initialOrderId | string / null | Заказ, оплата которого создала связку; null у связки, созданной без платежа |
confirmationUrl | string / null | Страница, на которой плательщик подтверждает связку, созданную без платежа. Перенаправьте его туда |
bankName | string / null | Банк плательщика, если провайдер его сообщил |
bankLogoUrl | string / null | Логотип банка плательщика, если провайдер его сообщил |
callbackUrl | string / null | URL вебхуков этой связки |
createdAt | string | Время создания (ISO 8601) |
updatedAt | string | Время последнего изменения (ISO 8601) |
activatedAt | string / null | Когда связка впервые стала ACTIVE |
closedAt | string / null | Когда связка стала DELETED или FAILED |
Статусы связки
| Статус | Финальный | Описание |
|---|---|---|
PENDING | Нет | Ждём плательщика: первый платёж ещё не завершён или плательщик не подтвердил связку |
ACTIVE | Нет | Связка подтверждена: по ней можно списывать |
SUSPENDED | Нет | Приостановлена провайдером или банком плательщика. Списания отклоняются; связка может снова стать ACTIVE |
DELETED | Да | Удалена вами, плательщиком в банковском приложении или провайдером. Списания отклоняются |
FAILED | Да | Связка не создана: первый платёж не прошёл или истёк, либо плательщик не подтвердил её за 24 часа |
Связка FAILED всё же станет ACTIVE, если провайдер сообщит о поздней успешной оплате первого платежа. О каждой смене статуса приходит вебхук RECURRING_BINDING_UPDATE.
Управление связками
| Запрос | Описание |
|---|---|
GET /v1/recurring/bindings/{bindingId} | Связка по ID |
GET /v1/recurring/bindings/external/{externalId} | Связка по вашему ID |
POST /v1/recurring/bindings/find | Поиск с фильтрами и пагинацией, например все связки плательщика |
POST /v1/recurring/bindings/{bindingId}/sync-status | Запросить текущее состояние у провайдера и применить его |
DELETE /v1/recurring/bindings/{bindingId} | Удалить связку у провайдера; она станет DELETED |
Связки плательщика
curl -X POST "https://api.1capital.capital/v1/recurring/bindings/find" \
-H "Content-Type: application/json" \
-H "X-Api-Token: YOUR_API_TOKEN" \
-d '{
"pagination": { "page": 1, "perPage": 20 },
"filter": { "externalUserId": "user_987", "status": ["ACTIVE"] }
}'Фильтры: externalUserId, externalId, status (любой из), fromDate, toDate (время создания), q (ID связки, ваш ID, ID плательщика или ID первого заказа). Сортировка: sort: [{ "field": "createdAt", "order": "desc" }] по status, createdAt, updatedAt, activatedAt. Ответ — { "data": [объекты связок], "total": число }.
Удаление связки
curl -X DELETE "https://api.1capital.capital/v1/recurring/bindings/0199a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b" \
-H "X-Api-Token: YOUR_API_TOKEN"Возвращает связку в статусе DELETED. Связка, уже DELETED или FAILED, отвечает 409; если провайдер не ответил — 503, связка не меняется.
Сверка с провайдером
Плательщик может приостановить или удалить подписку в банковском приложении. Связки PENDING сверяются в фоне; для ACTIVE вызовите sync-status, когда списание отклонено, чтобы узнать, действует ли связка. Ответ — { "providerState", "previousStatus", "binding" }.
Тестовый режим
На тестовом способе оплаты настоящий источник оплаты не сохраняется:
- связка с первым платежом становится
ACTIVE, когда её тестовый заказ становитсяCOMPLETED(сумма1000), иFAILED, если заказ не оплачен; - связка без платежа становится
ACTIVEв течение минуты,confirmationUrl—null; - списания — тестовые заказы, их статус зависит от суммы:
1000—COMPLETED,1001—CANCELED,1002—FAILED,1003—COMPLETED, затемREFUND, любая другая сумма —EXPIREDчерез 5 минут; sync-statusотвечает400, удаление работает без провайдера.
Рекомендации
- Передавайте
recurring.externalIdдля связок иexternalIdдля списаний: повторный запрос с тем же значением отклоняется с409— это защищает от дублей связок и двойных списаний. - Списывайте только по связкам
ACTIVE; после первого платежа дождитесь вебхукаRECURRING_BINDING_UPDATE. - Списание в
PENDINGещё в обработке: не повторяйте его, пока оно не получит финальный статус. - Удаляйте связки отменённых подписок — до этого плательщик видит подписку в банковском приложении.