# Возврат не проходит

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

## Коротко

Возврат делается через `POST /api/v1/invoices/{id}/refund` с телом `{ amount?, reason? }`. Если пришла ошибка, смотрите в первую очередь на **код `error`** — от него зависит, что делать дальше. Главное правило: **при `refund_unknown` и `refund_pending_unknown` запрос повторять нельзя**. Эти два кода означают «результат пока неизвестен», и повтор может вернуть деньги дважды. Вместо повтора прочитайте статус счёта и узнайте из него, что произошло на самом деле.

## По кодам ошибок

| Код | HTTP | Что случилось | Что делать |
|---|---|---|---|
| `invoice_not_refundable` | 409 | По этому счёту возврат невозможен | Прочитайте статус: оплачен ли счёт, не вышел ли срок |
| `invalid_refund_amount` | 422 | Неверная сумма | Положительное число, не больше оплаченной суммы |
| `refund_failed` | 502 | Kaspi не выполнил возврат | Проверьте, хватает ли денег на счёте Kaspi |
| `refund_unknown` | 502 | Kaspi не ответил, результат неизвестен | **Не повторять.** Прочитайте статус счёта |
| `refund_pending_unknown` | 409 | Результат предыдущего возврата ещё не ясен | **Не повторять.** Подождите |
| `refund_state_conflict` | 409 | Состояние возврата не то, которого ждали | Перечитайте статус счёта и решайте по нему |
| `invoice_not_found` | 404 | Счёта нет или он вам не виден | Проверьте идентификатор и кассира, к которому привязан ключ |

## Три самые частые причины

**1. Счёт не подлежит возврату.** Возврат делается только по **оплаченному** счёту. По `pending`, `expired` и `cancelled` возвращать нечего — на них приходит `invoice_not_refundable`. Полностью возвращённый счёт второй раз тоже не вернуть.

Сначала прочитайте статус через `GET /api/v1/invoices/{id}`: возврат возможен, только если это `paid` или `partially_refunded`.

**2. На счёте Kaspi не хватает денег.** Это самая частая причина ошибки `refund_failed`. Деньги на возврат уходят с вашего счёта Kaspi, а не от нас — мы деньги никогда не держим. Если остатка не хватает, Kaspi операцию не выполняет.

Решение простое: проверьте остаток на счёте Kaspi, пополните при необходимости и повторите возврат. `refund_failed` — одна из немногих ошибок, которую повторять можно, потому что она прямо говорит «не выполнено».

**3. Привязка кассира неактивна.** Возврат тоже идёт через роль «Кассир» в Kaspi. Если привязка оборвалась, не пройдёт ни возврат, ни создание счёта. Восстановите её в разделе **Kaspi**.

К тому же кассир может возвращать только по своим счетам. Если API-ключ привязан к конкретному кассиру, счёт другого кассира он вообще не видит — вам придёт `invoice_not_found`.

## Если результат неизвестен

`refund_unknown` — Kaspi не ответил на запрос. Прошёл возврат или нет, не знаем и мы. `refund_pending_unknown` — результат предыдущего возврата ещё не определён, и новый запрос не принимается.

В обоих случаях порядок одинаковый:

1. **Не повторяйте запрос.** Гарантии идемпотентности здесь нет: второй запрос может стать вторым возвратом.
2. **Подождите** несколько секунд, при необходимости минуту.
3. **Прочитайте статус счёта:** `GET /api/v1/invoices/{id}`. В ответе видны возвраты по этому счёту.
4. Если статус стал `refunded` или `partially_refunded` — возврат прошёл, повторять не нужно.
5. Если статус всё ещё `paid`, а список возвратов пуст — только тогда повторяйте.

И не сообщайте покупателю «деньги вернули», пока не увидели это в статусе счёта.

## Частичный возврат

Если указать поле `amount`, вернётся только указанная сумма, а счёт перейдёт в статус `partially_refunded`. Без `amount` возврат будет полным.

- Сумма не может превышать оплаченную, иначе `invalid_refund_amount`
- При нескольких частичных возвратах их сумма тоже не должна превышать оплаченную
- Поле `reason` стоит заполнять: потом в отчёте будет видно, за что возвращали

После успешного возврата приходит событие `invoice.refunded` или `invoice.partially_refunded`. Если ведёте автоматический учёт, удобнее опираться на эти события, чем опрашивать статус.

## Срок

Возврат возможен не бессрочно: спустя определённое время Kaspi перестаёт разрешать возврат по старой операции. Срок задаёт **Kaspi**, продлить его мы не можем. По просроченному счёту приходит `invoice_not_refundable`.

Поэтому не затягивайте решение о возврате, особенно если покупатель спорит.

## Частые ошибки

- **Обрабатывать ошибку по тексту `message`.** Текст может измениться, код `error` — нет.
- **Включать автоматический повтор при любой ошибке.** В возвратах это опасно.
- **Отвечать покупателю, не проверив статус счёта.**
- **Писать боевой возврат, не проверив его в песочнице.** В песочнице весь цикл прогоняется безопасно.

## Вопросы и ответы

**Когда деньги дойдут до покупателя?** Это определяет Kaspi, на сроки мы повлиять не можем.

**Можно ли отменить возврат?** Нет. Прошедший возврат обратно не откатывается — придётся просить покупателя оплатить заново.

**Возвращается ли комиссия?** Свою комиссию Kaspi определяет сам, уточняйте в поддержке Kaspi. Мы процент с транзакции не берём, поэтому с нашей стороны возвращать нечего.

**Какое право нужно ключу?** `refunds:write`. Если права нет, придёт `insufficient_scope`.

**Что будет, если вернуть дважды?** Деньги уйдут дважды, и откатить это нельзя. Поэтому при ошибках с неизвестным результатом никогда не повторяйте запрос: принципы защиты из статьи [Счета дублируются](/kb/ru/duplicate-invoices) относятся и к возвратам.
