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

# Idempotency

> Use the Idempotency-Key header to retry payout requests safely.

Payout requests move funds. If a request times out or your connection drops, you can't tell whether the payout was created. An idempotency key lets you retry safely: Tender processes the request at most once and replays the original response to any retry.

## Where it is required

The `Idempotency-Key` header is **required** on:

| Endpoint | |
| - | - |
| `POST /v1/api/payout/fiat` | [Fiat payout](/api-reference/endpoint/payouts/fiat.md) |
| `POST /v1/api/payout/crypto` | [Crypto payout](/api-reference/endpoint/payouts/crypto.md) |

A request without the header is rejected with `400` before anything is processed. Other endpoints ignore the header.

## Choosing a key

* Generate a new, unique key for each payout you intend to make, for example a UUID v4 or your own payout ID.
* Keys can be up to **200 characters**. Leading and trailing whitespace is ignored.
* Store the key with your payout record **before** you send the request, so a retry after a crash reuses it.
* Reuse the key only to retry the **same** payout with the **same** request body.

```http theme={null}
POST /v1/api/payout/fiat
Idempotency-Key: 4f9c2a1e-7b3d-4c8e-9a51-2f6d0e8b7c13
x-access-id: <YOUR_ACCESS_ID>
x-request-id: <UUID_V4>
x-timestamp: <ISO_8601_TIMESTAMP>
authorization: <BASE64_HMAC_SIGNATURE>
Content-Type: application/json
```

The `Idempotency-Key` header is separate from `x-request-id`. Each retry still needs a fresh `x-request-id`, `x-timestamp` and signature (see [Authentication](/api-reference/authentication.md)); only the idempotency key and the body stay the same.

## How it behaves

Keys are scoped to your merchant account **and** the endpoint, so the same key used on `/payout/fiat` and `/payout/crypto` refers to two different requests.

| Situation | Result |
| - | - |
| First request with a new key | Processed normally. |
| Retry with the same key and the same body, after the first request **succeeded** | The original response is returned again. No new payout is created. |
| Retry with the same key while the first request is **still being processed** | `409` `"A request with this Idempotency-Key is already being processed"`. Wait and retry. |
| Same key with a **different** body | `409` `"Idempotency-Key was already used with a different request"`. |
| Retry with the same key after the first request **failed** (any error response) | Processed again as a new request. A failed request releases its key. |
| Same key more than **24 hours** after it was first used | Treated as a new key. |

"Same body" means the same fields with the same values, in the same order. Fields the endpoint doesn't recognise are ignored and don't affect the comparison. The simplest approach is to serialise the body once and resend exactly those bytes.

## Errors

| HTTP status | `message` | Meaning |
| - | - | - |
| `400` | `Idempotency-Key header is required` | The header is missing or empty. |
| `400` | `Idempotency-Key header is too long` | The key is longer than 200 characters. |
| `409` | `A request with this Idempotency-Key is already being processed` | An earlier request with this key hasn't finished. Retry after a short delay with the same key and body. |
| `409` | `Idempotency-Key was already used with a different request` | You reused a key for a different payout. Use a new key. |

## Recommended retry pattern

1. Create the key and save it with your payout record.
2. Send the request.
3. On a network error, timeout, `429`, `500` or `503`, retry with the **same** key and body, using exponential backoff.
4. On `409 … already being processed`, wait a few seconds and retry with the same key.
5. On any other `4xx`, fix the request. If you change the body, use a **new** key.
6. Confirm the final state with the payout `GET` endpoints rather than resending the payout.

Payout routes share a small [rate limit](/api-reference/rate-limits.md), so keep retries spaced out.


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