Blog

Idempotency-Key Errors That Look Like Random 409s

Developers retry a POST, reuse an idempotency key with a different body, and get a 409 they cannot explain. Document the key lifetime, the mismatch case, and the header that fixes it.

2026-10-11 · 7 min read · AethelLayer

Retries are the happy path for payments and webhooks

Any API that asks clients to retry must say what makes two requests the same. The Idempotency-Key header is that contract. Reusing a key with the same body should return the original result. Reusing it with a different body is a conflict, not a new charge.

If you return a bare 409, the developer thinks the record already exists and starts inventing new keys, which creates the duplicate you were trying to prevent.

Name the mismatch

Give the conflict a stable code such as IDEMPOTENCY_BODY_MISMATCH. Say how long you store the key. Say which fields are part of the fingerprint. A message that tells them to send a new key only when the body changed will save a day of debugging.

Do not put the previous request body in the error. It may contain data they should not log. Say that the body differed, and which top-level field if you can do that without leaking values.

SDKs should set the key and surface the code

Generate the key inside the SDK for a single logical operation, and reuse it across the SDK's own retries. If the caller changes the payload, that is a new key. Document that in the method docstring so it is not a surprise.

When the API returns the mismatch code, throw an error with that code and capture a probe. The stack plus 'I was retrying a create from the sample' tells you the sample is generating a new body on every run.

Read the probes before you blame the client

A spike in mismatch codes after a release often means you added a server-side default field and their replay no longer matches. That is your breaking change. The inbox will show it before the angry thread does.

Draft the issue with the code and their sentence. A human sends it once the pattern is real, not on every retry.

Capture the failure before they leave

Capture the failure before they leave. Book early access or talk to sales, then install @aethellayer/sdk when you are onboarded.