> For the complete documentation index, see [llms.txt](https://docs.loomgate.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.loomgate.io/concepts/refunds.md).

# Hoàn tiền

Hoàn được bao nhiêu, phí hoàn tiền, trạng thái và cách gọi an toàn.

Bạn hoàn tiền cho người mua của một payment đã `succeeded`, từ dashboard (trang chi tiết giao dịch) hoặc bằng `POST /partner/v1/refunds`. Có thể hoàn nhiều lần, mỗi lần một phần.

## Hoàn được bao nhiêu

{% hint style="info" %}
**Phí không bao giờ được hoàn**, cho người mua cũng như cho bạn.
{% endhint %}

Mỗi payment có `amount_refundable`, số còn có thể hoàn:

```
amount_refundable = amount_total − processing_fee − bank_fee − amount_refunded
```

`amount_refundable` là 0 khi payment chưa `succeeded`.

|                               | Người mua chịu phí | Bạn chịu phí |
| ----------------------------- | ------------------ | ------------ |
| `amount`                      | 10000              | 10000        |
| `amount_total`                | 10320              | 10000        |
| `processing_fee` + `bank_fee` | 290 + 30           | 290 + 30     |
| `amount_refundable` ban đầu   | **10000**          | **9680**     |

* Người mua chịu phí: người mua được hoàn tối đa `amount`; dòng phí họ đã trả không được hoàn.
* Bạn chịu phí: hoàn tối đa phần bạn đã nhận. Muốn trả lại người mua toàn bộ, bạn tự chuyển phần chênh lệch ngoài Loomgate.

Không gửi `amount` thì hoàn hết `amount_refundable`. Vượt quá trả `refund_exceeds_remaining`; payment chưa thành công trả `payment_not_refundable`.

## Phí hoàn tiền

Mỗi lần hoàn tiền có thể có `refund_fee` theo biểu phí của bạn. Phí này tính cho bạn, nằm **ngoài** số tiền hoàn (người mua vẫn nhận đủ `amount` của refund) và được trừ vào số dư của bạn.

## Trạng thái

| Trạng thái              | Nghĩa                                                                                           |
| ----------------------- | ----------------------------------------------------------------------------------------------- |
| `pending`, `processing` | Đang xử lý. Số tiền đã được giữ chỗ: `amount_refunded` của payment đã tính cả refund đang xử lý |
| `succeeded`             | Đã hoàn. Webhook `refund.succeeded`                                                             |
| `failed`                | Không hoàn được; số tiền giữ chỗ được trả lại cho payment. Webhook `refund.failed`              |

## Gọi an toàn với `Idempotency-Key`

Gửi header `Idempotency-Key` để thử lại mà không bao giờ hoàn hai lần:

* Sinh **một key cho mỗi lần hoàn tiền** (ví dụ `refund-1042-1`), lưu nó trước khi gọi, và dùng lại đúng key đó mỗi lần thử lại sau timeout, lỗi mạng, 429 hay 5xx.
* Cùng key, cùng body: nhận lại đúng refund lần đầu (cùng `id`, trạng thái hiện tại), kể cả khi hai request chạy cùng lúc.
* Cùng key, body khác: `409 idempotency_key_reused`. Hoàn thêm một phần nữa thì dùng key mới.
* Request kết thúc bằng lỗi không lưu gì: gửi lại cùng key sẽ chạy lại từ đầu.
* Không dùng key mà gặp timeout: đọc lại `amount_refunded` của payment trước khi gọi lại, nếu không có thể hoàn hai lần.

Key dùng chung giữa tạo payment và hoàn tiền (kể cả hoàn tiền trên dashboard), nên đặt tiền tố khác nhau cho hai loại.

## Ảnh hưởng tới số dư

Khi payment còn mốc chưa mở khóa, số tiền hoàn rồi phí hoàn tiền được trừ vào các mốc còn khóa của chính payment đó, mốc có giờ mở khóa gần nhất trước rồi tới mốc kế tiếp (`deducted` của mốc tăng, `remaining` giảm); phần không còn mốc khóa nào chứa thì trừ ngay vào số dư khả dụng. Khi mọi mốc đã mở khóa, hoàn tiền trừ ngay vào số dư khả dụng. Xem [Số dư và giờ mở khóa](/concepts/balance.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.loomgate.io/concepts/refunds.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
