Skip to main content
Network failures are not “rare edge cases” — at sufficient request volume they happen daily. The single most important pattern to keep your integration correct under failure is idempotency: making it safe to retry the same operation any number of times without producing duplicate side effects.

The problem

Consider a “create payment order” request that returns a network error:
You face an ambiguity:
  • Did the server receive the request and process it? → Retry creates a duplicate payment.
  • Did the request fail before the server saw it? → Not retrying leaves you with a missing payment.
Without an idempotency key, you cannot tell. Both choices are wrong sometimes.

The solution: idempotencyKey

When you create a payment order, supply an idempotencyKey — a client-generated identifier unique to the intent of the operation:
The server tracks (wallet, idempotencyKey) tuples: Retries become safe. You can retry as many times as needed without creating duplicates.

Choosing an idempotencyKey

Tie the key to the business intent, not the network attempt.

The persist-then-call pattern

The safest implementation:
1

Persist the intent locally

Before you call the API, write a row in your database describing the operation, with a stable idempotencyKey (UUID v4 is fine).
2

Call the API with that key

Include the persisted key in the request body.
3

On any error

Retry — read your persisted key from the local row, do not regenerate.
4

On success

Update your local row with the returned id and current status.
This pattern survives application crashes between any of the steps.

Scope and lifetime

Because keys are retained indefinitely, scope them carefully. payment-1 is a poor key — it will collide eventually. Prefix with a meaningful namespace: invoice-2026-0184.

When you supply different params on retry

The most common cause of IDEMPOTENCY_KEY_IN_USE_WITH_DIFFERENT_PARAMS is not a bug in your retry logic — it is reusing a key across different invoices. If you genuinely need to retry with corrected parameters (e.g., the original amount was wrong):
  1. Treat the original key as burned.
  2. Mint a new idempotencyKey for the corrected attempt.
  3. Reconcile against the original key via your local persistence.
There is no “force overwrite” operation. The first set of params for a key is final.

What if I do not supply an idempotencyKey?

The OpenAPI spec marks idempotencyKey as optional. Omitting it means every retry creates a new order. For PIX in particular this means every retry potentially creates a duplicate payment.
For any operation with financial side effects, always supply an idempotencyKey. The cost of generating one is trivial; the cost of a duplicate transfer to a customer can be material.

What is NOT idempotent

For approve and cancel, the operation is idempotent in effect — calling twice does not duplicate the state transition; the second call merely returns an error indicating the resource is no longer in the right state. Treat the error as success when you know you intended the transition.

Idempotency vs request retry signature

Each retry attempt still needs a new X-Access-Request-Id — that is the signing protocol’s anti-replay nonce, separate from idempotencyKey: See Sign a request for the request-id rules.

Next

Retry strategy

When to retry and how to back off.

Payments overview

How idempotency interacts with the payment-order lifecycle.