The Idempotency-Key header lets you safely retry a request without risk of double-processing.
When is it required, when is it recommended
| Endpoint | Header |
|---|---|
POST /api/v1/payments |
Required |
POST /api/v1/customers |
Recommended (especially for unattended writes) |
Everything else (GET) |
Not used |
If you call POST /payments without an Idempotency-Key, you'll get:
HTTP/1.1 400 Bad Request
{
"error": {
"code": "missing_idempotency_key",
"message": "Idempotency-Key header is required on POST /api/v1/payments"
}
}
How it works
Idempotency-Key: 9c6a5a52-1aa3-4f6f-9b1d-7d8a5d4e3a2b
- Pick a stable, unique key per logical attempt — a fresh UUID, or a structured key like
order_1234:attempt_1. - Send the same key + same body to retry safely. We return the original response — your retry never creates a duplicate payment.
- Reuse the same key with a different body and we return:
HTTP/1.1 409 Conflict
{
"error": {
"code": "key_reused",
"message": "Idempotency-Key already used with a different request body"
}
}
The fix is to pick a new key — the new request is genuinely a different operation.
When to pick what
| Situation | Suggested key |
|---|---|
| One-shot charge from a fresh checkout | A fresh UUID: uuidgen or crypto.randomUUID(). |
| Charge tied to an order in your system | order_<id>:attempt_<n> where you bump n only when the request body actually differs. |
| Scheduled charge | subscription_<id>:cycle_<yyyymmdd> — stable across retries within the same cycle, different across cycles. |
| Customer creation tied to a user signup | signup_<user_id> — guarantees that double-clicks don't create two customers. |
Key lifetime
- We retain the idempotency record for 24 hours.
- Within that window, replays return the original response (with the exact same fields, timestamps, and IDs).
- After 24 hours, the same key submitted again is treated as a new request.
What it doesn't help with
- Idempotency-Key isn't a duplicate-charge prevention mechanism beyond the 24-hour window — your own application should still avoid charging the same shopper twice for the same logical order.
- It doesn't change the outcome of a declined card — a
failedresponse is still the original response, and replaying the key returns the same failure.
Was this article helpful?
That’s Great!
Thank you for your feedback
Sorry! We couldn't be helpful
Thank you for your feedback
Feedback sent
We appreciate your effort and will try to fix the article