An idempotency key lets a client retry an API operation without accidentally creating the same result twice. This matters when a request may have reached the server but the response was lost because of a timeout or network interruption.
You usually apply this pattern to operations such as creating an order, starting a payment, or submitting a booking. The client sends a unique key with the request, and the server remembers the result for a defined period.
Why Idempotency Keys Are Useful
Suppose a user submits an order and the connection closes before the client receives a response. The client cannot tell whether the server created the order. Sending the same request again without protection may create a duplicate.
An idempotency key gives both requests the same identity. The server processes the first request and returns its stored result when the same key and payload arrive again.
How an Idempotent Request Works
- The client generates a unique, unpredictable key for one logical operation.
- The client sends the key with the request.
- The server stores the key, a request fingerprint, the processing state, and the final response.
- A retry uses the same key and the same request data.
- The server returns the original result instead of repeating the operation.
Note: Each API defines its own key format, retention time, supported methods, and replay behavior. Document these rules clearly for your clients.
Send an Idempotency Key
The Idempotency-Key request header is a common convention. Generate a new key when the user begins a new operation, then reuse that key only for retries of the same operation.
Example:
# Reuse this key only when retrying the same order request.
curl -X POST "https://api.example.test/orders" -H "Content-Type: application/json" -H "Idempotency-Key: 4d3bbf44-42d4-4b11-a7c8-2183b8429a61" -d '{"customerId":"C102","item":"Keyboard","quantity":1}'
Response:
HTTP/1.1 201 Created
Content-Type: application/json
{
"orderId": "ORD-2048",
"status": "created"
}
If the response is lost, the client sends the same request with the same key. A correct implementation returns the stored status code and response body for ORD-2048.
Create a Request Fingerprint
A key alone cannot prove that two requests represent the same operation. Calculate a fingerprint from the method, normalized target, and relevant request body. Store it with the key.
When the same key arrives with different data, reject the request. Do not return the earlier response because it belongs to a different operation.
| Incoming request | Recommended action |
|---|---|
| New key | Reserve the key and process the operation |
| Same key and same fingerprint, completed | Replay the stored response |
| Same key and same fingerprint, still running | Report a conflict or ask the client to retry later |
| Same key and different fingerprint | Reject the request as invalid key reuse |
| Expired key | Treat it according to the documented retention policy |
Reserve the Key Atomically
Two identical requests can reach different application instances at nearly the same time. A simple read followed by an insert creates a race condition. Reserve the key with an atomic insert, unique constraint, transaction, or equivalent operation in a shared data store.
Example:
# Server-side processing outline
validate key format and request data
calculate request fingerprint
try to reserve key atomically
if key is new:
mark operation as processing
perform the business operation once
store status code and response
return stored response
if key exists with a different fingerprint:
return an invalid-reuse error
if key exists and processing is complete:
return the original stored response
if key exists and processing is still active:
return a conflict response
Choose Clear Error Responses
Return a consistent problem response so clients know whether to correct the request or retry it. Common choices include:
- 400 Bad Request: the endpoint requires a key, but the client omitted it or used an invalid format.
- 409 Conflict: another request with the same key is still processing.
- 422 Unprocessable Content: the client reused the key with different request data.
These status codes are design recommendations, not automatic HTTP behavior. Keep the choice consistent across your API and describe it in the endpoint documentation.
Store the Right Information
An idempotency record normally contains the key, tenant or account identifier, request fingerprint, processing state, response status, response body, creation time, and expiry time. Scoping the key to the authenticated account prevents one customer from affecting another customer's requests.
Set a retention period that covers realistic retry windows. Deleting records too early can allow a delayed retry to repeat the operation. Keeping every record forever wastes storage and may retain sensitive response data longer than necessary.
Handle Failures Carefully
Do not permanently cache every failure in the same way. A completed validation error can usually be replayed, while a server failure that occurred before the business operation began may allow another attempt. If the operation changed state before failing, preserve enough information to return a stable result or continue recovery safely.
Commit the business change and the idempotency result in one transaction when they use the same transactional store. When that is not possible, use a durable workflow that can recover after a process crash.
Idempotency Keys and HTTP Methods
Methods such as GET, PUT, and DELETE have idempotent semantics in HTTP, although a response may change between calls. POST is not idempotent by default, which is why keys are especially helpful for creation and action endpoints. A key does not replace correct method design; it adds retry protection where the operation needs it.
Security and Operational Practices
- Use high-entropy keys that are difficult to guess.
- Limit key length and validate allowed characters.
- Scope records to the authenticated caller and endpoint.
- Rate-limit repeated requests to prevent storage abuse.
- Avoid storing secrets in logs or unprotected response caches.
- Monitor conflicts, invalid reuse, and processing records that never complete.
Conclusion
REST API idempotency keys make retries predictable when clients cannot confirm an earlier result. Generate one key per logical operation, compare a request fingerprint, reserve the key atomically, and replay the original response. Clear retention and error rules help clients recover safely without creating duplicate orders, payments, or bookings.