Skip to main content

Idempotency

Every financially-relevant operation that mutates state accepts an idempotency key. Sending the same key with the same payload is always safe — it replays the original result instead of executing again. Sending the same key with a different payload is rejected with IDEMPOTENCY_KEY_CONFLICT (409, see Errors § Idempotency conflicts) — it never silently overwrites or double-executes.

Where the key goes

Two real mechanisms exist, and which one applies depends on the specific route:

  • Body field (the common case) — an optional idempotencyKey parameter on operations like creating a Transaction, a PaymentIntent, executing a Settlement or a Refund, requesting a Withdrawal, or ingesting an Event.
  • Idempotency-Key header — used by only two routes: creating an Organization and creating an Application. If you're calling these directly over HTTP rather than through an SDK, check which mechanism the specific operation's API Reference page documents.

If you omit the key entirely, every official SDK generates a random UUID v4 for you automatically — meaning a bare SDK call without an explicit key is not idempotent across separate calls (each generates its own key). Always pass an explicit, deterministic key yourself when you actually need replay-safety (e.g. derived from your own order ID or a request ID you control) — the auto-generated default only protects a single call's own internal retries, never two independent calls that should have been "the same" operation.

Retry behavior

An SDK's own automatic retry logic (network failures, 5xx, rate limiting) always reuses the same key from the first attempt — it never generates a new key per retry attempt. This is what makes automatic retries safe by default: a retried call that actually succeeded server-side on an earlier attempt replays that same result instead of executing a second time.

What "same payload" means

The platform compares the payload associated with a previously-used key against the new request's payload. If they match, you get the original result back (replay, not a fresh execution — no duplicate financial effect). If they differ in any field the platform considers significant, you get IDEMPOTENCY_KEY_CONFLICT. Never reuse a key across two conceptually different operations, even if you expect the conflict to be harmless — treat a key as a one-time identity for one specific intended operation.

Example

// Deterministic key derived from your own order ID -- safe to retry this exact call any number
// of times; never derived from Date.now()/Math.random(), which would defeat the whole mechanism.
const idempotencyKey = `settle-order-${orderId}`;

const settlement = await client.settlements.executeSettlement(transactionId, undefined, idempotencyKey);