Skip to main content

Why Idempotency Matters

In payment systems, network failures and timeouts are inevitable. Without idempotency, retrying a failed request could create a duplicate transaction — charging a user twice or triggering two payouts. Idempotency keys let you safely retry requests with the guarantee that the operation only executes once.

The Idempotency-Key Header

Include an Idempotency-Key header on mutating requests. The key uniquely identifies the intent of the request — same key, same result.

Key Format

Use a UUID v4 for each unique operation:
Generate a new key for each distinct operation. Do not reuse a key from a previous transaction for a new one — this will return the cached response from the original transaction.

Key Expiry

Keys expire after 24 hours. After expiry, the same key can be used for a new request.

Behavior

Successful Retry

When you retry with the same key and body, the response includes a header indicating it’s a replay:
The response body is identical to the original 201 response.

Conflict (Different Body)

If you accidentally reuse a key with different parameters:
Generate a new key and retry.

Retry Example

The key is generated once outside the loop. Every retry sends the same key, so even if a previous attempt succeeded but the response was lost, the retry returns the original result without creating a duplicate.

Recovering a Lost Transaction ID

If your client crashes after sending a request but before saving the transactionId, you can recover it by replaying the same idempotency key and body:
If the original request succeeded, you’ll get back the original response (including the transactionId) with the Idempotent-Replayed: true header. This works as long as the key hasn’t expired (24 hours).
Store your idempotency keys alongside the operation they represent. This makes recovery straightforward — if in doubt, just replay the request.