A client can lose the response after a provider has accepted a payment request. Retrying with a new operation identity can create a second charge; never retrying can leave an order unresolved. Idempotency gives repeated attempts one stable identity so the client can ask for the same operation again.
Provider contracts differ. Stripe says its idempotency layer returns the stored result for a reused key, including a stored server error, and checks that repeated parameters match. Adyen says a reused key can return the original response, documents a provider-specific key lifetime and scope, and marks certain errors as transient (Stripe; Adyen). Implement against the selected API’s exact contract rather than copying constants from this guide.
Give the business operation an identity
Create the idempotency key when the business decides to perform an operation, not each time the HTTP client sends it. Store it with the order and operation type. Attempts to capture order A-1042 should reuse the capture operation’s key until the outcome is known. A later refund is a different business operation and needs a different key.
The key is not a substitute for the merchant’s own uniqueness rule. Maintain a local operation table containing order ID, operation type, amount, currency, provider account, key, request fingerprint, provider reference, state, attempt count, and timestamps. Enforce the intended rule, such as one initial payment per checkout session, in the local database as well.
Never reuse a key with changed amount, currency, customer, or destination. If the business meaning changes, create a new operation deliberately and link it to the superseded one.
Classify the outcome before retrying
Treat results in three groups:
- Definitive rejection. Validation failed before the provider began the operation, or the provider explicitly says the request cannot be retried. Correct the request or ask the customer for another action.
- Definitive success or failure. Persist the provider reference and terminal or actionable state. A transport retry is unnecessary.
- Ambiguous transport outcome. The connection timed out, reset, or returned an error the provider documents as retryable. Retry the same operation with the same key and unchanged parameters, using bounded exponential backoff with jitter.
Do not treat every 5xx, 409, or timeout identically across providers. Stripe’s documented cached-result behavior and Adyen’s transient-error behavior illustrate why a generic status-code table is insufficient. Read response headers and provider error semantics.
Resolve ambiguity with more than HTTP
After the retry budget, mark the operation unknown, not failed. Query the provider by its reference or the merchant reference where supported, and wait for signed asynchronous events. Reconcile provider transactions and payouts before allowing a person to “try again” manually. The webhook receiver guide covers repeated and out-of-order delivery; the payment lifecycle guide separates an accepted API request from the later financial outcome.
Expose a customer-safe status such as “We’re confirming your payment” rather than inviting repeated submission. Support staff should see the existing operation key and state, with a controlled action to refresh status. They should not create a new charge because the first response is missing.
Test the failure windows
In the provider’s test environment, simulate a timeout before send, a disconnect after send, two concurrent requests with the same key, a retry with changed parameters, and a delayed webhook. Verify that the local order has one payment operation and one fulfillment decision. These are recommended tests; no tests were executed for this editorial guide.
Monitor duplicate business operations, unresolved unknown states, retry counts, and keys nearing the provider’s retention limit. Idempotency makes a retry safer. It does not make an operation correct, confirm settlement, or replace reconciliation.
Sources
- Stripe, Idempotent requests — provider-specific
- Adyen, API idempotency — provider-specific
Evidence & dates
Prepared 19 Sept 2026 · source checks 19 Sept 2026 · website publication pending. Undated means no publication date was established on the reviewed page.
Stripe · Idempotent requests
Stripe-specific idempotency-key behavior, cached responses, parameter comparison, and key lifetime caveats.
Source publication date: undated · checked 2026-09-19 · full page reviewed · evidence: self-reported · recheck by 2026-12-19
Read the primary source ↗Adyen · API idempotency
Adyen-specific key scope, validity period, transient errors, concurrent request behavior, and exponential backoff guidance.
Source publication date: undated · checked 2026-09-19 · full page reviewed · evidence: self-reported · recheck by 2026-12-19
Read the primary source ↗