# Idempotency

Writes are made safe to retry with an idempotency key. Network failures, client timeouts, and proxy retries can leave you unsure whether a `POST` succeeded — an idempotency key lets you re-send the exact same request and be certain you will not create a duplicate booking.

## Where it is required

The `Idempotency-Key` header is **mandatory** on both write steps of the booking flow:

* `POST /api/v1/prebook`
* `POST /api/v1/book`

A write request without the header is rejected with `400` and code `IDEMPOTENCY_KEY_REQUIRED`.

## Header format

```
Idempotency-Key: 3b2a1c0d-5e6f-4a8b-9c0d-1e2f3a4b5c6d
```

| Property | Constraint                                           |
| -------- | ---------------------------------------------------- |
| Length   | 1–255 characters                                     |
| Content  | An opaque string. A UUID v4 is the recommended form. |

## Replay vs conflict

The server records the outcome of the first request seen for a given key, scoped to your tenant, and matches subsequent requests against it:

* **Replay — same key + same payload.** Returns the **same** result as the original request (the same booking, with `200`), without creating or mutating anything. Safe to retry as many times as you need.
* **Conflict — same key + different payload.** Returns `409` with code `IDEMPOTENCY_KEY_CONFLICT`. A key is a one-time promise about one specific request body; reusing it with a changed body is rejected so a key can never silently apply to a different operation.

```bash
# First call — creates the booking, returns 201.
curl -s -X POST https://ari.console.adrasis.com/api/v1/book \
  -H 'Authorization: Bearer eyJ...' \
  -H 'Idempotency-Key: 3b2a1c0d-5e6f-4a8b-9c0d-1e2f3a4b5c6d' \
  -H 'Content-Type: application/json' \
  -d @book.json

# Retry after a timeout — SAME key, SAME body → 200, the same booking. No duplicate.
curl -s -X POST https://ari.console.adrasis.com/api/v1/book \
  -H 'Authorization: Bearer eyJ...' \
  -H 'Idempotency-Key: 3b2a1c0d-5e6f-4a8b-9c0d-1e2f3a4b5c6d' \
  -H 'Content-Type: application/json' \
  -d @book.json

# SAME key, DIFFERENT body → 409 IDEMPOTENCY_KEY_CONFLICT.
```

A conflict response looks like:

```json
{
  "code": "IDEMPOTENCY_KEY_CONFLICT",
  "message": "Idempotency-Key was reused with a different request body"
}
```

## TTL behaviour

The recorded result for a key is retained for a bounded window, after which the key is forgotten. Within the window, a repeat of the same request replays the stored outcome. After the window elapses, the same key is treated as new — so do not rely on an old key to deduplicate a request days later. In practice, retries that protect against network failures happen within seconds to minutes, well inside the retention window; generate a fresh key for each genuinely new operation.

## Recommended key-generation strategy

1. **One key per logical operation.** Generate a fresh UUID v4 at the moment you decide to prebook (and another when you decide to book), before the first send.
2. **Reuse the key across retries of that same operation.** When a call times out or you are unsure it landed, re-send with the **same** key and the **identical** body. You will either create the booking (first time) or replay the existing result — never a duplicate.
3. **Persist the key with the operation** so a process restart still re-sends the same key rather than starting a new one.
4. **Never reuse a key for a different booking** or a changed payload — that is exactly the case the conflict response guards against.

## Next steps

* [The booking flow](/developer/booking-flow.md) — where prebook and book sit in the lifecycle.
* [Errors](/developer/errors.md) — the full status-code reference, including `409`.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://adrasis.gitbook.io/developer/idempotency.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
