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

# Payouts

> Send money globally with Zuba payouts

## Overview

Payouts are the core functionality of the Zuba platform, enabling you to send money to beneficiaries worldwide through various payment rails including SEPA, SWIFT, crypto networks, and local payment methods.

## Payout Lifecycle

```mermaid theme={"dark"}
sequenceDiagram
    participant Client
    participant Zuba API
    participant Provider
    participant Bank/Wallet
    
    Client->>Zuba API: Create Payout
    Zuba API->>Zuba API: Validate & Record
    Zuba API-->>Client: Payout ID
    Zuba API->>Provider: Process Payment
    Provider->>Bank/Wallet: Transfer Funds
    Bank/Wallet-->>Provider: Confirmation
    Provider-->>Zuba API: Status Update
    Zuba API-->>Client: Webhook Notification
```

## Beneficiaries & Accounts

### Beneficiary Management

Before sending payouts, you must create beneficiaries with their payment details:

<CodeGroup>
  ```javascript Get Beneficiary theme={"dark"}
  const beneficiary = await fetch(`https://api.zuba.com/v1/beneficiaries/${beneficiaryId}`, {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY'
    }
  });
  ```

  ```javascript Create Beneficiary theme={"dark"}
  const beneficiary = await fetch('https://api.zuba.com/v1/beneficiaries', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      name: 'John Doe',
      email: 'john.doe@example.com',
      country: 'US',
      countrySubdivision: 'NY',
      address: '123 Main St',
      city: 'New York',
      postcode: '10001',
      accounts: [{
        type: 'bank_account',
        currency: 'USD',
        data: {
          accountNumber: '1234567890',
          routingNumber: '021000021',
          accountHolderName: 'John Doe',
          bankName: 'Chase Bank'
        }
      }]
    })
  });
  ```
</CodeGroup>

### Account Types

Zuba supports multiple account types for maximum flexibility:

<Tabs>
  <Tab title="Bank Accounts">
    **SEPA (European Union)**

    ```json theme={"dark"}
    {
      "type": "iban",
      "currency": "EUR",
      "data": {
        "iban": "DE89370400440532013000",
        "accountHolderName": "John Doe",
        "bic": "DEUTDEFF"
      }
    }
    ```

    **US ACH**

    ```json theme={"dark"}
    {
      "type": "bank_account",
      "currency": "USD",
      "data": {
        "accountNumber": "1234567890",
        "routingNumber": "021000021",
        "accountHolderName": "John Doe",
        "bankName": "Chase Bank"
      }
    }
    ```

    **UK Bank Account**

    ```json theme={"dark"}
    {
      "type": "bank_account",
      "currency": "GBP",
      "data": {
        "accountNumber": "12345678",
        "sortCode": "123456",
        "accountHolderName": "John Smith",
        "bankName": "Barclays"
      }
    }
    ```

    **Nigerian Bank Account**

    ```json theme={"dark"}
    {
      "type": "bank_account",
      "currency": "NGN",
      "data": {
        "bankCode": "044",
        "crAccount": "1234567890",
      }
    }
    ```

    **Ghanaian Bank Account**

    ```json theme={"dark"}
    {
      "type": "bank_account",
      "currency": "GHS",
      "data": {
        "bankCode": "gh_0002",
        "crAccount": "12223444555"
      }
    }
    ```

    **Sandbox-only currencies**

    <Note>
      **ZMW** (Zambian kwacha), **MZN** (Mozambican metical), **MWK** (Malawian
      kwacha) and **EGP** (Egyptian pound) are available in the **sandbox
      only**. Payouts to them settle with simulated outcomes — see
      [Sandbox testing](/guides/sandbox-testing#sandbox-only-payout-currencies).
      In production these currencies are not yet available and a payout to one
      is rejected at creation.
    </Note>

    ```json Zambian Bank Account (sandbox only) theme={"dark"}
    {
      "type": "bank_account",
      "currency": "ZMW",
      "data": {
        "bankCode": "260001",
        "accountNumber": "1234567890",
        "accountHolderName": "Chanda Mwansa"
      }
    }
    ```

    The same shape applies for `MZN`, `MWK`, and `EGP` — any `bankCode` is
    accepted in the sandbox.
  </Tab>

  <Tab title="Crypto Wallets">
    **USDT on Tron (TRC-20)**

    ```json theme={"dark"}
    {
      "type": "wallet",
      "currency": "USDT",
      "data": {
        "address": "TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9",
        "network": "TRON"
      }
    }
    ```

    **USDC on Solana (SPL)**

    ```json theme={"dark"}
    {
      "type": "wallet",
      "currency": "USDC",
      "data": {
        "address": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
        "network": "SOLANA"
      }
    }
    ```

    **USDC on Ethereum (ERC-20)**

    ```json theme={"dark"}
    {
      "type": "wallet",
      "currency": "USDC",
      "data": {
        "address": "0x742d35Cc6634C0532925a3b8D33AA5e0000000000",
        "network": "ETHEREUM"
      }
    }
    ```

    **USDT on Ethereum (ERC-20)**

    ```json theme={"dark"}
    {
      "type": "wallet",
      "currency": "USDT",
      "data": {
        "address": "0x742d35Cc6634C0532925a3b8D33AA5e0000000000",
        "network": "ETHEREUM"
      }
    }
    ```
  </Tab>

  <Tab title="Card Payouts">
    **Debit/Credit Card**

    ```json theme={"dark"}
    {
      "type": "card",
      "currency": "EUR",
      "data": {
        "cardNumber": "4242424242424242",
        "accountHolderName": "John Doe"
      }
    }
    ```
  </Tab>

  <Tab title="Mobile Money">
    Mobile money pays out to a recipient's phone wallet in **XOF** (West African
    CFA franc), **XAF** (Central African CFA franc), or **GHS** (Ghana cedi).

    ```json XOF (West Africa) theme={"dark"}
    {
      "type": "mobile",
      "currency": "XOF",
      "data": {
        "mobileProvider": "orange",
        "phoneNumber": "+2250123456789",
        "country": "CI"
      }
    }
    ```

    ```json XAF (Cameroon) theme={"dark"}
    {
      "type": "mobile",
      "currency": "XAF",
      "data": {
        "mobileProvider": "mtn",
        "phoneNumber": "+237650000000",
        "country": "CM"
      }
    }
    ```

    ```json GHS (Ghana) theme={"dark"}
    {
      "type": "mobile",
      "currency": "GHS",
      "data": {
        "mobileProvider": "mtn",
        "phoneNumber": "+233241234567",
        "country": "GH"
      }
    }
    ```

    `phoneNumber` must be in international format (including the `+`). `mobileProvider` must be valid for `country`:

    | Country       | `currency` | `country` | `mobileProvider`                |
    | ------------- | ---------- | --------- | ------------------------------- |
    | Côte d'Ivoire | `XOF`      | `CI`      | `orange`, `mtn`, `moov`, `wave` |
    | Senegal       | `XOF`      | `SN`      | `orange`, `free`, `wave`        |
    | Mali          | `XOF`      | `ML`      | `orange`, `moov`, `wave`        |
    | Burkina Faso  | `XOF`      | `BF`      | `orange`, `moov`, `wave`        |
    | Benin         | `XOF`      | `BJ`      | `mtn`, `moov`                   |
    | Togo          | `XOF`      | `TG`      | `moov`, `tmoney`                |
    | Cameroon      | `XAF`      | `CM`      | `mtn`, `orange`                 |
    | Ghana         | `GHS`      | `GH`      | `mtn`, `vodafone`, `airteltigo` |

    Pay out with `route: "mobile_money"`; the per-transaction amount depends on
    the destination currency — **XOF 200–2,000,000**, **XAF 500–1,000,000**,
    **GHS 5–25,000**. Ghana (GHS) requires the sender's first and last name via
    `senderInfo`; Cameroon (XAF) requires the sender's name **and** phone. Ghana
    (GHS) is also **dual-rail** — the same currency pays out over a bank account
    (see [Bank Account](#account-types)). See
    [Mobile money](#mobile-money-xof-xaf-and-ghs) below.
  </Tab>
</Tabs>

## Creating Payouts

### Single Payout

After creating a beneficiary, use their ID to create payouts (recommended approach).

**Currency Fields:** `inputCurrency` is the currency from your account you'll be paying from, while `currency` is what the beneficiary will receive (automatic conversion if different):

<CodeGroup>
  ```javascript Single Payout (Recommended) theme={"dark"}
  const payout = await fetch('https://api.zuba.com/v1/payouts', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      clientRef: 'PAYOUT-INV-001',
      amount: '1000.00',
      inputCurrency: 'EUR',
      currency: 'NGN',
      route: 'bank_transfer',
      senderInfo: {
        firstName: 'Jack',
        lastName: 'Jones',
        address: '456 London Road',
        city: 'London',
        postalCode: 'SW1A 1AA',
        country: 'GB',
        dateOfBirth: '1985-06-15'
      },
      beneficiary: {
        id: 'cc82fa1d-fc7a-478c-a734-d3bce40464e7'
      },
      reference: 'Invoice #INV-001',
      description: 'Payment for marketing services'
    })
  });
  ```
</CodeGroup>

### Batch Payouts

Process multiple payouts in a single API call for efficiency:

<CodeGroup>
  ```javascript Batch Payouts theme={"dark"}
  const payouts = await fetch('https://api.zuba.com/v1/payouts', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify([
      {
        clientRef: 'PAYOUT-BATCH-001',
        beneficiary: { id: 'ben_1234567890' },
        amount: '1000.00',
        inputCurrency: 'EUR',
        currency: 'EUR',
        senderInfo: {
          firstName: 'Jack',
          lastName: 'Jones',
          address: '456 London Road',
          city: 'London',
          postalCode: 'SW1A 1AA',
          country: 'GB',
          dateOfBirth: '1985-06-15'
        },
        reference: 'Salary March 2024'
      },
      {
        clientRef: 'PAYOUT-BATCH-002',
        beneficiary: { id: 'ben_0987654321' },
        amount: '1500.00',
        inputCurrency: 'EUR',
        currency: 'USD',
        senderInfo: {
          firstName: 'Jack',
          lastName: 'Jones',
          address: '456 London Road',
          city: 'London',
          postalCode: 'SW1A 1AA',
          country: 'GB',
          dateOfBirth: '1985-06-15'
        },
        reference: 'Freelancer payment'
      }
    ])
  });
  ```
</CodeGroup>

## Payment Routes

Zuba automatically selects the optimal payment route, but you can specify preferences:

| Route           | Regions                                                                                      | Speed                       |
| --------------- | -------------------------------------------------------------------------------------------- | --------------------------- |
| `sepa_credit`   | European Union                                                                               | 1-2 business days           |
| `sepa_inst`     | EU (SEPA Instant banks)                                                                      | \< 10 seconds               |
| `bank_transfer` | Multiple regions                                                                             | Varies by destination       |
| `ach`           | United States                                                                                | 1-3 business days           |
| `fedwire`       | United States (domestic wire)                                                                | Same business day           |
| `swift`         | International (availability varies by destination country)                                   | 1-3 business days           |
| `crypto`        | On-chain (Ethereum, Solana, Tron)                                                            | Minutes (network-dependent) |
| `mobile_money`  | West Africa (XOF — CI, SN, ML, BF, BJ, TG), Central Africa (XAF — Cameroon), and Ghana (GHS) | Minutes                     |

### Crypto rail

Set `route: "crypto"` to send a stablecoin (`USDC` or `USDT`) on-chain to a crypto
wallet beneficiary. The `currency` is the stablecoin and is debited from your
same-currency balance (no FX). The destination network and address come from the
beneficiary's `wallet` account (see **Crypto Wallets** above), so the request only
references the beneficiary by `id`:

```javascript Crypto Payout theme={"dark"}
const payout = await fetch('https://api.zuba.com/v1/payouts', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    clientRef: 'PAYOUT-CRYPTO-001',
    amount: '250.00',
    currency: 'USDC',
    route: 'crypto',
    beneficiary: { id: 'cc82fa1d-fc7a-478c-a734-d3bce40464e7' },
    reference: 'Contractor payment'
  })
});
```

The funds are held the moment the payout is created, screened for compliance,
then signed and broadcast on-chain. The payout reaches `paid` only once the
transaction has broadcast; if it is declined or signing fails, the held funds are
returned to your balance automatically. Crypto payouts are availability-gated per
environment — contact your account manager to enable them.

Once the transfer is broadcast, `GET /v1/payouts/{id}` returns the on-chain
transaction hash in the `txHash` field (`null` for non-crypto payouts or before
broadcast). Use it to look the transfer up on a block explorer for the payout's
network.

### Mobile money (XOF, XAF, and GHS)

Set `route: "mobile_money"` to pay out **XOF** to a recipient's mobile money
wallet across West Africa, **XAF** to a wallet in Cameroon, or **GHS** to a
wallet in Ghana. The destination provider and phone number come from the
beneficiary's `mobile` account (see **Mobile Money** under Account Types above):

```javascript Mobile Money Payout theme={"dark"}
const payout = await fetch('https://api.zuba.com/v1/payouts', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    clientRef: 'PAYOUT-MM-001',
    amount: '5000',
    currency: 'XOF',
    route: 'mobile_money',
    beneficiary: { id: 'cc82fa1d-fc7a-478c-a734-d3bce40464e7' },
    reference: 'Supplier payment'
  })
});
```

Supported in **Côte d'Ivoire, Senegal, Mali, Burkina Faso, Benin, and Togo**
(XOF), **Cameroon** (XAF), and **Ghana** (GHS). The per-transaction amount
depends on the destination currency — **XOF 200–2,000,000**, **XAF
500–1,000,000**, **GHS 5–25,000**. A mismatched provider/country, an invalid
phone number, an unsupported country, a currency that isn't `XOF`/`XAF`/`GHS`, or
an out-of-range amount is rejected at creation.

**Ghana (GHS) is dual-rail.** The same currency also pays out over a bank account
(`route: "bank_transfer"`); the rail is chosen by the beneficiary's account type
(`mobile` vs `bank_account`). **GHS mobile requires the sender's first and last
name** via `senderInfo` (no phone — unlike Cameroon), or the payout is rejected:

```javascript GHS Mobile Money Payout (Ghana) theme={"dark"}
const payout = await fetch('https://api.zuba.com/v1/payouts', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    clientRef: 'PAYOUT-MM-GHS-001',
    amount: '100',
    currency: 'GHS',
    route: 'mobile_money',
    beneficiary: { id: 'cc82fa1d-fc7a-478c-a734-d3bce40464e7' },
    senderInfo: {
      type: 'individual',
      firstName: 'Ama',
      lastName: 'Owusu'
    },
    reference: 'Supplier payment'
  })
});
```

**Cameroon (XAF) additionally requires sender details.** Supply the originator's
name and phone in `senderInfo`, or the payout is rejected:

```javascript XAF Mobile Money Payout (Cameroon) theme={"dark"}
const payout = await fetch('https://api.zuba.com/v1/payouts', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    clientRef: 'PAYOUT-MM-XAF-001',
    amount: '2000',
    currency: 'XAF',
    route: 'mobile_money',
    beneficiary: { id: 'cc82fa1d-fc7a-478c-a734-d3bce40464e7' },
    senderInfo: {
      type: 'individual',
      firstName: 'Jane',
      lastName: 'Doe',
      phoneNumber: '+237655555555'
    },
    reference: 'Supplier payment'
  })
});
```

Mobile money is a gated corridor — contact your account manager to enable it.

### USD rails

For USD payouts, three rails are surfaced by `GET /payouts/available-rails?accountId=<uuid>`:

* **`fedwire`** — domestic wire to a US bank. Requires routing + account number on the beneficiary.
* **`ach`** — batched same-day-to-3-day transfer to a US bank. Same required fields as fedwire.
* **`swift`** — international wire via SWIFT. Requires BIC + IBAN/account number + the beneficiary's bank country. Destination coverage spans most major markets and expands as corridors are enabled, so it is not a fixed list: `GET /payouts/available-rails?accountId=<uuid>` reports, per saved account, whether SWIFT currently serves that account's destination country (`available` plus an `unavailableReason` when it does not).

The rail is fixed at beneficiary-account creation time via the `route` field stored on the account, so payouts against an existing account don't re-prompt the sender to pick a method. New beneficiary accounts intended for SWIFT must be created with `type: "swift"` and supply `swiftCode`, `accountNumber`, `beneficiaryCountry`, and (optionally) `bankName` / `beneficiaryAddress` in `data`.

A SWIFT payout from a non-USD balance (e.g. NGN) is a cross-rate send: it passes through a quote (`POST /v1/quotes`), is debited in the source currency, and Zuba satisfies the USD outflow on the destination bank. A same-currency USD to USD SWIFT needs no quote and is sent 1:1 from your USD balance.

### Route Selection Logic

```mermaid theme={"dark"}
flowchart TD
    A[Payout Request] --> B{Currency & Destination}
    B --> C{SEPA Eligible?}
    C -->|Yes| D[SEPA/SEPA Instant]
    C -->|No| E{Same Country?}
    E -->|Yes| F[Local Rails]
    E -->|No| G[SWIFT/Correspondent Banking]
    B --> H{Crypto Currency?}
    H -->|Yes| I[Blockchain Network]
```

## Tracking & Status

### Payout Statuses

| Status       | Description                           | Next Actions        |
| ------------ | ------------------------------------- | ------------------- |
| `created`    | Payout has been created               | Can be cancelled    |
| `queued`     | Queued for processing                 | Monitor for updates |
| `processing` | Being processed by payment provider   | Monitor for updates |
| `paid`       | Successfully delivered to beneficiary | Download receipt    |
| `failed`     | Processing failed                     | Review error, retry |
| `cancelled`  | Cancelled by user or system           | Funds returned      |

A receipt can be downloaded for a payout in any status except `cancelled`. For a payout that is still in progress, the receipt reflects its current status.

### Amounts above corridor limits

Every corridor has an amount cap, and a payout or payout quote above it is rejected by the standard bounds checks. Amounts above corridor limits are served by the orders channel (`POST /v1/orders`) for order-enabled accounts: a quote-first flow where funds are held from your balance and the trade is executed by Zuba's desk within a stated execution window. See the [Trade Desk Orders guide](/guides/orders) or contact us to enable orders on your account.

### Real-time Tracking

<CodeGroup>
  ```javascript Check Status theme={"dark"}
  const payout = await fetch(`https://api.zuba.com/v1/payouts/${payoutId}`, {
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY'
    }
  });

  const data = await payout.json();
  console.log(data.status); // created, queued, processing, paid, failed, cancelled
  ```

  ```curl Check Status theme={"dark"}
  curl -X GET "https://api.zuba.com/v1/payouts/pay_1234567890" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```
</CodeGroup>

## Best Practices

<AccordionGroup>
  <Accordion title="Beneficiary Validation">
    * Always validate beneficiary details before creating
    * Use SEPA reachability check for EU transactions
    * Store beneficiary IDs for repeat payments
    * Keep beneficiary information up to date
  </Accordion>

  <Accordion title="Error Handling">
    * Implement proper error handling for all API calls
    * Use exponential backoff for retries
    * Monitor webhook notifications for status updates
    * Log all transactions for audit purposes
  </Accordion>

  <Accordion title="Security">
    * Never expose API keys in client-side code
    * Validate webhook signatures
    * Use HTTPS for all API communications
    * Implement proper access controls
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="First Payout Guide" icon="rocket" href="/guides/first-payout">
    Step-by-step guide to send your first payout
  </Card>

  <Card title="Batch Processing" icon="layer-group" href="/guides/batch-payouts">
    Learn how to process multiple payouts efficiently
  </Card>

  <Card title="Webhooks" icon="webhook" href="/guides/webhooks">
    Set up real-time notifications for payout status
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference/introduction">
    Complete API documentation for payouts
  </Card>
</CardGroup>
