> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flowlix.eu/llms.txt
> Use this file to discover all available pages before exploring further.

# Refunds

> Create a full or partial Refund and track it through the parent Payment

A Refund returns all or part of a `SUCCEEDED` Payment to the customer's card.
It always uses the Payment currency and is processed asynchronously.
A Refund does not use shopper 3D Secure and never requires a browser redirect.

## Refund procedure

1. Retrieve the Payment and confirm that it is `SUCCEEDED`.
2. Read its current `amount_refundable`.
3. A **full refund** (`refund_type: FULL`) returns the full original Payment amount
   when nothing has been successfully refunded and no other Refund is in progress.
   Returning the remaining amount after a **succeeded** partial Refund is `PARTIAL`.
   A failed partial Refund does not by itself prevent a later `FULL` Refund.
   To return all currently available funds, set `amount` to `amount_refundable`.
4. Create the Refund with a new deterministic `Idempotency-Key` and store the
   returned `refund.id`.
5. `GET` the parent Payment, select the object in `refunds[]` whose `id` matches
   the stored ID, and keep retrieving the Payment until that Refund is
   `SUCCEEDED` or `FAILED`.

## Create a Refund

```bash theme={null}
curl -X POST https://api.flowlix.eu/v1/refunds \
  -H "Authorization: Bearer $FLOWLIX_API_KEY" \
  -H "Idempotency-Key: refund-ord_1234-1" \
  -H "Content-Type: application/json" \
  -d '{
    "payment_id": "pay_q7Mk2Np8Vr4Xt6Yz9Ab3Cd5E",
    "amount": 1500,
    "merchant_reference": 3456789012,
    "reason": "Customer requested a partial refund"
  }'
```

`amount` is required and expressed in minor units. `reason` is also required
and accepts at most 50 characters. `merchant_reference` is optional; when
supplied, it must be a 10-digit integer. Currency is inherited from the
Payment.

A Payment may have several partial Refunds. Flowlix rejects a request that
exceeds the latest `amount_refundable` with
`amount_exceeds_refundable`.

A successful create request returns `201 Created` and a Refund object. This
means the Refund exists; it does not mean that funds have already been returned.
The returned status is `PROCESSING` after a submitted Refund, or `FAILED` when
submission was definitively rejected. A `201` response with `FAILED` is an
object outcome, not an HTTP request error.

```json theme={null}
{
  "id": "ref_L9xQ4wE2rT8yU6iO3pA7sD1f",
  "payment_id": "pay_q7Mk2Np8Vr4Xt6Yz9Ab3Cd5E",
  "amount": 1500,
  "currency": "EUR",
  "merchant_reference": 3456789012,
  "reason": "Customer requested a partial refund",
  "refund_type": "PARTIAL",
  "status": "PROCESSING",
  "created_at": 1719795600,
  "updated_at": 1719795660,
  "livemode": false
}
```

## Refund statuses

| Status       | Terminal | What it means                                           | What you should do                                                                             |
| ------------ | -------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `PENDING`    | No       | The Refund was accepted and is awaiting processing.     | Keep the order's refund state pending.                                                         |
| `PROCESSING` | No       | The Refund was submitted to downstream payment systems. | Continue retrieving the parent Payment.                                                        |
| `SUCCEEDED`  | Yes      | The Refund completed.                                   | Mark the refunded amount in your system.                                                       |
| `FAILED`     | Yes      | The Refund could not be completed.                      | Read `failure.code` and `failure.message` before deciding whether a new Refund is appropriate. |

A non-terminal Refund can remain unresolved; a timeout in your system is not
a confirmed failure. If it stays pending longer than expected, contact support
with the Payment ID, Refund ID, and `Request-Id`. Do not issue a replacement
Refund while the original outcome is uncertain.

## Track the Refund on its parent Payment

Subscribe to [Refund webhooks](/guides/webhooks#event-types) for notifications.
Use the parent Payment to reconcile the latest Refund status and remaining
refundable amount, including when an event is delayed or arrives out of order.

```bash theme={null}
curl https://api.flowlix.eu/v1/payments/pay_q7Mk2Np8Vr4Xt6Yz9Ab3Cd5E \
  -H "Authorization: Bearer $FLOWLIX_API_KEY"
```

Find the stored Refund ID in the Payment's `refunds[]` array. The array also
lets you reconcile `amount_refunded` and `amount_refundable` before another
partial Refund.

## Retry safely

* Same key and an equivalent effective request identity: Flowlix returns the
  original Refund result.
* Same key and a different effective request identity: Flowlix returns
  `409 idempotency_key_reused`.
* Original request still being processed: Flowlix returns
  `409 idempotency_key_in_use`; wait briefly, then retry with the same key and
  an equivalent effective request identity.
* A distinct Refund required by a new business decision: use a new key after
  retrieving the latest `amount_refundable`.

See [Idempotency](/guides/idempotency) and
[operation failures](/guides/operation-failures) for the complete handling
rules.
