> For the complete documentation index, see [llms.txt](https://docs.cashramp.co/cashramp/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.cashramp.co/cashramp/cashramp-api/withdraw-to-bank.md).

# Withdraw to Bank

Withdraw your local-currency balance to a bank account as an instant bank transfer.

Nigeria is the only supported destination today, so the balance debited is your **NGN** balance. No FX conversion happens: naira in, naira out.

### Find the Bank

`withdrawToBank` identifies the destination bank by ID, so list the banks available in the country first.

```graphql
query {
  banks(
    country: "VHlwZXM6OkNvdW50cnktN2FhZjdlYjEtODIwYi00YzA4LWIyM2ItODFlN2FjMTQyYmI0"
  ) {
    id # Pass this as `bank`
    name # "Access Bank"
    code # "044"
    resolvable # true when the account name can be looked up
  }
}
```

Get the `country` ID from [`availableCountries`](/cashramp/cashramp-api/queries.md#available-countries).

***

### Verify the Account

Optional, but worth doing before you move money: resolve the account number to the name on the account and show it back to whoever requested the payout.

```graphql
query {
  resolveBankAccount(
    bank: "VHlwZXM6OkJhbmstMzljYzE4MGYtYThjNC00Zjc2LWJlZGQtNWI1NzNjNjYxMDU4"
    accountNumber: "0123456789"
  )
}
```

Returns the account name as a string, or `null` when the account cannot be resolved.

***

### Create the Withdrawal

```graphql
mutation {
  withdrawToBank(
    bank: "VHlwZXM6OkJhbmstMzljYzE4MGYtYThjNC00Zjc2LWJlZGQtNWI1NzNjNjYxMDU4"
    accountNumber: "0123456789"
    amount: 20000
  ) {
    id
    amount # 20000 — what lands in the destination account
    feeLocal # 25 — charged on top of `amount`
    reference
    status # initiated
    createdAt
  }
}
```

#### Arguments

| Name            | Type       | Required | Description                                                                                                           |
| --------------- | ---------- | -------- | --------------------------------------------------------------------------------------------------------------------- |
| `bank`          | `ID!`      | **Yes**  | Destination bank, from the `banks` query.                                                                             |
| `accountNumber` | `String!`  | **Yes**  | Destination account number at that bank.                                                                              |
| `amount`        | `Decimal!` | **Yes**  | Amount in the destination currency that the recipient should receive. Rounded to the currency's minor unit.           |
| `currency`      | `String`   | No       | Destination currency. Defaults to the bank country's currency; pass it only to assert what you expect (e.g. `"NGN"`). |

#### Fees

The transfer fee is charged **on top of** `amount`, so the recipient receives the full amount you requested and your balance is debited `amount + feeLocal`.

| Withdrawal amount (NGN)    | Fee     |
| -------------------------- | ------- |
| Up to and including ₦5,000 | **₦10** |
| Over ₦5,000, up to ₦50,000 | **₦25** |
| Over ₦50,000               | **₦50** |

The minimum withdrawal is **₦500**. The response's `feeLocal` is the fee actually applied; `amountUsd` and `fee` restate the same figures in USD at the current rate, for reconciliation only.

The mutation fails if:

* The destination country is not supported for payouts.
* `currency` is supplied and is not the bank country's currency.
* `amount` is below the minimum for the destination country.
* Your local-currency balance cannot cover `amount` plus the fee.
* The account number cannot be resolved at the selected bank.

***

### Receive Status Updates

The mutation returns as soon as the withdrawal is queued, with `status: initiated`. Your balance is debited at that point — the amount and fee move into a pending state and settle when the transfer completes.

You'll get a `fiat_payout.updated` webhook as the payout progresses.

```json
{
  "event_type": "fiat_payout.updated",
  "data": {
    "id": "VHlwZXM6OlBheW1lbnQtYWMzZjg5NjItYzc0ZC00ZjVjLWE0OWQtZGJiMzFjNTA3OTM3",
    "payment_type": "withdrawal",
    "amount": 20000,
    "amount_usd": 13.33,
    "fee_local": 25,
    "currency": "NGN",
    "reference": "505dc8e9-0d58-4e42-b8bc-18aa5706db28",
    "status": "completed",
    "destination": {
      "account_name": "ACME LTD",
      "account_number": "0123456789",
      "bank_name": "Access Bank"
    }
  }
}
```

The payout status is `processing` once the transfer is accepted, then `completed` or `failed`. A payout that fails after being accepted returns the full `amount + feeLocal` to your balance, so treat `failed` as money-back rather than money-gone.

{% hint style="info" %}
A transfer the provider rejects outright is retried on the next run and does not emit an event, so a payout can sit at `initiated` for a short while before you see `processing`.
{% endhint %}
