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

# Retry safely with idempotency keys

> Send an Idempotency-Key with every PanoFlow POST that moves money so you can retry timeouts and partner errors without paying twice.

An idempotency key lets you retry a PanoFlow request without doing the work twice. If a payment request times out or a partner bank is unavailable, send the same request again with the same `Idempotency-Key` and PanoFlow either finishes the original or replays its response.

## When to send one

The `Idempotency-Key` header is **required on every POST that moves money or creates a money-moving object**:

| Operation | Endpoint |
| - | - |
| Create a transfer | `POST /v1/transfers` |
| Create a batch | `POST /v1/batches` |
| Schedule a payment | `POST /v1/scheduled-payments` |
| Prepare a pay run | `POST /v1/payroll/runs` |
| Approve a pay run | `POST /v1/payroll/runs/{run_id}/approve` |
| Execute a pay run | `POST /v1/payroll/runs/{run_id}/execute` |

On every other `POST` the header is optional, and PanoFlow honours it when you send it.

## How it works

* The key is a string you generate, 1 to 255 characters. A UUIDv4 is recommended.
* PanoFlow stores each key for 7 days.
* Same key and same body: you get the original response back, with the header `Idempotent-Replayed: true`.
* Same key and a different body: `409 idempotency_key_reused`.

```bash theme={null}
curl https://api.panoflow.io/v1/transfers \
  -H "Authorization: Bearer pk_live_..." \
  -H "Idempotency-Key: 6f1c2a7e-4b8d-4f0e-9a3b-2d5c7e9f1a04" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

## Retrying

Generate the key once per payment you intend to make, store it with the payment in your system, and reuse it on every retry of that payment.

| Response | What to do |
| - | - |
| `502` or `503` (`bank_unavailable`, `partner_timeout`) | Retry with the same idempotency key. |
| `500 internal_error` | Retry with the same idempotency key. |
| `409 idempotency_key_reused` | You sent a different body under a key you already used. Don't change the body of a retry; use a new key only for a new payment. |
| A network timeout with no response | Retry with the same idempotency key. |

> [!NOTE]
>
> Once a payout has gone to the bank, a timeout on PanoFlow's side is resolved by a status check with the bank, never by sending the payment again.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.