Idempotency-Key header. Sending the same key on a repeated request replays the original response instead of executing the operation again — making it safe to retry network errors and timeouts without worrying about duplicate creates or double-charges.
Which requests support idempotency
Idempotency keys are accepted on all mutating methods:POSTPATCHPUT
GET and DELETE requests are inherently idempotent and ignore the header.
On most endpoints the header is optional — recommended for safe retries, but the request is processed normally without one. A specific set of paths (below) makes it required.
Mandatory idempotency keys
Three path prefixes have real duplicate-side-effect risk on a client retry — a second ingest batch, a second config version, a second full engine run — so the middleware rejects mutating requests to them outright when the header is missing:
A request to one of these prefixes without an
Idempotency-Key header is rejected before it reaches the handler:
How it works
- You attach an
Idempotency-Keyheader with a unique value to a mutating request. - The server processes the request normally and caches the response (for 2xx responses only) keyed by
(Idempotency-Key, request path). - If you send a second request with the same key and path, the server returns the cached response immediately — the handler is never called again.
- The replay response includes an
Idempotency-Replayed: trueheader so you can distinguish a fresh response from a cached one.
Only successful (2xx) responses are cached. If the original request returned a 4xx or 5xx, the next request with the same key will be executed again.
The Idempotency-Key header
Cache lifetime
Idempotency responses are cached for 24 hours. After that window, a request with the same key will be processed as a new request. When Redis is configured (REDIS_URL), the cache is shared across all API replicas. Without Redis, the cache is in-process — a request hitting a different replica will be treated as new. For production deployments with multiple API instances, configure Redis to ensure consistent idempotency guarantees.
Example: safely creating an issue
Generate a unique key before the request, then reuse it on retries:Example: ingesting a batch (mandatory key)
POST /v1/ingest/batch is one of the mandatory-key paths — omit the header and you get 400 idempotency_key_required before any record is processed:
curl
IDEM_KEY — you get back the original {accepted, rejected, job_id, issue_ids, engine_status_summary} ack, not a second copy of the issue.
Response headers
Key scoping
The cache key is(caller, Idempotency-Key value, request path) — the caller’s Authorization header is part of the key, not just the header value and path. This means:
POST /v1/issueswith keyabc-123andPOST /v1/patternswith keyabc-123are separate cache entries.- The same key reused across different paths does not cause cross-resource collisions.
- Two different callers (different workspaces, different users, or a service account vs. a human) can never collide on the same cache entry, even if they happen to send the identical key and path.
- A request with no
Authorizationheader never reads from or writes to the replay cache — it always executes fresh, and normal auth enforcement (401) still applies downstream.