Skip to main content
Every payment order traverses a deterministic sequence of states from creation to a final state. The states are visible in the status field of every order and they drive webhook events.

States

A final state is terminalstatus will not change again. To reverse a SUCCESS, you create a new order in the opposite direction (or a refund flow, where supported).

Inbound (IN) state machine

Inbound orders start in PENDING immediately. There is no approval step — the platform submits to the provider as part of POST.

Outbound (OUT) state machine

Outbound orders pause in AWAITING_APPROVAL until you explicitly approve. This gate is where you implement business rules — dual control, anti-fraud, balance verification.

What you can do per state

approve and cancel are valid only in AWAITING_APPROVAL. Any attempt at another state returns PAYMENT_ORDER_NOT_AWAITING_APPROVAL or PAYMENT_ORDER_INVALID_STATE (HTTP 422).

Webhook events per transition

Every state transition fires a webhook event: See Payment events for full event payloads.

Polling vs. webhooks

  • Webhooks are the recommended source of truth — they push immediately on transition.
  • Polling (GET .../paymentOrders/{id}) is a valid fallback when you cannot expose a webhook endpoint, but be mindful of rate limits.
A reasonable polling cadence for transient states:

Error fields on FAILED

When status is FAILED, the order exposes:
Common errorCode values include INSUFFICIENT_FUNDS, RECIPIENT_INVALID, LIMIT_EXCEEDED. Branch on errorCode, not errorMessage.

EXPIRED is final, even if the payer pays late

For inbound dynamic QR codes, EXPIRED is terminal. If the payer pays after expiration:
  • The PIX network typically rejects the payment at their end (the QR is no longer valid).
  • In rare cases where settlement is force-completed, the funds may still appear in your wallet. They will not transition the order — they remain as an unattributed balance entry visible in the wallet ledger.
To handle this safely: do not promise the payer immediate fulfillment based solely on SUCCESS. Reconcile against your local ledger.

State invariants

A few rules to internalize:
  • A payment order cannot move from a final state to a transitional state.
  • direction is set at creation and never changes.
  • idempotencyKey is set at creation and never changes.
  • amount and network are set at creation and never change.
  • errorCode and errorMessage are populated only on FAILED; null otherwise.
  • processedAt is null until the order leaves PENDING for the first time; once set, it does not change.

Next

Payments overview

The payment-order resource model.

Pix cash-in tutorial

End-to-end inbound flow.

Webhooks

Receive state transitions in real time.