Обзор возвратов
Возврат платежа по завершённому заказу плательщику
Возврат возвращает плательщику платёж по завершённому заказу. Он создаётся одним запросом; сумма списывается с баланса мерчанта, а о каждом изменении статуса после создания приходит подписанное webhook-уведомление.
Перед тем как начать
Авторизация
Как подписывать запросы API-токеном.
Возвраты включаются для каждого способа оплаты отдельно. Попросите менеджера включить их для нужных вам способов: по остальным заказам запрос отклоняется с кодом 403.
Как это работает
Создайте возврат
Один запрос POST /v1/refunds с id заказа в статусе COMPLETED. Сумма списания сразу замораживается на вашем балансе; в ответе возвращается объект возврата. Сохраните его id.
Если платёжный провайдер поддерживает возвраты через API, возврат создаётся у провайдера и получает статус PENDING. Иначе возврат получает статус MANUAL и проводится платформой.
Отслеживайте результат
При каждом изменении статуса после создания мы отправляем подписанный webhook REFUND_UPDATE. Опрос GET /v1/refunds/{refundId} — резервный способ.
Получите статус заказа
Когда возврат переходит в COMPLETED, замороженная сумма списывается, а заказ переходит в статус REFUND: приходит и webhook-уведомление по заказу (ORDER_UPDATE). Если возврат завершается статусом FAILED или CANCELED, замороженная сумма возвращается на баланс.
Правила
- Вернуть можно только заказ в статусе
COMPLETED. - Пока поддерживаются только полные возвраты: плательщику возвращается вся сумма заказа.
- По заказу может быть один активный (
MANUAL,PENDING) или завершённый возврат. ПослеFAILEDилиCANCELEDможно создать новый. - Баланса должно хватать на сумму списания: иначе возврат не создаётся (
409).
Сколько списывается с баланса
Сумма списывается с того баланса, на который был зачислен заказ (debitCurrency). В зависимости от настроек способа оплаты это либо вся зачисленная сумма заказа, либо только полученная вами сумма, то есть сумма за вычетом комиссии. В объекте возврата видны и сумма (debitAmount), и основание (debitBasis).
Создание возврата
POST /v1/refundsПараметры запроса
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
orderId | string (UUID) | ✅ Да | ID заказа, по которому делается возврат. Заказ должен принадлежать вам и находиться в статусе COMPLETED |
amount | number | ❌ Нет | Сумма возврата в валюте заказа. Пока поддерживаются только полные возвраты: если сумма передана, она должна совпадать с суммой заказа |
externalId | string | ❌ Нет | ID возврата в вашей системе, уникальный среди ваших возвратов (до 255 символов) |
reason | string | ❌ Нет | Причина возврата (до 1000 символов) |
callbackUrl | string | ❌ Нет | URL для webhook-уведомлений по этому возврату. Если не указан, используется callbackUrl заказа, затем адрес из настроек мерчанта |
Пример запроса
curl -X POST "https://api.platinout.com/v1/refunds" \
-H "Content-Type: application/json" \
-H "X-Api-Token: YOUR_API_TOKEN" \
-d '{
"orderId": "0199a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5c",
"externalId": "refund-123",
"reason": "Запрос покупателя",
"callbackUrl": "https://example.com/webhooks/refunds"
}'Ответ
Успешный запрос возвращает объект возврата в начальном статусе (MANUAL, PENDING или, если провайдер сразу отклонил возврат, FAILED). Тот же объект возвращают endpoint'ы проверки статуса.
{
"id": "0199a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b",
"orderId": "0199a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5c",
"orderExternalId": "order_1234",
"terminalId": "0199a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5d",
"merchantId": "0199a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5e",
"status": "PENDING",
"amount": "1000.5",
"currency": "RUB",
"debitAmount": "1000.5",
"debitCurrency": "RUB",
"debitBasis": "ORDER_AMOUNT",
"externalId": "refund-123",
"reason": "Customer request",
"callbackUrl": "https://example.com/webhooks/refunds",
"statusMessage": null,
"gatewayRefundId": null,
"metadata": null,
"createdAt": "2026-09-23T12:34:56.000Z",
"updatedAt": "2026-09-23T12:34:56.000Z",
"completedAt": null
}Поля объекта возврата
| Поле | Тип | Описание |
|---|---|---|
id | string (UUID) | ID возврата. Используйте его для проверки статуса |
orderId | string (UUID) | ID заказа, по которому сделан возврат |
orderExternalId | string / null | externalId заказа |
terminalId | string / null | ID терминала, через который был оплачен заказ |
merchantId | string (UUID) | ID вашего мерчанта |
status | string | Текущий статус возврата, см. Статусы возвратов |
amount | string | Сумма, возвращаемая плательщику, в валюте заказа |
currency | string | Валюта заказа |
debitAmount | string | Сумма списания с вашего баланса: заморожена, пока возврат в статусе MANUAL или PENDING, списывается при COMPLETED, возвращается при FAILED и CANCELED |
debitCurrency | string | Валюта баланса, с которого списывается возврат: того, на который был зачислен заказ |
debitBasis | string | ORDER_AMOUNT: списывается вся зачисленная сумма заказа; MERCHANT_RECEIVED: только полученная вами сумма (сумма за вычетом комиссии) |
externalId | string / null | ID возврата в вашей системе |
reason | string / null | Причина возврата |
callbackUrl | string / null | URL для webhook-уведомлений по этому возврату (null — используется адрес заказа или настроек мерчанта) |
statusMessage | string / null | Служебное поле, в API мерчанта всегда null |
gatewayRefundId | string / null | Служебное поле, в API мерчанта всегда null |
metadata | object / null | Служебное поле, в API мерчанта всегда null |
createdAt | string | Время создания (ISO 8601) |
updatedAt | string | Время последнего обновления (ISO 8601) |
completedAt | string / null | Время завершения (ISO 8601) |
Ошибки
| HTTP-статус | Когда |
|---|---|
400 | Некорректные параметры или amount не совпадает с суммой заказа |
403 | Для способа оплаты заказа возвраты не включены |
404 | Заказ не найден или принадлежит другому мерчанту |
409 | Заказ не в статусе COMPLETED, по нему уже есть активный или завершённый возврат, externalId занят или баланса не хватает на списание |
Статусы возвратов
| Статус | Финальный | Описание |
|---|---|---|
MANUAL | Нет | Платёжный провайдер не поддерживает возвраты через API: возврат проводится платформой вручную |
PENDING | Нет | Возврат создан у платёжного провайдера и обрабатывается |
COMPLETED | Условно | Возврат завершён: сумма списана с вашего баланса, заказ переходит в REFUND |
FAILED | Условно | Возврат не прошёл: замороженная сумма вернулась на ваш баланс |
CANCELED | Условно | Возврат отменён: замороженная сумма вернулась на ваш баланс |
Финальные статусы меняются только при ручной корректировке возврата платформой. Баланс всегда следует за статусом, а о каждом изменении приходит webhook-уведомление REFUND_UPDATE.
Проверка статуса возврата
GET /v1/refunds/{refundId}curl -X GET "https://api.platinout.com/v1/refunds/0199a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b" \
-H "X-Api-Token: YOUR_API_TOKEN"По вашему ID возврата:
GET /v1/refunds/external/{externalId}Используйте webhook-уведомления как основной канал. Опрашивайте статус по ID только как резервный способ, например каждые 30 минут для возвратов, которые ещё не получили финальный статус.
Рекомендации
- Передавайте
externalIdи сохраняйтеidвозврата из ответа: повторный запрос с тем жеexternalIdотклоняется с кодом409, что защищает от двойного возврата. - Держите на балансе достаточно средств: сумма списания замораживается при создании.
- Обрабатывайте webhook-уведомление по заказу со статусом
REFUND: оно приходит, когда возврат завершён. - Считайте
MANUALстатусом «в работе»: такие возвраты завершает платформа, результат придёт в webhook-уведомлении.