Idempotency keys for payment and mutation endpoints
Why it matters
Without idempotency protection, a network timeout followed by a client retry on a payment endpoint triggers a duplicate charge (CWE-362, race condition via repeated mutation). A double-click on a checkout button produces two identical Stripe createSubscription calls. The business consequence is immediate: duplicate charges require manual refunds, generate chargebacks, and erode customer trust. This is not a theoretical risk — network retries are the default behavior of most HTTP clients and mobile SDKs, making duplicate invocation the expected path under degraded network conditions.
Severity rationale
High because duplicate payment execution from retries is a common real-world event that causes immediate financial and trust damage requiring manual remediation.
Remediation
Pass idempotency keys to every Stripe API call in your payment route handlers, and store key-to-result mappings in Redis or your database for your own mutation endpoints:
// For Stripe calls — always pass idempotencyKey
const idempotencyKey = request.headers.get('Idempotency-Key') ?? crypto.randomUUID()
const subscription = await stripe.subscriptions.create(
{ customer: customerId, items: [{ price: priceId }] },
{ idempotencyKey }
)
For your own endpoints, check whether the key was already processed before executing business logic, and return the cached response on a hit. The client generates and stores the key before the first attempt, then retries with the same key on failure. Document this contract in your API reference so integrators know to supply the header.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the API Design Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe · CWE-362 — Race Condition (check-then-act idempotency bypass)
- iso-25010:2011 · functional-suitability.functional-correctness — Functional Correctness
Taxons
History
- 2026-04-18·v1.0.0·Initial import from saas-api-design·automated