# Idempotency

Send an `Idempotency-Key` header so you can retry a request without doing the action twice. Use a unique value for each action, such as a UUID or your own order number.

```http
POST /v1/orders/ord_01JB.../refund
Idempotency-Key: refund-8842-attempt-1
```

The header is accepted on every `POST`, `PATCH` and `DELETE`. It is **required** on endpoints that move money: payments, refunds, payouts and orders.

## What happens

| Situation | Result |
|---|---|
| First request with a key | Runs normally. The status and body are stored for 24 hours. |
| Same key, same method, path and body | Returns the stored status and body, with `Idempotent-Replayed: true`. |
| Same key, different body | `409` `idempotency_key_reused`. |
| Same key while the first request is still running | `409` `idempotency_key_in_use`. Wait a moment and retry. |

Keys are scoped to your tenant and environment. A key in test mode does not match one in live mode.

## What is not stored

- Validation failures (`422`) are not stored, so you can fix the request and retry with the same key.
- `5xx` responses are not stored, so a retry runs again.

## Retry pattern

1. Generate the key once per action, and keep it with the action in your database.
2. Send the request. If it times out or returns `429`, `5xx` or `409 idempotency_key_in_use`, wait with backoff and send it again with the same key.
3. If you get a `409 idempotency_key_reused`, you changed the body. Use a new key for a new action.
