Skip to main content
The Causeloop API supports idempotent mutations via the 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.
The header is mandatory, not just recommended, on three path prefixes — /v1/ingest/, /v1/configs/, and /v1/engine/runs. See Mandatory idempotency keys below.

Which requests support idempotency

Idempotency keys are accepted on all mutating methods:
  • POST
  • PATCH
  • PUT
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:
Every example on this page — and every mutating call under those three prefixes in your integration — should always send a key.

How it works

  1. You attach an Idempotency-Key header with a unique value to a mutating request.
  2. The server processes the request normally and caches the response (for 2xx responses only) keyed by (Idempotency-Key, request path).
  3. 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.
  4. The replay response includes an Idempotency-Replayed: true header 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

The key value is a string of your choice. Use a UUID or a similarly unique value. The key is scoped to the combination of key value and request path — the same key sent to a different endpoint is treated as a separate cache entry. Recommended format: UUIDs (v4)

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
If the network drops before you see the response, resend the exact same request with the same 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/issues with key abc-123 and POST /v1/patterns with key abc-123 are 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 Authorization header never reads from or writes to the replay cache — it always executes fresh, and normal auth enforcement (401) still applies downstream.
Do not reuse the same key value for different logical operations on the same endpoint. If you create issue A with key abc-123, then later try to create issue B with the same key on POST /v1/issues, you will receive the cached response for issue A instead.