Skip to content

Idempotency

Calls that move money or create a session need an Idempotency-Key header:

Call Header
POST /v1/payments required
POST /v1/payments/{id}/refunds required
POST /v1/payments/{id}/reprocess required
POST /v1/checkout-sessions required
POST /v1/refunds/bulk, POST /v1/payments/reprocess one key per item in the body

Rules:

  • 8 to 255 characters of A-Z a-z 0-9 _ - : . (400 idempotency_key_required otherwise).
  • Derive it from your own data, for example order-1042-pay-v1 or refund-1042-1, and store it before you call. Never generate a random key per retry: the point is that a retry sends the same key.
  • Same key and same request: GIEP returns the original result and never repeats the side effect. This holds even if the first request is still running elsewhere: you get 409 request_in_progress; retry a little later.
  • Same key with a different body: 422 idempotency_key_reused.
  • A request refused by validation (4xx before anything was sent to a processor) releases the key, so you can fix the body and retry with the same key.
  • POST /v1/checkout-sessions replays return the same session with a freshly issued token (the token itself is never stored in clear).
  • Refund keys are per refund: the same key for a different payment or amount is 422 idempotency_key_reused. Keys starting with alert: are reserved.

A timeout is not a decline. If a money call times out or the connection drops, you do not know whether it worked. Retry with the same key, or read the payment. Never create a second payment with a new key for the same order.