Skip to main content
Documentation

Documentation menu

Idempotency

Use the Idempotency-Key header to retry a non-streaming request without being charged twice, and see what happens when the original response is gone.

Last updated 2026-11-04

Networks fail. If a request times out you cannot tell whether it ran and was billed. Send an Idempotency-Key header and the gateway guarantees that the same request is billed at most once.

Use it

Add the header to a non-streaming completion request (/v1/chat/completions or /v1/messages). Use a unique value per logical request, such as a UUID: 1 to 255 printable ASCII characters.

bash
KEY="demo-$(date +%s)-$RANDOM"
for attempt in 1 2; do
  curl -sS -D - -o /dev/null https://api.ticonai.com/v1/chat/completions \
    -H "Authorization: Bearer $AIP_API_KEY" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: $KEY" \
    -d '{
      "model": "your-model-id",
      "max_tokens": 32,
      "messages": [{ "role": "user", "content": "Say hello." }]
    }'
done

The second response has the header Idempotent-Replayed: true: it is the first response again, no model call was made, and nothing more was charged.

What the gateway does

SituationResult
New keyThe request runs normally and its outcome is remembered for 24 hours.
Same key, same request, finished, and the response is still heldThe original response is replayed with Idempotent-Replayed: true. No model call, no charge.
Same key, different request409 idempotency_conflict. Nothing runs.
Same key, first request still running409 idempotency_in_progress. Wait and retry.
Same key, finished, but the response is no longer available409 idempotency_replay_unavailable. See below.
Streaming requestThe header is ignored.

Keys are scoped to your organization. "Same request" means the same endpoint and the same body, compared exactly as sent: a body that differs only in whitespace counts as different.

When the response cannot be replayed

For privacy, the platform does not store prompts or completions in its database. A replay is therefore served from the gateway's memory, which is bounded and does not survive a restart or move between instances. When the response is gone, the gateway answers 409 idempotency_replay_unavailable. The message includes the id and the cost of the original request. The request is never run again or billed again.

What to do: treat the original request as done and billed, and send the next attempt with a new key if you still need an answer.

Failures do not use up the key

A request that fails before it is billed, for example with a 4xx, a provider error or a timeout, releases its key, so you can retry with the same key. After a request has been billed, the key is kept for the 24 hours.

In the rare case the platform cannot be sure how a request ended (for example, the billing write failed), the key answers 409 idempotency_replay_unavailable instead of risking a second charge.

Patterns

  • Generate the key once, before the first attempt, and reuse it for every retry of that request.
  • Retry with the same key after a timeout or a 5xx.
  • Never reuse a key for a different prompt.
  • If you stream, handle retries yourself: a cancelled or broken stream is billed for what was produced. See Streaming.

More on retries in Best practices and Errors.