---
title: Idempotency
description: Use idempotency keys to retry mutating REST requests safely, replay completed responses, and avoid executing an operation twice.
---

Mutating requests may include an idempotency key:

```http
UDX-Idempotency-Key: <unique-key>
```

The `UDX-Idempotency-Key` header is optional for mutating requests.

If you omit it, the exchange cannot recognize a retry as a duplicate, so a repeated request executes again. The request still uses normal authentication and member rate limits.

The key is the only replay mechanism. A client ID such as `client_order_id`, `client_rfq_id`, or `client_quote_id` correlates a resource with your own records; it does not replay a response.

The exchange does reject a second order that reuses a `client_order_id` within the same account and market, so an accidental duplicate order becomes a `rejected` order, but a repeated RFQ or quote creates a second one. A second account that reuses a `client_account_id` within your member is rejected with HTTP `409 Conflict`. See [Asynchronous Writes](/reference/asynchronous-writes) for how to reconcile a write whose outcome you do not know.

When you need safe retry and replay behavior, use a UUIDv4 or another high-entropy string up to 255 characters. Generate one key for each operation and reuse it only when retrying that operation.

## Retry the Same Operation

For a request that included an idempotency key, retry with the same method, path, query string, body, and key. The exchange returns the original response instead of performing the operation again. A replayed response includes:

```http
UDX-Idempotent-Replayed: true
```

Never reuse an idempotency key for a different request. The exchange rejects that reuse with HTTP `422 Unprocessable Content` instead of executing the new operation. If an identical request with the same key is still running, the exchange rejects the duplicate attempt with HTTP `409 Conflict`; wait, then retry it with the same key.

When a request includes an idempotency key, the key is part of the signed message, so the signature must include the same key sent in the request. An unkeyed request is signed without that value. See [Authentication](/reference/authentication#sign-with-an-api-key).

## Replay Window

A completed response stays replayable for a bounded time after it completes. Once the window lapses, the exchange forgets the key: a request that reuses it is treated as new and executes again, and a different request under that key is no longer rejected with `422`. A repeated account creation with a `client_account_id` is then rejected with `409 Conflict` rather than creating a second account.

| Operation | Window |
| --- | --- |
| Create a quote, cancel a quote | 5 minutes |
| Every other mutating request | 24 hours |

Quotes are valid for seconds, so a quote write retried after five minutes cannot duplicate a live quote.

## Handle Rejected Requests

| Status | Meaning | What to do |
| --- | --- | --- |
| `400` | A supplied idempotency key is empty or invalid. | Send a valid key, or omit the header. |
| `409` | The first request is still running. | Wait, then retry with the same key. |
| `409` | The operation completed, but its response was too large to replay. | Do not send the operation again. Read the affected resource to confirm the result. |
| `422` | The key was already used for a different request. | Use a new key for the new operation. |

The problem's `type` distinguishes the two `409` cases: `urn:udx:problem:request-with-header-in-progress` while the first request is still running, and `urn:udx:problem:response-too-large-to-replay` when it completed without a replayable response. Do not use `detail` to choose a recovery path.

A request rejected by a REST [rate limit](/reference/rate-limits) is not saved as the operation's result. Wait for `Retry-After`, then, if the mutation used a key, retry with that same key and a new timestamp and signature.
