Возврат средств с баланса клиента
Возврат средств
https://gptunnel.ru/api/v1/balance/refund Возвращает деньги со счёта клиента на баланс организации, которой принадлежит ключ. Клиент задаётся ровно одним полем: user_id (личный счёт пользователя) или org_id (счёт организации).
Правила возврата:
- В пределах ваших переводов. Вернуть можно не больше суммы ваших переводов этому клиенту, которая ещё не возвращена. Бонусы не возвращаются.
- Не больше остатка. Возврат больше текущего баланса клиента не пройдёт. Деньги на счёте по источнику не различаются: если клиент потратил часть перевода и пополнил счёт сам, возврат идёт из общего остатка — в пределах ваших переводов.
- Старые переводы возвращаются первыми. Сумма раскладывается по вашим переводам этому клиенту от старых к новым; вся операция атомарна — проходит целиком или не проходит вовсе.
Сумма задаётся одним из двух способов: явной amount либо refund_all_balance: true — вернуть всё, что можно, то есть меньшее из баланса клиента и невозвращённой суммы переводов. Лимит 100 000 ₽ действует только на явную amount.
Headers
| Параметр | Тип | Описание |
|---|---|---|
Authorization* | string | API ключ организации |
Idempotency-Key* | string | Уникальный ключ операции, 8–60 символов A-Za-z0-9_- |
Content-Type* | string | application/json |
Параметры запроса
| Параметр | Тип | Описание |
|---|---|---|
user_id | string | ID пользователя-клиента, 24 hex-символа строчными. Ровно одно из user_id, org_id и user_data |
org_id | string | ID организации-клиента, 24 hex-символа строчными. Ровно одно из user_id, org_id и user_data |
user_data | object | Поиск пользователя по телефону: { "phone": "+79XXXXXXXXX" }. Подключается отдельно, см. обзор |
amount | number | Сумма в рублях, больше 0 и не более 100 000, до 2 знаков после запятой. Ровно одно из amount и refund_all_balance: true |
refund_all_balance | boolean | true — вернуть всё доступное к возврату, без лимита 100 000. Ровно одно из amount и refund_all_balance: true |
Пример запроса
curl --request POST \ --url https://gptunnel.ru/api/v1/balance/refund \ --header 'Authorization: YOUR_API_KEY' \ --header 'Idempotency-Key: refund-2026-11-06-000041' \ --header 'Content-Type: application/json' \ --data '{ "user_id": "6ad72133269dc8d9f75a33bc", "amount": 300}'import axios from 'axios'
const response = await axios({ method: 'POST', url: 'https://gptunnel.ru/api/v1/balance/refund', headers: { Authorization: 'YOUR_API_KEY', 'Idempotency-Key': 'refund-2026-11-06-000041', }, data: { user_id: '6ad72133269dc8d9f75a33bc', amount: 300, },})
console.log(response.data)import requests
response = requests.post( 'https://gptunnel.ru/api/v1/balance/refund', headers={ 'Authorization': 'YOUR_API_KEY', 'Idempotency-Key': 'refund-2026-11-06-000041', }, json={ 'user_id': '6ad72133269dc8d9f75a33bc', 'amount': 300, },)
print(response.json())Ответ
Поля ответа
| Параметр | Тип | Описание |
|---|---|---|
code | number | 0 при успехе |
transaction_id | string | Ваш Idempotency-Key из запроса |
org_id | string | Организация, на баланс которой вернулись деньги |
client_user_id | string | null | Пользователь, с чьего личного счёта сделан возврат |
client_org_id | string | null | Организация, со счёта которой сделан возврат |
amount | number | Сумма, списанная со счёта клиента, в рублях. При refund_all_balance — фактическая, может быть больше 100 000 |
discount_reverted | number | Часть партнёрской скидки, отозванная вместе с возвратом; 0, если переводы шли без скидки |
net_amount | number | Итог для баланса организации: amount минус discount_reverted |
currency | string | Всегда RUB |
created_at | string | Время операции, ISO 8601 |
replayed | boolean | true, если это повтор по тому же Idempotency-Key |
{ "code": 0, "transaction_id": "refund-2026-11-06-000041", "org_id": "6ad5e0c3269dc8d9f75a1f07", "client_user_id": "6ad72133269dc8d9f75a33bc", "client_org_id": null, "amount": 300, "discount_reverted": 0, "net_amount": 300, "currency": "RUB", "created_at": "2026-11-06T08:21:07.000Z", "replayed": false}{ "code": 37, "message": "Insufficient funds on the client balance."}{ "code": 38, "message": "Amount exceeds the unreturned transfers to this client."}Партнёрская скидка
Если перевод шёл со скидкой, при возврате она отзывается пропорционально возвращённой сумме — по проценту, зафиксированному в каждом переводе. На баланс организации зачисляется amount, отзыв скидки проходит отдельной операцией на discount_reverted, итог — net_amount.
Ошибки
| HTTP | code | Когда |
|---|---|---|
| 400 | 3 | Тело не по схеме: нет клиента или указано больше одного поля, лишнее поле, id не из 24 символов 0-9a-f, нет суммы или заданы и amount, и refund_all_balance: true, сумма вне диапазона. Подробности — в поле details |
| 400 | 21 | Нет заголовка Idempotency-Key или он не из 8–60 символов A-Za-z0-9_- |
| 403 | 13 | Ключ личного аккаунта, а не организации |
| 403 | 22 | На ключе выключен тумблер «Переводы» |
| 403 | 27 | Поиск по user_data организации не подключён |
| 403 | 35 | Организации ключа метод не подключён, у неё выключены переводы или она обслуживается через дистрибьютора |
| 404 | 17 | Пользователь не найден, удалён или не является клиентом партнёра |
| 404 | 24 | Организация не найдена, удалена или не является клиентом партнёра |
| 409 | 20 | Idempotency-Key уже использован с другим клиентом или другой amount |
| 409 | 39 | Одновременно идёт другая операция по этой организации — повторите запрос с тем же Idempotency-Key |
| 422 | 37 | На счёте клиента меньше запрошенной суммы; при refund_all_balance — возвращать нечего |
| 422 | 38 | amount больше суммы ваших переводов этому клиенту, которая ещё не возвращена |
Сначала проверяется ключ, потом заголовок Idempotency-Key, потом тело: ключ без доступа получит 403 даже на запрос без заголовка.
Если клиент удалён прямо во время операции, придёт 404 с кодом 23 (пользователь) или 25 (организация). Организация, владелец которой не ваш клиент, методу не видна — 404, код 24, — даже если вы переводили ей деньги: вернуть их через API не получится.
Полный список кодов и ответ 401 на неверный ключ — в справочнике ошибок.