> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Transfers and cash-out

> Send Pix cash-out through the Indirect Pix Plugin via BTG — the two-step initiate-and-process flow that confirms the destination before moving funds.

A Pix cash-out moves money from an account to an external destination. The **Indirect Pix Plugin (BTG)** runs it in two steps — **initiate**, then **process**. You confirm *where* the money goes 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 receives the money.** The initiate response returns the resolved account owner. Your app can display the real name and let the payer confirm first.
* **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.

<Note>
  Both steps are idempotent — safe to retry without creating duplicate transfers. See [Retries and idempotency](/en/reference/retries-idempotency).
</Note>

## 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](/en/rails/pix/btg/indirect-pix-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](/en/rails/pix/btg/indirect-pix-qrcodes). |
| The payee's full account details            | `MANUAL`        | Uses 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

<CodeGroup>
  ```json KEY theme={null}
  POST /v1/transfers/cashout/initiate
  X-Account-Id: 01989f9e-6508-79f8-9540-835be49fbd0d
  {
    "initiationType": "KEY",
    "key": "john.doe@example.com"
  }
  ```

  ```json QR_CODE theme={null}
  POST /v1/transfers/cashout/initiate
  X-Account-Id: 01989f9e-6508-79f8-9540-835be49fbd0d
  {
    "initiationType": "QR_CODE",
    "emv": "00020126...5802BR5913Fulano..."
  }
  ```

  ```json MANUAL theme={null}
  POST /v1/transfers/cashout/initiate
  X-Account-Id: 01989f9e-6508-79f8-9540-835be49fbd0d
  {
    "initiationType": "MANUAL",
    "destination": {
      "account": {
        "branch": "0001",
        "number": "123456789",
        "participant": "12345678",
        "type": "CACC"
      },
      "owner": {
        "document": "12345678901",
        "name": "John Doe"
      }
    }
  }
  ```
</CodeGroup>

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`:

```json theme={null}
→ 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"
}
```

<Note>
  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.
</Note>

<Tip>
  **API reference:** [Initiate a Pix Transfer](/en/reference/midaz/plugins/indirect-pix/initiate-a-pix-transfer)
</Tip>

## Step 2 — Process: move the money

***

Processing executes the cash-out from the initiation you confirmed. It debits the source account, then 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. The final result — completed or failed — arrives later through a `cashout` webhook. Build your flow to react to that event, not to wait on the process response. See [Webhooks](/en/rails/pix/btg/indirect-pix-webhooks).

### Request

Pass the `id` from the initiate response as `initiationId`, along with the `amount` to transfer:

```json theme={null}
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 the reason for the cash-out. 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. |

<Note>
  **Fixed-amount QR codes:** the initiation can be a `QR_CODE` whose EMV payload carries a fixed amount. In that case, the `amount` you send to process **must equal** that encoded amount. A mismatch is rejected before any funds move.
</Note>

### Response

```json theme={null}
→ 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"
}
```

<Note>
  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](/en/rails/pix/btg/indirect-pix-intra-psp).
</Note>

<Tip>
  **API reference:** [Process a Pix Transfer](/en/reference/midaz/plugins/indirect-pix/process-a-pix-transfer)
</Tip>

## Tracking a transfer

***

Every transfer follows a predictable lifecycle. It starts in `PENDING`/`PROCESSING` while in flight, then reaches a terminal `COMPLETED`, `FAILED`, or `CANCELLED`. To check where a transfer stands, retrieve a single one by its id. You can also list transfers filtered by status, type (cash-out or cash-in), or date range.

```json theme={null}
GET /v1/transfers?type=CASHOUT&status=COMPLETED&limit=10&page=1
X-Account-Id: 01989f9e-6508-79f8-9540-835be49fbd0d
```

List filters include `status`, `type` (`CASHOUT`/`CASHIN`), `end_to_end`, and `modified_after`/`modified_before`, plus `page`/`limit`/`sort_order` pagination.

<Tip>
  **API reference:** [List transfers](/en/reference/midaz/plugins/indirect-pix/list-pix-transfers) · [Retrieve a transfer](/en/reference/midaz/plugins/indirect-pix/retrieve-a-pix-transfer)
</Tip>

## How transfers land in Midaz

***

The plugin posts every settled movement to Midaz as a ledger transaction, with the external leg against the `@external/BRL` account. Midaz records the accounting entry and correlation metadata — not the transfer's full banking details. Counterparty branch, account number, account type, and Pix key never reach Midaz; the one exception is the payer's identity on cash-in (`sourceBank`, `sourceDocument`, `sourceName`), stamped when known. The full counterparty detail lives in the plugin's transfer record.

The metadata stamped on the Midaz transaction depends on the flow:

| Flow         | Metadata keys                                                                                                                                                      |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Cash-out     | `initiationId`, `endToEndId`, `accountId`, `transferType: CASHOUT`, `paymentType`, `initiationType`                                                                |
| Cash-in      | `endToEndId`, `accountId`, `transferType: CASHIN`, `paymentType`, `initiationType` — plus `sourceBank`, `sourceDocument`, and `sourceName` when the payer is known |
| Refund (out) | `refundId`, `originalEndToEndId`, `returnIdentification`, `accountId`, `transferType: REFUND_CASHOUT`, `refundType`, `reason`                                      |
| Refund (in)  | The same refund keys with `transferType: REFUND_CASHIN`                                                                                                            |

The Midaz transaction `code` also carries the `endToEndId` (or the `returnIdentification` for refunds), so the E2E identifier is visible directly on the ledger entry.

Correlation works in both directions:

* The plugin stores the Midaz transaction and operation identifiers on its own transfer and refund records, and uses them to commit, cancel, or revert ledger entries.
* The Midaz transaction carries correlation keys in its metadata: filter by `metadata.endToEndId` for cash-outs and cash-ins, or by `metadata.originalEndToEndId` / `metadata.returnIdentification` for refunds. The transaction `code` is the common fallback — it carries the E2E ID on transfers and the return identification on refunds.

<Note>
  Custom `metadata` you pass when processing a cash-out is stored with the plugin's transfer record and returned by the plugin's own API. It is **not** copied onto the Midaz transaction — the Midaz metadata keys above are fixed by the plugin.
</Note>

## When a transfer gets stuck

***

If the settlement call to BTG times out before BTG confirms, a transfer can stay in `PROCESSING` with its funds on hold. The plugin provides an **unblock** operation. Unblock re-checks the transfer with BTG and drives it to the correct final state. It settles the transfer if BTG confirms, or releases the hold if BTG never received it.

<Note>
  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](/en/rails/pix/btg/indirect-pix-refund-operations).
</Note>

## Next steps

***

* [Intra-PSP transfers](/en/rails/pix/btg/indirect-pix-intra-psp) — Internal P2P settlement
* [QR Codes](/en/rails/pix/btg/indirect-pix-qrcodes) — Generating and decoding QR codes
* [Refund operations](/en/rails/pix/btg/indirect-pix-refund-operations) — Refunds and unblocking
* [Webhooks](/en/rails/pix/btg/indirect-pix-webhooks) — Cash-out and cash-in event handling
* [API reference](/en/reference/midaz/plugins/indirect-pix/initiate-a-pix-transfer) — Full request/response details, headers, and field schemas
