# Idempotency

Send an `Idempotency-Key` header on `POST /v1/predict` and a retry can never charge
you twice. This page is the whole contract — each statement below is a promise.

## The seven promises

1. **The header is optional, and absence is never an error.** A request without an
   `Idempotency-Key` is processed normally and charged per call. Nothing about the
   request changes except that a retry of it is a new, charged request.

2. **Keys are scoped to your Account.** One Account can never replay another
   Account's result, whatever key it sends. Two Accounts using the same key value
   never touch each other.

3. **The replay window is 24 hours.** Send the same request with the same key inside
   the window and you receive the stored response — one Spend, however many sends.
   After 24 hours the stored response expires, and a repeat is a new, charged
   request.

4. **Only successful responses are stored.** A failed request — one that was refunded
   — is not stored against its key. So retrying the same key after a
   [`502`](/errors/upstream-unavailable) or a [`504`](/errors/upstream-timeout) is a
   genuine fresh attempt: it spends again, and it can succeed. This is what makes
   retry-after-a-5xx work; a stored failure would replay the failure.

5. **The same key with a different body is a conflict, not a replay.** The request is
   refused as [`422 idempotency-key-conflict`](/errors/idempotency-key-conflict) and
   nothing is charged. Send the changed request with a new key.

6. **An identical request already in flight is answered, not raced.** While the first
   send is still being processed, an identical second send receives
   [`409 duplicate-request-in-flight`](/errors/duplicate-request-in-flight) with a
   `Retry-After` header, and nothing is charged for it. Wait the interval, ask again,
   and you get the stored result of the first send.

7. **Zero-cost endpoints ignore the header entirely.** `POST /v1/validate` consumes
   no Credits and makes no Ledger call, so there is no Spend for a key to protect —
   an `Idempotency-Key` sent to it is ignored.

## Why this API never retries for you

No request is ever retried on our side. A Metered Call can consume a Credit before it
fails, so a gateway that re-issued requests on its own could charge twice for one
intent. Retry belongs to you, and the `Idempotency-Key` is what makes it safe.
