Reference
Idempotency
Retry a request safely without paying twice. Stripe's convention, backed by a database constraint rather than a cache read.
A network timeout does not tell you whether the work happened. Send an Idempotency-Key and the
retry is safe.
curl https://api.dawnstackai.com/v1/chat/completions \
-H "Authorization: Bearer $DAWNSTACK_API_KEY" \
-H "Idempotency-Key: 8f2a1c94-6e3b-4d5a-9c11-2f7e0a1b3d44" \
-H "Content-Type: application/json" \
-d '{"model":"llama-3.1-8b","messages":[{"role":"user","content":"Hello"}]}'import uuid
key = str(uuid.uuid4()) # generated ONCE, reused across every retry of this request
reply = client.chat.completions.create(
model="llama-3.1-8b",
messages=[{"role": "user", "content": "Hello"}],
extra_headers={"Idempotency-Key": key},
)Generate the key once, before the first attempt, and reuse it for every retry of that same request. A key generated inside the retry loop protects nothing.
What happens on a repeat
| Situation | Response |
|---|---|
| Same key, same body, first request finished | The original response, replayed, free. Carries Idempotent-Replay: true |
| Same key, same body, first request still running | 409. Wait a moment and retry |
| Same key, different body | 422. A key identifies one request, not a slot |
| Same key, more than 24 hours later | Treated as new. Records expire |
A replay is byte-identical to the original, including the id, the token counts and the cost. It is
not re-run and it is not charged again.
The claim is a database constraint
Two consequences you can rely on:
- A failed request releases its key. A crash does not lock you out of the retry the failure was inviting.
- A claim that is never completed expires after five minutes. A worker that dies mid-request does not leave a key nobody can ever use.
Not with streaming
Idempotency-Key plus stream: true is a 400. Replaying a stream from cache would mean buffering
every response on the chance of a retry. Refusing is honest; accepting the header and quietly
ignoring it would let you believe you were protected when you were not.
When to use it
Any request where a double charge matters and a retry is plausible: a queue worker, a webhook handler, anything behind a proxy with its own timeout. It costs nothing when nothing goes wrong.