status field of every order and they drive webhook deliveries.
States
A final state is terminal —
status 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 inPENDING immediately. There is no approval step — the platform submits to the provider as part of POST, and the 201 response already contains the rendered QR/copy-paste payload while the order is PENDING. Inbound orders never enter PROCESSING; they move from PENDING straight to a terminal state.
Outbound (OUT) state machine
Outbound orders pause inAWAITING_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 deliveries per status
A webhook is delivered when an order reaches a settled status. There are no named event types — each delivery is the full PaymentOrder document, and you branch on itsstatus field:
Order creation and approval do not generate webhooks — only settled statuses do.
The order’s
direction selects the destination: IN orders are delivered to your registered cash-in endpoint, OUT orders to your cash-out endpoint (both registered during onboarding). Deduplicate deliveries by (id, etag) and guard ordering with ordVersion.
See Payment events for the full delivery payload.
Polling vs. webhooks
- Webhooks are the recommended way to learn about settlement — a delivery is pushed as soon as the order reaches a settled status.
- Polling (
GET .../paymentOrders/{id}) is how you observe intermediate states (PENDING,PROCESSING,AWAITING_APPROVAL), which never generate deliveries — and a valid fallback when you cannot expose a webhook endpoint. Be mindful of rate limits.
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.
Note that INSUFFICIENT_FUNDS on outbound orders is detected asynchronously at submit time: creation and approval succeed normally, and the shortfall surfaces only when the platform submits the order after approval, finalizing it as FAILED.
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.
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.
directionis set at creation and never changes.idempotencyKeyis set at creation and never changes.amountandnetworkare set at creation and never change.errorCodeanderrorMessageare populated only onFAILED;nullotherwise.processedAtisnulluntil the order leavesPENDINGfor 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 settled orders in real time.