Adrasis™

Idempotency

The mandatory Idempotency-Key header on book: replay vs conflict semantics, TTL behaviour, and a recommended key-generation strategy.

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/book
  • POST /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 409 with code IDEMPOTENCY_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.

  1. One key per logical operation. Generate a fresh UUID v4 at the moment 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 without creating 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. 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.