Skip to main content
Any POST that creates a billable resource (generations, comparisons, uploads, webhooks) accepts an Idempotency-Key header. We store the response for 24 hours; the same key within the window replays the original response instead of creating a new resource.

When to use it

  • Always for retries on network errors.
  • Always on POST endpoints that consume credits.
  • Pair with exponential backoff for 502/500.

How to generate keys

A UUID v4 per request is the standard. The key must be ≤ 200 characters and unique per logical operation.

Replay behavior

If the same key is reused within 24h with the same body, you get the original response back and an Idempotent-Replayed: true header:
If the body is different but the key is the same, we return 409 idempotency_key_reuse. This prevents accidentally booking a different generation under the same key.

What’s stored

We snapshot the response body and HTTP status. Headers other than X-Request-Id are NOT replayed (so Set-Cookie won’t leak, for instance).

Expiration

24 hours from creation. After that, the key is forgotten and a new POST with the same key creates a new generation.

Anti-patterns

  • ❌ Reusing the same UUID across logically different requests.
  • ❌ Generating keys from Date.now() — collisions.
  • ❌ Sending an Idempotency-Key on GET (silently ignored).
  • ❌ Using the key as a “session” identifier — it’s per-request.

Combined with retry logic

The same idempotencyKey is used on every retry — so the 4th attempt that finally succeeds doesn’t create a 5th generation.