Idempotency-Key.
This header is optional. If you do not send it, nothing changes: the API behaves exactly as it always has, and a retry sends again. Everything below is opt-in.
The header
Pick a string that is unique to the message you are trying to send — an order id, a row id, a UUID — and send it with the request:Sending with a key
What each outcome looks like
Read
Idempotency-Replayed to know which happened. false means this call did the sending; true means it was a replay. If the header is absent from the response, idempotency is not enabled on the deployment you are talking to and retries will send again — treat that as “not protected”.Choosing a key
- Make it unique per message, not per customer and not per day.
order-4471-confirmationis good;daily-reminderis not, because tomorrow’s reminder is a different message that would be refused as a reuse. - 8 to 255 characters, from letters, digits, and
._:~-. - A UUID is always a safe choice if you have nothing natural to use.
- Reuse the same key for every retry of the same send. Generating a fresh key on retry defeats the entire purpose.
Two things it deliberately does not do
It does not merge different messages. Reusing a key with a changed body returns422 idempotency_key_reused rather than quietly sending the new one or quietly replaying the old one. Both of those would be a lie about what your customer received.
It cannot rescue a lost reply. If we genuinely delivered the message and only the response was lost on the way back to you, a retry sends again — the key was released when the request failed, because the far more common case is a request that never got through at all. No key can tell those two apart from our side. If exactly-once matters more to you than delivery, wait and check rather than retry.
When to bother
Worth it
Anything triggered by a queue, a webhook, a cron, or a serverless function — all of which retry by default, often without telling you.
Probably not
A human clicking a button in a UI you control, where you can disable the button and show the result.
Errors
Both codes are documented in full on the Errors page.409 idempotency_key_in_flight— your first request is still running. Retry the identical request shortly; you will get the original result. CarriesRetry-After.422 idempotency_key_reused— this key already means a different message. Use a new key.

