Why two steps
Splitting a cash-out into initiate and process gives you a checkpoint between “who is the payee?” and “send the money”:
- Verify the destination first. Initiate validates and resolves the payee account without touching balances. A wrong Pix key or an invalid account fails here — before any money moves.
- Show the payer who they’re paying. The initiate response returns the resolved account owner, so your app can display the real name and let the payer confirm before committing.
- Move funds only on confirmation. Nothing is debited until you process the transfer. If the payer abandons the flow, there’s no reversal to make — there was never any movement to undo.
Both steps are idempotent — safe to retry without creating duplicate transfers. See Retries and idempotency.
Step 1 — Initiate: confirm the destination
Initiating a transfer creates a short-lived record that validates and resolves the payee without moving funds. How the plugin finds the destination depends on what you start with:
| You start with | Initiation type | What the plugin does |
|---|---|---|
| A Pix key (CPF, CNPJ, email, phone, or EVP) | KEY | Looks the key up in DICT and resolves the destination account for you. |
| A QR code (BR Code) | QR_CODE | Decodes the code and resolves the destination via DICT. See QR Codes. |
| The payee’s full account details | MANUAL | Uses the branch, account, participant, and owner document you provide — no DICT lookup needed. |
KEY and QR_CODE, you never supply the destination yourself. The plugin resolves it and returns it in the response, ready to show the payer for confirmation.
Request — pick the tab for your initiation type
type values are CACC (checking), SVGS (savings), TRAN (transaction), and OTHR (other). endToEndId is optional for all types — it’s auto-generated when omitted.
Response
The response returns the initiationid (used as initiationId in step 2) and the resolved destination:
Initiations expire. The response includes an
expiresAt timestamp — process the transfer before it lapses, or initiate again. This keeps a confirmed destination from going stale between the lookup and the payment.Step 2 — Process: move the money
Processing takes the initiation you just confirmed and executes the cash-out: it debits the source account and routes the payment to BTG for settlement with BACEN. Settlement with the Pix network is asynchronous. The transfer comes back as
PROCESSING while BTG settles, and the final result — completed or failed — arrives later through a cashout webhook. Build your flow to react to that event rather than waiting on the process response. See Webhooks.
Request
Pass theid from the initiate response as initiationId, along with the amount to transfer:
amount is required. You can also pass an optional description (max 140 characters) and metadata (custom key-value attributes).
The X-Purpose header
Use the optional X-Purpose header to declare why the cash-out is happening. It defaults to TRANSFER when omitted:
| Value | When to use |
|---|---|
TRANSFER | A regular Pix cash-out — the default for ordinary payments. |
INSTANT_PAYMENT_REFUND | When the cash-out is refunding a previously received instant payment, so the network can classify it as a refund rather than a new transfer. |
Fixed-amount QR codes: when the initiation is a
QR_CODE whose EMV payload carries a fixed amount, the amount you send to process must equal that encoded amount. A mismatch is rejected before any funds move.Response
When the destination belongs to your own institution, the money never leaves for BTG — it settles internally as a P2P transfer. See Intra-PSP transfers.
Tracking a transfer
Every transfer follows a predictable lifecycle: it starts in
PENDING/PROCESSING while it’s in flight, then reaches a terminal COMPLETED, FAILED, or CANCELLED. To check where a transfer stands, you can retrieve a single one by its id, or list transfers filtered by status, type (cash-out or cash-in), or date range.
status, type (CASHOUT/CASHIN), end_to_end, and modified_after/modified_before, plus limit/offset/sort_order pagination.
When a transfer gets stuck
If the settlement call to BTG times out before it confirms, a transfer can stay in
PROCESSING with its funds still on hold. The plugin provides an unblock operation that re-checks the transfer with BTG and drives it to the correct final state — settling it if BTG confirms, or releasing the hold if BTG never received it.
Unblock doesn’t apply to intra-PSP transfers — there’s no BTG transaction to re-check. For the full unblock behavior and its options, see Refund operations.
Next steps
- Intra-PSP transfers — Internal P2P settlement
- QR Codes — Generating and decoding QR codes
- Refund operations — Refunds and unblocking
- Webhooks — Cash-out and cash-in event handling
- API reference — Full request/response details, headers, and field schemas

