Why
Network failures, timeouts, and client retry policies mean the same write request can arrive at the server more than once. Constants requires everyPOST, PUT, PATCH, and DELETE to carry an Idempotency-Key header
so the server can detect and coalesce retries into a single write.
Without this, a retried POST /v1/run/my-tool could execute your tool
twice, double-charge quota, or create duplicate records. With it, the
second request returns the first response — cached — and the tool runs
exactly once.
This is a hard requirement. Write requests without an
Idempotency-Key header are rejected with 400 Bad Request.How to use it
Generate a fresh UUID v4 per logical user attempt (not per retry) and send it as theIdempotency-Key header:
In code
Rules
| Situation | Server response |
|---|---|
| Header missing or not a UUID v4 | 400 Bad Request |
| Same key + same request body + handler still running | 409 Conflict |
| Same key + same request body + handler finished | Cached response replayed (adds Idempotent-Replay: true header) |
| Same key + different request body | 422 Unprocessable Entity |
| New key | Handler runs; response cached for 24 hours |
- The cache lives 24 hours. After that, reusing the key starts over as a new request.
- Keys are scoped to the authenticated user. Two different API keys (even for the same workspace) have separate idempotency namespaces.
GET,HEAD, andOPTIONSrequests don’t need the header.
MCP
MCP clients don’t need to sendIdempotency-Key explicitly. The server
uses the JSON-RPC id field — which every MCP client already sends and
reuses on retry — to dedupe tools/call invocations automatically.
Slack
Slack webhooks delivered to Constants are deduplicated using Slack’s ownevent_id as the idempotency key. If Slack redelivers the same event
(at-least-once delivery), Constants ignores the duplicate.
Picking a good key
- Use a UUID v4 or any opaque string that’s unique per logical attempt.
- Generate it before the first request, not inside your retry loop.
- Don’t hash the request body into the key — let the server do that (fingerprint mismatch is how we catch reused keys pointing at different bodies).
- Don’t reuse a key across different endpoints. If you want to call
/v1/run/tool-aand/v1/run/tool-b, use two different keys.
