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

# Idempotency

> Safely retry value-affecting requests without creating duplicates.

Value-creating or replacing `POST`/`PUT` requests accept — and generally require — an
`Idempotency-Key` header. This includes creating customers, payment routes, webhook subscriptions,
API keys, Treasury beneficiaries, payouts, withdrawals, quotes, and conversions. It lets you retry
after a network error without creating a duplicate.

<Note>
  Direct-route transfers are created automatically when a route is funded. Treasury is an explicit
  wallet API, so its payouts, stablecoin withdrawals, conversion quotes and quote acceptance are all
  idempotent writes.
</Note>

```bash theme={null}
curl -X POST https://api.sandbox.rails.wayex.com/v1/customers \
  -H "Authorization: Bearer YOUR_SECRET_KEY" \
  -H "Idempotency-Key: a-unique-key-per-operation" \
  -H "Content-Type: application/json" \
  -d '{"email":"customer@example.com"}'
```

## How it works

* Use a **unique key per logical operation** (a UUID is ideal). Reuse the *same* key when retrying that
  same operation.
* Persist the key before the first network attempt. A browser refresh, MFA step-up, worker restart, or
  client timeout must not generate a replacement key for the same action.
* **Same key + same parameters** → you get back the original, cached response (with an
  `Idempotency-Replayed: true` header). The action runs once.
* **Same key + same parameters while the original request is still running** → the API waits
  briefly (up to about five seconds) for the original to finish and, if it does, returns its cached
  response. Otherwise you get `409` (`idempotency_key_in_progress`) with a `Retry-After` header —
  wait at least that long, then retry the identical request. Never switch to a new key: the
  original action may still complete.
* **Same key + different parameters** → the request is rejected with `409`
  (`idempotency_key_conflict`), protecting you from accidentally reusing a key for a different
  operation.
* Keys are isolated per tenant account — all credentials belonging to the same tenant account share
  one idempotency namespace, so use a unique key per logical operation regardless of which API key
  sends it. Never reuse a key across separate tenant accounts.
* Keys are retained for **7 days**. After that, the same key is treated as brand new and the request
  would execute again — beyond the window, recover a lost outcome by fetching the resource by its
  Wayex ID or your `externalReference` instead of retrying.

<Note>
  Idempotency keys are scoped to supported `POST`/`PUT` writes, which require a secret key (`sk_`).
  Read requests (`GET`) are naturally idempotent and do not need a key. The current `PATCH` and
  `DELETE` resources do not use this header: read current state before retrying an unknown response,
  as explained on each endpoint page.
</Note>

## Unknown money outcomes

If a payout, conversion, or withdrawal response is lost, retry the identical request with the same
key. Do not create a replacement operation while the original is `accepted`, `submitted`, held, or
unknown. Fetch the original by its Wayex ID or your `externalReference` and inspect its reservation
state first. See [Operations and reconciliation](/treasury/operations-and-reconciliation).

## Webhooks and ordering

Wayex is event-driven: webhooks are the source of truth for asynchronous state. **Do not assume webhook
ordering** — dedupe by the reference on each event and, when in doubt, fetch the current resource state
with a `GET`. See [Developers](/console/developers) for subscription setup and signature verification.
