Idempotency
Also known as: Idempotent operation, Replay-safe operation
Quick definition
Idempotency is a property of API operations where making the same request multiple times produces the same result as making it once. Idempotent endpoints can be safely retried after failures or webhook duplicates; non-idempotent endpoints risk creating duplicate records, double-charging, or worse on retry.
Contents
What is idempotency?
Idempotency is a mathematical and engineering property: an operation is idempotent if performing it once and performing it many times produces the same end state. In API terms, an idempotent endpoint can be called repeatedly with the same input without causing additional side effects beyond the first call. The classic example: a DELETE endpoint that removes a specific resource is idempotent — calling DELETE /posts/123 once removes the post; calling it 10 more times just confirms it's still gone, no harm done.
Non-idempotent endpoints, by contrast, create new state on every call. POST /posts (create a post) is non-idempotent by default — calling it 10 times creates 10 posts. This becomes a problem when networks are flaky: if your client sends a POST and doesn't receive a response, did the server process it or not? Retrying might double-create. The solution is to add idempotency keys — client-generated unique IDs that the server uses to deduplicate retries.
Why idempotency matters for retries
Three real-world scenarios where idempotency saves you. (1) Network timeouts — your client sends a POST, the network drops the response; you don't know if it succeeded. Without idempotency, retrying might create a duplicate. (2) Webhook retries — the API server retries failed webhook deliveries; your handler must process the same event multiple times safely. (3) Background job retries — when a job server retries a task that may have partially completed, idempotent operations let you safely re-run.
Most mature APIs (Stripe, GitHub, AWS) treat idempotency as a first-class feature. Stripe's API specifically supports an Idempotency-Key header on POST requests; submit the same key twice and you get the same response, with no side effects on the second call.
How to implement idempotency
Two patterns. (1) Idempotency keys — the client generates a unique ID per logical operation (typically a UUID), passes it on every request, and the server caches the response keyed by ID. Repeat requests get the cached response without re-executing the operation. CodivUpload's API supports an Idempotency-Key header on POST /v1/posts — duplicate keys within a 24-hour window return the same post_id without creating a duplicate. (2) Natural idempotency via state checks — for non-key approaches, the server can check whether the operation's intended end state already exists. 'Mark email as verified' is naturally idempotent because there's no difference between marking it once or 10 times.
For webhook handlers specifically, idempotency typically means tracking event IDs in a deduplication table. When an event arrives, check if its ID was already processed; skip if so.
Idempotency-Key on a POST request via CodivUpload
bash
# Generate a UUID per logical operation
# Same key + same body = same response (no duplicate post created)
IDEMP_KEY=$(uuidgen)
curl -X POST https://api.codivupload.com/v1/posts \
-H "Authorization: Bearer cdv_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $IDEMP_KEY" \
-d '{
"profile_name": "main",
"platforms": ["instagram"],
"post_type": "feed",
"media_urls": ["https://cdn.example.com/photo.jpg"],
"description": "Daily post"
}'
# If the request times out, retry with the SAME idempotency key.
# Server returns the existing post_id rather than creating a duplicate.
# After 24 hours, the key cache expires and the same key would create
# a new post — design retry windows to fit within that 24h boundary.Common pitfalls
- ×Reusing idempotency keys across logically different operations — defeats the purpose, returns wrong cached response
- ×Not generating fresh keys for retries that you actually want to be retries — using the same key on a retry of a different operation breaks correctness
- ×Treating GET as needing idempotency keys — GET is naturally idempotent (just reads); only POST/PUT/PATCH/DELETE need explicit keys
- ×Implementing idempotency only at the API client level — webhooks also need handler-level idempotency via event-ID dedup tables
Tips
- ✓Generate idempotency keys with UUIDs — collision-safe, easy to log and trace
- ✓Pair API-level idempotency with handler-level dedup — defense in depth against retries
- ✓Set sensible cache windows — 24 hours is typical for most use cases
- ✓Log the idempotency key with every request — makes debugging double-submission incidents tractable
Frequently asked questions
Are GET requests idempotent?+
Yes by definition — GET requests should never modify server state, so calling GET multiple times is naturally safe. The HTTP spec explicitly defines GET, HEAD, OPTIONS, PUT, and DELETE as idempotent; POST and PATCH are not (without explicit idempotency keys).
How long should an idempotency key be valid?+
Most APIs cache keys for 24 hours. Within that window, the same key returns the same response. Beyond 24 hours, the same key creates a new operation. Design your retry windows to fit within the cache window.
What if I forget to add an idempotency key?+
The request still works — it just becomes non-idempotent. If the network drops during the response, retrying might create duplicates. For one-off operations the risk is low; for high-volume automation, idempotency keys are essential.
Do I need idempotency in webhooks too?+
Yes. Webhook providers retry on failures, so the same event can arrive multiple times. The pattern is to track event IDs in a deduplication table — first time you see an event ID, process it; subsequent times, skip. This is handler-level idempotency, separate from API-call idempotency.
Idempotent API calls and webhooks built in
CodivUpload's API supports Idempotency-Key headers on POST /v1/posts (24h cache window). Webhooks deliver event IDs for handler-side dedup. Retry-safe by design.
See API docsRelated glossary terms