Retries should repeat the result, not the charge

Why model requests need canonical idempotency keys, request fingerprints, and deterministic recovery across billing and inference.

A client can lose the response after a model finishes. A proxy can retry. A mobile connection can disappear between reservation and settlement. Without idempotency, each recovery attempt risks creating another hold, another inference run, or another charge.

01

A key identifies one logical request

OurToken requires a canonical UUID v4 in the Idempotency-Key header for chat completions. The first accepted request binds that key to the authenticated API key and a fingerprint of the normalized model request.

Repeating the same key and fingerprint returns or recovers the same logical operation. Reusing the key for different input returns a conflict. This distinction prevents accidental duplicate work without letting a key alias unrelated requests.

Retry-safe request
curl https://api.ourtoken.dev/v1/chat/completions \
  -H "Authorization: Bearer $OURTOKEN_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 9b97755f-6a36-4a6f-a682-5aa22a67ac47" \
  -d '{
    "model": "publisher/model-name",
    "messages": [{"role": "user", "content": "Explain hold settlement."}]
  }'

02

Idempotency crosses subsystem boundaries

Protecting only the HTTP response is insufficient. The usage record and wallet reservation use deterministic identities derived from the API key and request key. Settlement has its own replay protection. If two workers race, only one owns the active operation and the losing reservation is released.

This makes recovery possible after partial failure. The service can distinguish a completed request, an in-progress request with a live lease, and stale state that needs reconciliation.

03

The fingerprint prevents surprising replays

An idempotency key is not a cache key. The server fingerprints the normalized provider request, including the stable model contract and bounded generation parameters. A retry must describe the same logical operation.

Authentication scope matters too: keys are resolved within the calling API key, so one customer cannot discover or replay another customer’s request by guessing an identifier.

  • Generate a fresh UUID v4 for each new logical request.
  • Persist it before sending so a network retry can reuse it.
  • Reuse it only when the normalized request body is unchanged.
  • Treat an idempotency conflict as a client bug, not a transient failure.

04

Recovery is part of the API contract

A reliable model API must specify what happens after ambiguity, not only on the happy path. Deterministic request identity lets the server repair stale holds, finish settlement, or replay a result without guessing whether the customer intended a new charge.

The takeaway

Bind one client-generated key to one normalized request, carry that identity through reservation and settlement, and make conflicts explicit.