Idempotency (especially for payments)

An operation is idempotent if performing it once or multiple times has the same effect. For APIs, that means: same request (identified by an idempotency key) applied once or retried many times produces the same outcome and no duplicate side effects (e.g. one charge, one order).

Why it matters for payments

Networks and clients retry. Without idempotency, a double-click or a retry can create two charges or two orders. With an idempotency key (client-generated unique ID per logical operation), the server can recognize a repeat and return the same result without re-executing.

sequenceDiagram participant C as Client participant S as Server participant DB as Store C->>S: POST /charge Idempotency-Key: key-123, body S->>DB: Has key-123 been seen? alt First time DB-->>S: No S->>S: Process charge S->>DB: Store result for key-123 S-->>C: 201 Created (charge id) else Retry / duplicate DB-->>S: Yes, result stored S-->>C: 200 OK (same charge id, no new charge) end

Implementing idempotency

What should be idempotent

flowchart TB subgraph Idempotent["Should be idempotent"] I1[Payments / charges] I2[Order creation] I3[Subscription changes] I4[PUT / PATCH / DELETE] end subgraph NonIdempotent["Inherently not"] N1[POST create without key] N2[Send email / notification] end

Use idempotency keys for any non-idempotent mutation that must not be applied twice: payments, order creation, sign-ups that send email, etc. GET, PUT, DELETE are naturally idempotent; POST and custom actions need a key.