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

> ## Agent Instructions
> Bitnob API requests authenticate with an `X-Auth-Client` API key header against https://api.bitnob.com.
> Always use the sandbox environment for testing. Never put live API keys in sample code.
> Money amounts are integers in the smallest unit of the currency (satoshis for BTC, cents for fiat). Never use floats.
> Every state-changing request takes a client-supplied `reference` and must be treated as idempotent on retry.
> Quotes expire. Re-quote rather than reusing a stale quote id.

# Send your first payout

> A complete first payout, from credentials to confirmed delivery: create a quote, attach a beneficiary, fund it, and track it to `SUCCESS`.

In this tutorial you send one payout end to end: lock a rate with a quote, attach a beneficiary, pay from your balance with finalize or fund it onchain, and watch it reach `SUCCESS`. Responses are shortened to the fields this tutorial uses.

## Prerequisites

* A Bitnob business account, created at [app.bitnob.com](https://app.bitnob.com/), with payouts enabled by the compliance team.
* Your `CLIENT_ID` and `CLIENT_SECRET` from **Settings → API Keys**. The secret is shown once; store it securely.
* A signing helper that adds the four `X-Auth-*` headers to every request. Build one with [Authentication](https://www.bitnob.dev/api-reference/authentication/authentication.md); it has reference implementations in Node.js, Go, and Python.

If you whitelist IPs (**Settings → IP**), add your server's IP before testing, or requests will be rejected.

Every request goes to `https://api.bitnob.com`. Sandbox and production share that URL; the secret you sign with selects the environment. Test in sandbox first.

**1. Pick a destination and validate the beneficiary**

Look up what your destination country needs before you quote. The short version:

```http theme={null}
GET {BASE_URL}/api/payouts/supported-countries        # where you can pay out
GET {BASE_URL}/api/payouts/supported-countries/NG     # required beneficiary fields
GET {BASE_URL}/api/payouts/banks/NG                   # bank names and codes
GET {BASE_URL}/api/payouts/account-lookup?country=NG&account_number=0123456789&bank_code=000013
```

Confirm the lookup returns `is_verified: true` and the `account_name` you expect. Ghana bank accounts can't be looked up yet, so skip this step for them and have your user confirm the account name. The full walkthrough, including mobile money destinations, is in [Validate a beneficiary](https://www.bitnob.dev/docs/payouts/validate-a-beneficiary.md).

**2. Create a quote**

A quote locks the exchange rate and fees. `source` decides where the funds come from: `offchain` charges your Bitnob balance, `onchain` gives you a deposit address to pay per transaction.

```http theme={null}
POST {BASE_URL}/api/payouts/quotes
```

```json theme={null}
{
  "from_asset": "BTC",
  "to_currency": "NGN",
  "source": "onchain",
  "country": "NG",
  "chain": "lightning",
  "settlement_amount": "50000",
  "payment_reason": "Invoice payment",
  "reference": "your-unique-reference"
}
```

Provide one side of the conversion: `settlement_amount` (what the beneficiary receives) or `amount` (what you pay in `from_asset`). `chain` is required when `source` is `onchain`.

The response returns the payout record in status `QUOTE`:

```json theme={null}
{
  "success": true,
  "message": "Quote created successfully",
  "data": {
    "payout": {
      "id": "01a1490a-8853-701d-b999-12833458ac68",
      "quote_id": "QT2_21052918",
      "status": "QUOTE",
      "source": "ONCHAIN",
      "from_asset": "BTC",
      "chain": "CHAIN_TYPE_LIGHTNING",
      "to_currency": "NGN",
      "sat_amount": "45289",
      "btc_amount": "0.00045289",
      "amount": "0.00045289",
      "settlement_amount": "50000",
      "fees": "0",
      "exchange_rate": {
        "rate": "1809.3",
        "btc_rate": "61141.15",
        "currency": "ngn"
      },
      "trip": {
        "quote_at": "2026-10-17T08:46:29.195404170Z"
      },
      "reference": "your-unique-reference",
      "country": "NG",
      "expires_at": "2026-10-17T08:52:29.195416730Z"
    }
  }
}
```

Save `quote_id`. Note `expires_at`: the window is minutes, so continue promptly. Full schema: [Create quote](https://www.bitnob.dev/api-reference/payouts/create-quote.md).

**3. Initialize with the beneficiary**

Attach the recipient to the quote. The `beneficiary` shape depends on the country; it is exactly what step 1's country requirements returned.

```http theme={null}
POST {BASE_URL}/api/payouts/{quoteId}/initialize
```

```json theme={null}
{
  "beneficiary": {
    "account_number": "0123456789",
    "bank_code": "000013",
    "account_name": "Ada Okafor",
    "country": "NG"
  },
  "reference": "your-unique-reference",
  "payment_reason": "Invoice payment",
  "callback_url": "https://your-app.example.com/webhooks/payout"
}
```

`callback_url` is where webhook events for this payout are sent; set it.

For onchain funding the response moves the record to `PENDING_ADDRESS_DEPOSIT` and carries the funding instruction in `address`:

```json theme={null}
{
  "success": true,
  "message": "Payout initialized successfully",
  "data": {
    "payout": {
      "id": "01a1490a-8853-701d-b999-12833458ac68",
      "quote_id": "QT2_21052918",
      "status": "PENDING_ADDRESS_DEPOSIT",
      "from_asset": "BTC",
      "chain": "CHAIN_TYPE_LIGHTNING",
      "to_currency": "NGN",
      "sat_amount": "45289",
      "settlement_amount": "50000",
      "deposit_amount": "0.00045289",
      "beneficiary": {
        "account_name": "Ada Okafor",
        "account_number": "0123456789",
        "bank_code": "000013",
        "country": "NG"
      },
      "address": "lntb452890n1p4dxd0xpp53lg3cjx7hmmyglsf656djf4qp5hhu5dj5cn08f37nj7qmxu7g49sdqcf9h8vmmfvdjjqurp09kk2mn5cqzpgxqztxsp5dta7kw6clzy96q39k8h6dy6ranjf0d6624yy3rwt3fjprctkaqns9qrsgqp4vhncl2a3yvnnhexc45kwxp60u2xy6txp7nl6ajsfsgwcz3ldm50a0p79cmld72y4e7s2ekjmcd56x344vkhd9shzdjd0uzjd93a0spkswms9",
      "expires_at": "2026-10-17T08:52:29Z"
    }
  }
}
```

What `address` contains depends on `chain`: a BOLT11 invoice for `lightning` (`lnbc…` in production, `lntb…` testnet invoices in sandbox), a BTC address for `bitcoin`, or a deposit address on the relevant chain for stablecoins. With `source: "offchain"` there is no `address` and the record moves to `INITIATED` instead.

#### Beneficiaries for other corridors

Only the `beneficiary` object changes between corridors. Read the exact fields from country requirements in step 1. For example:

```json Ghana mobile money (MTN) theme={null}
{
  "destination_type": "mobile_money",
  "network": "mtn",
  "account_number": "233200000000",
  "account_name": "Jane Doe",
  "country": "GH"
}
```

```json Ghana bank account theme={null}
{
  "destination_type": "bank",
  "bank_code": "GH190100",
  "account_number": "0012345678901",
  "account_name": "Kwame Mensah",
  "country": "GH"
}
```

```json Kenya M-Pesa theme={null}
{
  "destination_type": "mobile_money",
  "network": "mpesa",
  "account_number": "254712345678",
  "account_name": "John Doe",
  "country": "KE"
}
```

For Ghana mobile money, set `network` to `mtn`, `vodafone` (Telecel Cash) or `airtel` (AirtelTigo Money) to match the recipient's number.

Each quote can be initialized once. A second initialize on the same quote fails with `400` "Quote '…' has already been initialized", so use a fresh quote for each payout.

Full schema: [Initialize payout](https://www.bitnob.dev/api-reference/payouts/initialize-payout.md).

**4. Finalize (offchain payouts)**

Finalize commits an offchain payout. It takes no request body, so sign an empty body string.

```http theme={null}
POST {BASE_URL}/api/payouts/{quoteId}/finalize
```

Your balance is debited here. Skip this step for onchain payouts: your deposit finalizes the payout automatically, and calling finalize before funding returns `400`. Full schema: [Finalize payout](https://www.bitnob.dev/api-reference/payouts/finalize-payout.md).

**5. Fund it**

**Onchain**: pay the `address` from the initialize response before `expires_at`. For Lightning, pay the invoice from any Lightning wallet; for `bitcoin` and stablecoins, send the full `deposit_amount` from the initialize response to the deposit address. It is the quoted amount plus fees, and a shorter deposit is refused. Once the payment confirms, settlement proceeds on its own.

**Offchain**: nothing to do, the payout is already proceeding.

**6. Track it to SUCCESS**

Two ways, and production systems use both:

* **Webhooks** arrive at your `callback_url` as the payout advances: `payouts.initialized`, `payouts.processing`, then `payouts.withdrawal.success` on delivery, `payouts.withdrawal.failed` if delivery fails, or `payouts.withdrawal.expired` if funding never arrived. Verify every signature; see [Receive payout webhooks](https://www.bitnob.dev/docs/payouts/webhook-payout.md).
* **Polling** covers the transitions that have no event:

```http theme={null}
GET {BASE_URL}/api/payouts/{id}
```

```json theme={null}
{
  "success": true,
  "message": "Payout retrieved successfully",
  "data": {
    "payout": {
      "id": "01a1490a-8853-701d-b999-12833458ac68",
      "quote_id": "QT2_21052918",
      "reference": "your-unique-reference",
      "status": "SUCCESS",
      "from_asset": "BTC",
      "to_currency": "NGN",
      "settlement_amount": "50000",
      "country": "NG",
      "beneficiary": {
        "account_name": "Ada Okafor",
        "account_number": "0123456789",
        "bank_code": "000013"
      }
    }
  }
}
```

`SUCCESS` is the only success state. A `FAILED` payout emits `payouts.withdrawal.failed`. Webhooks can be missed, so also schedule reconciliation sweeps with [List payouts](https://www.bitnob.dev/api-reference/payouts/list-payouts.md). The full status vocabulary is on [Statuses and webhook events](https://www.bitnob.dev/docs/payouts/statuses-and-webhook-events.md).

## Where to go next

* [How payouts settle](https://www.bitnob.dev/docs/payouts/settlement-models.md), if you have not yet chosen between balance funding and per-transaction funding.
* [Handle payout failures](https://www.bitnob.dev/docs/payouts/error-handling.md), before you take this to production.
* [Send a SWIFT payout](https://www.bitnob.dev/docs/payouts/swift-payout.md) for destinations with no local rail.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.