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

# Idempotency

> Safely retry requests without creating duplicate resources.

The YuvexPay API supports idempotency keys to prevent duplicate operations when retrying failed requests.

## How it works

Include an `X-Idempotency-Key` header with a unique string on any POST request that creates a resource:

```bash theme={null}
curl -X POST https://api.yuvexpay.com/v1/payments \
  -H "Authorization: Bearer ypk_test_..." \
  -H "X-Idempotency-Key: order-1234-v1" \
  -H "Content-Type: application/json" \
  -d '{"amount": 49.90, "methods": ["PIX"]}'
```

If you send the same request with the same idempotency key, the API returns the original response instead of creating a duplicate.

## Which endpoints require it

| Endpoint                            | Required |
| ----------------------------------- | -------- |
| `POST /v1/payments`                 | Yes      |
| `POST /v1/payments/:id/refund`      | Yes      |
| `POST /v1/withdrawals`              | Yes      |
| `POST /v1/products`                 | Yes      |
| `POST /v1/customers`                | Yes      |
| `POST /v1/anticipations/simulate`   | Yes      |
| `POST /v1/anticipations`            | Yes      |
| `POST /v1/anticipations/:id/cancel` | Yes      |

## Rules

* **Maximum length:** 100 characters.
* **TTL:** Idempotency keys are valid for 24 hours.
* **Scope:** Keys are scoped per company **and** environment. The same key can be used in sandbox and production without colliding — they're separate keyspaces.
* **Payload check:** If you reuse a key with a different request body, the API returns a `409 Conflict` with error code `IDEMPOTENCY_PAYLOAD_MISMATCH`.
* **Concurrent requests:** If a request with the same key is already being processed, the API returns a `409 Conflict` with error code `IDEMPOTENCY_CONFLICT`.
* **Replay:** Once a request completes **successfully** (`2xx`), subsequent retries with the same key return the original status code and body for the remainder of the 24h window.

<Warning>
  Only successful (`2xx`) responses are stored. Error responses — both client errors (`4xx`) and server errors (`5xx`) — are **not** stored, so retrying with the same key after an error executes the request again. The key stays safe for retries.
</Warning>

## Generating keys

Use a value that uniquely identifies the business operation, not just a random string:

```javascript theme={null}

const key = `order-${orderId}-payment-v1`;


const key = crypto.randomUUID();


const key = Date.now().toString();
```

<Tip>
  Append a version suffix (e.g., `-v1`, `-v2`) to the key if you need to intentionally retry with different parameters.
</Tip>
