Card 02/ 06

WalkthroughDifficulty: Intermediate2 min

The Idempotency-Key Header: One Payment for Two Requests

The client sends a unique key with the write; the server stores the result and returns it again for the same key.

An idempotency key is a unique value the client generates for one operation and sends in an Idempotency-Key header. The server records the key with the response it produced; when a request arrives carrying a key it has seen, it returns the stored response and does not act again. Here is the payment on the train replayed with a key. The key is illustrative.

The key works like a cloakroom ticket: show the same ticket twice and you get the same coat, not a second one. The comparison breaks on who issues it, since a cloakroom hands out its tickets while the client makes its own key.

A keyed payment, a lost response, and a retry answered from the stored result

A keyed retry, step by step

The client generates a key for the operation

Before the first attempt the app creates a random value, usually a UUID, and keeps it with the payment it is trying to make. Every retry of this payment reuses it; a new payment gets a new key.

The server records the key before acting

On the first request the server stores the key as in progress, then charges the card. Recording first is what stops a second copy that arrives mid-charge from charging too.

The server stores the result under the key

When the charge completes, the server saves the status code and body it is about to send, 201 Created and the new payment, against the key.

The response is lost

The response never reaches the app. On the server everything is complete; on the client nothing is known.

The retry carries the same key

The app sends the identical request with Idempotency-Key: 8e0f2c51. The server finds the key with a stored response and returns that response, without calling the card processor.

What the client sees. The retry receives the same 201 Created and the same payment id the first attempt would have, so the app cannot tell, and does not need to, whether it is the first answer or a replay.

Where the key comes from. It must be unique per operation and unpredictable, so a UUID version 4 or a similar random value is the usual choice. Deriving it from the request body is a mistake: two genuine payments of 30 euros on the same day would share it.

Which requests carry it. POST, and PATCH where a repeat changes the result. GET, PUT and DELETE are idempotent already and need none.

The header's status. Idempotency-Key is defined in an IETF draft from the HTTP APIs working group, and payment providers such as Stripe use the same pattern. Check the API's own documentation for the exact header name and rules.