A customer taps “Pay” and the mobile connection drops before the confirmation screen loads. The app does not know whether the server created the charge. Should it send the request again? API idempotency is the design answer to that question: a way for a client to retry a request so that the operation behind it happens no more than once.
The idea is older than any particular payment API. HTTP defines which methods are idempotent by nature, and API providers such as Stripe and Amazon Web Services add keys or tokens so that a request that is not naturally idempotent can be retried safely. Reading those specifications side by side shows what an idempotency key protects and where its protection stops.
What HTTP already promises
RFC 9110, section 9.2.2 defines a request method as idempotent when “the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request.” Among the methods the RFC defines, PUT, DELETE and the safe methods such as GET qualify. POST does not.
The same section explains why the property matters. If a connection closes before the client reads the response, a client can retry an idempotent request knowing that a repeat has the same intended effect, “even if the original request succeeded, though the response might differ.” For other methods the RFC says a client should not retry automatically unless it has some means to know the request is idempotent in practice, or some means to detect that the original was never applied. It also says a proxy must not automatically retry non-idempotent requests.
Two details in that definition are easy to miss. The property covers the intended effect, so a server may still log every request separately. And it describes the method’s semantics, not a guarantee that every server implements them correctly.
A key turns a POST into a recognizable retry
Creating a payment or a customer record is usually a POST, which leaves the client with the problem the RFC describes. An idempotency key closes that gap by giving the server a way to recognize “this is the same request again.”
Stripe’s API reference describes the pattern. The client generates a unique key, Stripe suggests a V4 UUID or another random string with enough entropy, and sends it with the request. Keys can be up to 255 characters, and Stripe asks developers not to use sensitive data such as email addresses as keys. For its v1 API, Stripe saves the status code and body of the first request made with a key once endpoint execution begins, and a retry with the same key returns that saved response, including a 500 error.
Amazon EC2’s API guide uses the same idea under a different name. Many EC2 actions accept a client token, a unique, case-sensitive string of up to 64 ASCII characters. If a request completed successfully and the client retries it with the same token and the same parameters, the retry succeeds without performing further actions, although the result may show updated information such as the current creation status.
The key is bound to the request it first described
A key is only meaningful if it keeps pointing at one operation. Both providers check this.
Stripe says its v1 idempotency layer compares incoming parameters with those of the original request and returns an error if they differ. EC2 returns an IdempotentParameterMismatch error when a retry reuses a client token with different parameters, other than the Region or Availability Zone.
The IETF HTTP APIs working group drafted a common header for this pattern. The Idempotency-Key HTTP Header Field proposes that a server answer 422 when a key is reused with a different payload, 409 when a retry arrives while the original request is still being processed, and 400 when a documented operation requires the header and it is missing. The datatracker lists the latest revision, -07 from October 2025, as an expired Internet-Draft, so these status codes describe a proposal rather than an adopted standard. Individual APIs still define their own behavior.
| Situation | Stripe v1 | Amazon EC2 client token | IETF draft proposal |
|---|---|---|---|
| Same key, same request | Saved first response returned | Success, no further action | Result of the completed first request, success or error |
| Same key, different parameters | Error | IdempotentParameterMismatch | 422 |
| Retry while the first is running | Result not saved; can be retried | Not stated in the cited section | 409 |
| Key lifetime or scope | Can be removed after at least 24 hours | Scoped by Region or Availability Zone | Server publishes its own expiry policy |
Where the protection stops
The documentation also marks the edges of what a key does.
A key expires. Stripe says v1 keys can be pruned once they are at least 24 hours old, and a key reused after pruning creates a new request. A retry queue that can hold work for longer than the provider’s window needs its own record of what was already sent.
Not every failure is stored. Stripe saves an idempotent result only after endpoint execution begins. A request that fails parameter validation, or that conflicts with another request executing concurrently, is not saved and can be retried.
The key belongs to one service. The provider’s idempotency layer protects the operation inside that provider. It does not know whether the client’s own database recorded the order, sent the receipt or updated a ledger. Those side effects need their own checks, often keyed by the same business identifier. The same reasoning applies to incoming events; our piece on webhook signatures and replay protection follows the receiving side of a payment integration.
Methods that are already idempotent need no key. Stripe says sending a key with GET and DELETE requests has no effect, because those requests are idempotent by definition.
How to generate and store an idempotency key
The client creates the key, not the server. The IETF draft recommends “a UUID or a similar random identifier,” and Stripe suggests V4 UUIDs or another random string with enough entropy to avoid collisions. The draft’s own example is a header, Idempotency-Key: "8e03978e-40d5-43e8-bc93-6894a57f9324". Stripe’s API reference asks for the key as an additional element of the request options, separate from the object’s parameters.
Generate the key once per intended operation and save it before the first attempt. A key created fresh on each retry defeats the purpose, because the server sees a new request every time.
The server side stores the key with what it needs to recognize the request again. The draft adds an optional idempotency fingerprint: a checksum of the whole request payload, or of selected fields, so the server can tell a true retry from a different request that reuses the key.
Idempotency key vs request ID
The two identifiers travel in opposite directions. An idempotency key is chosen by the client and sent to the server to say “treat repeats of this as one operation.” A request ID is assigned by the server to each individual attempt. Stripe returns one in the Request-Id response header for every API call and asks developers to quote it when contacting support. Two retries of the same payment share one idempotency key but receive two request IDs.
| Idempotency key | Request ID (Stripe) | |
|---|---|---|
| Who creates it | Client | Server |
| Direction | Request header or option | Response header |
| Scope | One intended operation, across retries | One HTTP attempt |
| Purpose | Prevent a repeated effect | Trace and support a specific call |
Questions to ask before the next release
The useful review follows one retried request from the client to the final record. Where is the key generated, and is it stored before the first attempt so the same value survives an app restart? Does the retry send exactly the same parameters? How long does the provider keep keys, and can any of the system’s queues outlast that window? What does the client do with a 409 or a saved 500? These questions are analysis drawn from the documented behavior above, not results from testing a particular integration.
Reporting & Sources
RFC 9110, HTTP Semantics, section 9.2.2 (June 2022); Stripe API reference: idempotent requests; Amazon EC2 developer guide: ensuring idempotency; IETF datatracker: The Idempotency-Key HTTP Header Field, revision -07 (October 2025); Stripe API reference: request IDs. Sources reviewed October 10, 2026. The review questions and design implications are analysis based on those documents.





