Skip to main content

Why idempotency keys?

Network failures and timeouts can leave you uncertain whether a POST succeeded. If you retry a generation request and the original call had actually completed, you’d be charged twice. Idempotency keys let you safely retry: the same key + same body returns the original response, never a second one.

How to use

Pass an Idempotency-Key header on POST /v1/images, POST /v1/videos, or POST /v1/files. Use any opaque value, 1 to 256 characters. UUID v4 is recommended. The vendor-prefixed header Aurous-Idempotent-Key is accepted as an alias for Idempotency-Key.
If you retry with the same key and the same body, the original response is replayed:

Rules

Recovering after a dropped connection

If your POST times out and you don’t know whether it landed, retry with the same Idempotency-Key:
  • If the original is still running, you’ll get 409 idempotency_key_in_use. There’s no Retry-After on this response — use your own backoff (e.g. 0.5s doubling to ~8s) and retry the same key.
  • Once it reaches a terminal state, the same key returns the original response with Aurous-Idempotent-Replayed: true. Read the generation id from that body.
Two rules make this reliable:
  1. Generate and persist your Idempotency-Key before the request, keyed to your own operation record. The 409 does not echo the original generation id, so your stored key is your only handle on the in-flight call until it completes.
  2. Only retry-loop on 409 idempotency_key_in_use if you have not changed the body or route. The same code is also returned when a key is reused with a different body or route — that’s a client bug to fix, not a transient state to wait out.

Caveats

  • Keys are scoped per team — collisions across teams are impossible.
  • Keys expire after 24 hours. After that, the same key starts fresh.
  • If a request is interrupted server-side before completing (a rare mid-flight crash), the key is freed as soon as the platform observes the failure — retry with the same key right away. The 24h expiry is only a backstop for the rarer cases where the platform can’t free the key right away.
  • Body comparison uses canonical JSON (lexicographic key order). {"a":1,"b":2} and {"b":2,"a":1} are treated as identical.
  • The header is optional; absent header behaves like a fresh non-idempotent request every time.
  • 503 responses are never cached against your key — retry with the same key.