Idempotency
Make a retried POST safe with an Idempotency-Key, and understand exactly which retries are replayed and which are allowed through.
Automations retry — on a socket timeout, a 502 from a proxy, a queue redelivery, a CI step re-run. Without help, a retried "create task" makes a second task, and the client has no way to tell "my request never arrived" from "my request arrived and the response didn't".
Using it
Attach a unique value to a POST:
curl -X POST https://acme.krrim.com/api/v1/projects/APOLLO/tasks/ \
-H "Authorization: Bearer krm_live_..." \
-H "Idempotency-Key: 0f0d6a4e-3f6b-4a5f-8f6f-3a2f1b9c4d77" \
-H "Content-Type: application/json" \
-d '{"title": "Investigate checkout timeout", "priority": "high"}'The first request runs normally and its response is remembered. Any later request with the same key gets that same response back — same status, same body — without the work happening twice.
Use a value derived from the thing you are creating (an upstream event id, a row id) rather than a fresh UUID per attempt. A key that changes between retries is no key at all.
The rules
POST only. PUT, PATCH and DELETE are already idempotent by
definition and GET has nothing to replay. Sending the header on those would
imply a guarantee that is either meaningless or already true, so it is ignored.
The body is part of the match. Reusing one key for two different payloads is
a client bug — almost always a key generated once and then cached too widely —
and replaying the first response would silently drop the second request's data.
That returns 409 rather than pretending to succeed.
Keys are scoped to the token. Two workspaces, or two integrations in one
workspace, cannot collide on Idempotency-Key: 1.
A request still in flight returns 409, not a duplicate. Two concurrent
retries of the same key would otherwise both run. The claim and the check are a
single atomic operation, so exactly one wins and the other is told to wait.
5xx responses are not cached. A server error is not a decision, it is a
failure, and a client retrying it must be allowed to actually retry. If
5xx were remembered, one bad minute would make the failure permanent for
that key.
2xx and 4xx are remembered — those are outcomes. A repeated validation
error stays the same error rather than becoming a duplicate create on the
third attempt.
How long a key lives
A remembered response stays replayable for 24 hours. That covers every retry pattern in practice — exponential backoff, a nightly job re-run, a human re-triggering a pipeline the next morning — without holding response bodies indefinitely.
After that the key is forgotten and a request carrying it is treated as new.
Reading the outcome
| Situation | You get |
|---|---|
| First request with this key | The real response |
| Retry, same key, same body | The remembered response, replayed |
| Retry while the first is still running | 409 CONFLICT |
| Same key, different body | 409 CONFLICT |
Retry after a 5xx | Runs again for real |
Rate limits
Two tiers — a per-token burst limit and a per-organization sustained limit — plus the headers that let you back off on the one that is actually binding.
Webhooks
Signed events pushed to your endpoint, the published retry curve you can size your outage tolerance against, and how to verify a delivery.