An idempotency key prevents duplicate writes during retries. Network failures,
client timeouts, and proxy retries can leave the outcome of a POST unknown.
Re-send the exact same request with the same key to create or replay the result
without a duplicate write.
Where it is required
The Idempotency-Key header is mandatory on the finalize step of every
booking flow:
POST /api/v1/bookPOST /api/v1/transfer/book,POST /api/v1/tour/book,POST /api/v1/flight/book,POST /api/v1/package/book
A finalize request without the header is rejected with 400 and code
IDEMPOTENCY_KEY_REQUIRED.
POST /api/v1/prebook does not take the header. Prebook mints a token
without writing anything, so each retry mints a fresh token.
On POST /api/v1/bookings/{public_id}/cancel the header is optional (cancel
is idempotent by state: an already-cancelled booking returns 200), with one
exception: cancelling a package booking requires it. When you do send a
key on cancel, the same replay/conflict semantics apply.
Webhook endpoint creation, secret rotation, verification, test and manual
delivery retry also require Idempotency-Key. Their exact request replay is
retained for 24 hours. See Booking webhooks for the
separate If-Match requirement on endpoint changes.
Header format
Idempotency-Key: 3b2a1c0d-5e6f-4a8b-9c0d-1e2f3a4b5c6d
| Property | Constraint |
|---|---|
| Length | 1–128 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 authenticated partner account and operation, and matches subsequent requests against it. Profiles and credential rotation do not create a second idempotency namespace inside the same account. The resolved profile is part of the booking request identity: reusing a key under another profile conflicts even if the JSON body is unchanged:
- Replay: same key + same payload. Returns the same result as the
original request (the same booking, with
200), without creating or mutating anything. Further identical retries replay that result. - Conflict: same key + different payload. Returns
409with codeIDEMPOTENCY_KEY_CONFLICT. A key identifies one specific request body. Reusing it with a changed body is rejected, so it cannot silently apply to a different operation.
# 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:
{
"error": {
"code": "IDEMPOTENCY_KEY_CONFLICT",
"message": "Idempotency-Key reused with a different payload",
"retryable": false,
"trace_id": "0f2c9d6e-7b1a-4c3e-9a2f-1d6e7b1a4c3e"
}
}
TTL behaviour
The recorded result for a key is retained for 24 hours, 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. Do not rely on an old key to deduplicate a request days later. Retries for network failures usually occur within seconds or minutes, inside the retention window. Generate a fresh key for each new operation.
Recommended key-generation strategy
- One key per logical operation. Generate a fresh UUID v4 at the moment you decide to book, before the first send.
- 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 without creating a duplicate.
- Persist the key with the operation so a process restart still re-sends the same key rather than starting a new one.
- Never reuse a key for a different booking or a changed payload. The conflict response rejects this case.
Next steps
- The booking flow: where prebook and book sit in the lifecycle.
- Errors: the full status-code reference, including
409.