---
title: "Withdraw BRL from a customer's balance"
method: POST
path: "/withdrawals"
tags: ["Accounts"]
---

# Withdraw BRL from a customer's balance

`POST /withdrawals`

## Request

- Base URL: `https://developers.ozav.io/v2`
- URL: `https://developers.ozav.io/v2/withdrawals`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Sends a Pix from the customer's BRL **balance** (what deposits and sales
credited to that customer) to one of **the customer's own** payout
destinations. The balance is debited when the withdrawal is created;
nothing is converted. The response does not name the account the money
leaves from.

The destination must belong to the same customer and be a BRL destination
with a Pix key; the payment institution also checks that the destination's
document is the customer's. Payments to third parties are not available on
this endpoint.

**`reference` is the idempotency lever.** The same `reference` for the same
customer returns the existing withdrawal with `200` and its current status,
even if the destination was deactivated since. The same `reference` with a
different `amount` or destination is `409 WITHDRAWAL_IDEMPOTENCY_CONFLICT`.

When the institution refuses the Pix, the amount goes back to the customer's
balance and the withdrawal is `rejected` with `balance_restored: true`. An
outcome the institution has not confirmed yet stays `pending`, with the
amount reserved from the balance, until it is confirmed either way.

Refusals, with named codes: withdrawals not enabled for your organization yet
(`422 WITHDRAWALS_NOT_ENABLED`); the balance does not cover the amount
(`422 WITHDRAWAL_INSUFFICIENT_BALANCE`); no account ready to pay this
customer (`422 WITHDRAWAL_ACCOUNT_NOT_AVAILABLE`, the reason in `details`);
the balance is moving to the customer's own account
(`409 WITHDRAWAL_BALANCE_IN_TRANSIT`, retry once it arrives); the institution
refused it (`502 WITHDRAWAL_DISPATCH_FAILED`, nothing left and the balance is
restored); the institution did not confirm it (`502 WITHDRAWAL_OUTCOME_UNCONFIRMED`:
the amount stays reserved until the outcome is confirmed; read
`GET /withdrawals/{withdrawal_id}` before retrying). When it cannot be created right now the answer is
`503 WITHDRAWAL_UNAVAILABLE`: retry with the same `reference`.

## Request body

- WithdrawalCreateRequest
  - `customer_id` string, required: The customer who withdraws (`ozav_cus_...`).
  - `payout_destination_id` string, required: One of that customer's own BRL payout destinations (`ozav_pd_...`).
  - `amount` object, required
    - `currency` 'BRL', required
    - `value` string, required
  - `reference` string, required: Your idempotency handle for this withdrawal; it also travels with the Pix.

## Response `200`

The same withdrawal already existed (same `reference`).

- Withdrawal
  - `id` string, required
  - `object` 'withdrawal', required
  - `customer_id` string, required
  - `payout_destination_id` string, required
  - `amount` object, required
    - `currency` 'BRL'
    - `value` string
  - `reference` string, required
  - `status` 'pending' | 'accepted' | 'settled' | 'rejected', required
  - `balance_restored` boolean, required: true when the Pix did not leave and the amount is back in the customer's balance.
  - `created_at` string, date-time, nullable

## Other responses

- `201`: Withdrawal created and sent.
- `400`: The request is invalid.
- `401`: Missing or invalid API key.
- `403`: The organization lacks the entitlement (code ENTITLEMENT_REQUIRED) or the key lacks the scope (code INSUFFICIENT_SCOPE). On money-moving requests (POST /transfers, POST /wallets/{wallet_id}/transfers) a compliance hold on the customer answers with code COMPLIANCE_HOLD: the hold is reviewed and lifted on OZAV's side; retrying does not clear it. When the only hold is a pause until pending onboarding documents are received, a withdrawal answers CUSTOMER_DOCUMENTS_PENDING instead: send what `requirements` on GET /customers/{id} lists; OZAV lifts the pause after reviewing it. On OZAV Services (live without the platform's KYB), any API outside decisions, screenings, lists and self-custody wallets answers with code PRODUCTION_NOT_ACTIVATED.
- `404`: The resource does not exist, is not visible to the caller, or the id was malformed for this position (see "Resource ids" under Errors). These share one status; `code` and `message` tell them apart.
- `409`: Conflict (e.g. IDEMPOTENCY_KEY_REUSED).
- `422`: The request is well-formed but cannot be fulfilled - e.g. a `rail` that is not served (see `Rail.x-ozav-rail-availability`).
- `502`: The payment institution refused the withdrawal (`WITHDRAWAL_DISPATCH_FAILED`; nothing left and the amount is back in the customer's balance), or did not confirm it (`WITHDRAWAL_OUTCOME_UNCONFIRMED`; the amount stays reserved until the outcome is confirmed).
- `503`: A dependency OZAV needs (storage, a resource lookup) could not be reached, so OZAV fails closed rather than guess. Safe to retry with the same `Idempotency-Key` where the operation accepts one.

---

[API](https://skmtc.dev/ozav/apis/ozav-api.md) - [All operations](https://skmtc.dev/ozav/apis/ozav-api/llms.txt) - [OpenAPI document](https://skmtc.dev/ozav/apis/ozav-api/revisions/4133dc2109d7?raw)
