Skip to main content
A Pix cash-out moves money out of an account to an external destination. The Indirect Pix Plugin (BTG) handles it in two deliberate steps — initiate, then process — so you always confirm where the money is going before any funds leave the ledger.

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.
This mirrors how a good payment experience works: look up the destination, confirm the details, then pay.
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 withInitiation typeWhat the plugin does
A Pix key (CPF, CNPJ, email, phone, or EVP)KEYLooks the key up in DICT and resolves the destination account for you.
A QR code (BR Code)QR_CODEDecodes the code and resolves the destination via DICT. See QR Codes.
The payee’s full account detailsMANUALUses the branch, account, participant, and owner document you provide — no DICT lookup needed.
For 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

POST /v1/transfers/cashout/initiate
X-Account-Id: 01989f9e-6508-79f8-9540-835be49fbd0d
{
  "initiationType": "KEY",
  "key": "john.doe@example.com"
}
Account 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 initiation id (used as initiationId in step 2) and the resolved destination:
201 Created
{
  "id": "019c96a0-0c82-7c3d-8dcc-c180868b45c4",
  "initiationType": "KEY",
  "endToEndId": "E1234567820240101000001234567890",
  "destination": { "account": { ... }, "owner": { ... } },
  "expiresAt": "2024-01-15T11:00:00Z",
  "createdAt": "2024-01-15T10:30:00Z"
}
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 the id from the initiate response as initiationId, along with the amount to transfer:
POST /v1/transfers/cashout/process
X-Account-Id: 01989f9e-6508-79f8-9540-835be49fbd0d
X-Purpose: TRANSFER
{
  "initiationId": "019c96a0-0c82-7c3d-8dcc-c180868b45c4",
  "amount": "100.50"
}
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:
ValueWhen to use
TRANSFERA regular Pix cash-out — the default for ordinary payments.
INSTANT_PAYMENT_REFUNDWhen 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

201 Created
{
  "id": "019c96a0-0c21-71f9-a487-66a1258278a1",
  "endToEndId": "E1234567820240101000001234567890",
  "amount": "100.50",
  "status": "PROCESSING",
  "type": "CASHOUT",
  "createdAt": "2024-01-15T10:30:00Z",
  "updatedAt": "2024-01-15T10:30:00Z"
}
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.
API reference: Process a Pix Transfer

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.
GET /v1/transfers?type=CASHOUT&status=COMPLETED&limit=10&offset=0
X-Account-Id: 01989f9e-6508-79f8-9540-835be49fbd0d
List filters include 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