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

# Create Payout API

Use this endpoint to disburse funds to a beneficiary. The payout consumes an existing quote, validates the beneficiary, and queues the transfer for settlement.

The code examples below mirror the corridors covered in our payout guides. Select the appropriate `recipient` payload to match your payout use case, or browse the dedicated [payout examples](/payout-docs/payout-examples/ngn-ngn-example) for a full walkthrough.

## Endpoint

**POST** `https://sandboxapi.me-cash.com/v2/payout`

<Tip>
  **Environment Note:** The endpoint above is for Sandbox testing. In Production, replace `sandboxapi` with `api` (`https://api.me-cash.com/v2/payout`).

  You must supply the `quoteId` generated by the [`Create Quote API`](/quote-docs/create-quote). Quotes that have expired or already been consumed will be rejected.
</Tip>

## Request headers

| Header         | Description                           | Required | Example            |
| -------------- | ------------------------------------- | -------- | ------------------ |
| `x-api-key`    | Workspace API key for authentication. | ✅ Yes    | `YOUR_API_KEY`     |
| `Content-Type` | Media type of the request body.       | ✅ Yes    | `application/json` |

## Request body

```json copy theme={null}
{
  "recipient": {
    "name": "Chris Tiana",
    "paymentChannel": "BANK_TRANSFER",
    "country": "NG",
    "stored": false,
    "account": {
      "bankName": "Guaranty Trust Bank",
      "sortCode": "058",
      "accountNumber": "0712617XXX"
    }
  },
  "quoteId": "453eeu-567j-6tr3d-xxxxxxxxxxxxx",
  "reason": "Bills",
  "invoice": "4b9b6d30-a2ed-421a-bd69-xxxxxxxxxxxx",
  "remark": ""
}
```

### Body fields

| Field                             | Type    | Description                                                                                                        | Required | Example                                |
| --------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------ | -------- | -------------------------------------- |
| `recipient.name`                  | String  | Full name of the beneficiary.                                                                                      | ✅ Yes    | `Chris Tiana`                          |
| `recipient.paymentChannel`        | String  | Channel to deliver funds (`BANK_TRANSFER`, `MOBILE_MONEY`, `SWIFT_CUSTOMER`, `SWIFT_SHARED`, `SWIFT_BENEFICIARY`). | ✅ Yes    | `BANK_TRANSFER`                        |
| `recipient.country`               | String  | Recipient country (ISO 3166-1 alpha-2).                                                                            | ✅ Yes    | `NG`                                   |
| `recipient.stored`                | Boolean | Whether the recipient is saved in your address book.                                                               | ✅ Yes    | `false`                                |
| `recipient.account.bankName`      | String  | Financial institution name.                                                                                        | ✅ Yes    | `Guaranty Trust Bank`                  |
| `recipient.account.sortCode`      | String  | Routing or sort code where applicable.                                                                             | ✅ Yes    | `058`                                  |
| `recipient.account.accountNumber` | String  | Destination account number.                                                                                        | ✅ Yes    | `0712617XXX`                           |
| `quoteId`                         | String  | Quote identifier returned from the Quote API.                                                                      | ✅ Yes    | `453eeu-567j-6tr3d-xxxxxxxxxxxxx`      |
| `reason`                          | String  | High-level purpose of the transfer.                                                                                | ✅ Yes    | `Bills`                                |
| `invoice`                         | String  | Optional identifier for the invoice (returned from file upload endpoint).                                          | ❌ No     | `4b9b6d30-a2ed-421a-bd69-xxxxxxxxxxxx` |
| `remark`                          | String  | Additional comments or reference.                                                                                  | Optional | `September utilities`                  |

Depending on the corridor and channel, additional fields (such as mobile wallet metadata or address information) may be required. Refer to the route-specific examples in [`payout docs examples`](/payout-docs/payout-examples/ngn-usd-example).

## Request examples

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST 'https://sandboxapi.me-cash.com/v2/payout' \
    --header 'x-api-key: YOUR_API_KEY' \
    --header 'Content-Type: application/json' \
    --data '{
      "recipient": {
        "name": "Chris Tiana",
        "paymentChannel": "BANK_TRANSFER",
        "country": "NG",
        "stored": false,
        "account": {
          "bankName": "Guaranty Trust Bank",
          "sortCode": "058",
          "accountNumber": "0712617XXX"
        }
      },
      "quoteId": "453eeu-567j-6tr3d-xxxxxxxxxxxxx",
      "reason": "Bills",
      "invoice": "4b9b6d30-a2ed-421a-bd69-xxxxxxxxxxxx",
      "remark": ""
    }'
  ```

  ```js JavaScript (fetch) theme={null}
  const payload = {
    recipient: {
      name: 'Chris Tiana',
      paymentChannel: 'BANK_TRANSFER',
      country: 'NG',
      stored: false,
      account: {
        bankName: 'Guaranty Trust Bank',
        sortCode: '058',
        accountNumber: '0712617XXX'
      }
    },
    quoteId: '453eeu-567j-6tr3d-xxxxxxxxxxxxx',
    reason: 'Bills',
    invoice: '4b9b6d30-a2ed-421a-bd69-xxxxxxxxxxxx',
    remark: ''
  };

  fetch('https://sandboxapi.me-cash.com/v2/payout', {
    method: 'POST',
    headers: {
      'x-api-key': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(payload)
  })
    .then((res) => {
      if (!res.ok) {
        throw new Error(`Request failed with status ${res.status}`);
      }
      return res.json();
    })
    .then((body) => console.log(body))
    .catch((error) => console.error('Failed to create payout', error));
  ```

  ```python Python (requests) theme={null}
  import requests

  url = "https://sandboxapi.me-cash.com/v2/payout"
  headers = {
      "x-api-key": "YOUR_API_KEY",
      "Content-Type": "application/json",
  }
  payload = {
      "recipient": {
          "name": "Chris Tiana",
          "paymentChannel": "BANK_TRANSFER",
          "country": "NG",
          "stored": False,
          "account": {
              "bankName": "Guaranty Trust Bank",
              "sortCode": "058",
              "accountNumber": "0712617XXX",
          },
      },
      "quoteId": "453eeu-567j-6tr3d-xxxxxxxxxxxxx",
      "reason": "Bills",
      "invoice": "4b9b6d30-a2ed-421a-bd69-xxxxxxxxxxxx",
      "remark": "",
  }

  response = requests.post(url, json=payload, headers=headers, timeout=30)
  response.raise_for_status()
  print(response.json())
  ```

  ```js Node.js (axios) theme={null}
  const axios = require('axios');

  axios.post('https://sandboxapi.me-cash.com/v2/payout', {
    recipient: {
      name: 'Chris Tiana',
      paymentChannel: 'BANK_TRANSFER',
      country: 'NG',
      stored: false,
      account: {
        bankName: 'Guaranty Trust Bank',
        sortCode: '058',
        accountNumber: '0712617XXX'
      }
    },
    quoteId: '453eeu-567j-6tr3d-xxxxxxxxxxxxx',
    reason: 'Bills',
    invoice: '4b9b6d30-a2ed-421a-bd69-xxxxxxxxxxxx',
    remark: ''
  }, {
    headers: {
      'x-api-key': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    timeout: 30000
  })
    .then((response) => {
      console.log(response.data);
    })
    .catch((error) => {
      if (error.response) {
        console.error('API error:', error.response.data);
      } else {
        console.error('Request error:', error.message);
      }
    });
  ```
</CodeGroup>

## Successful response

```json copy theme={null}
{
  "message": "payout queued",
  "status": "success",
  "data": {
    "id": "f4e597cc-18fa-4c23-b9c1-xxxxxxxxxxxxx",
    "invoice": "4b9b6d30-a2ed-421a-bd69-xxxxxxxxxxxx",
    "reference": "BILLS-20240915",
    "quoteId": "453eeu-567j-6tr3d-xxxxxxxxxxxxx",
    "state": "PROCESSING",
    "recipient": {
      "name": "Chris Tiana",
      "country": "NG",
      "paymentChannel": "BANK_TRANSFER"
    },
    "metadata": {},
    "created": "2024-09-15T10:32:11.238Z"
  }
}
```

### Field reference

| Field            | Type   | Description                                                  |
| ---------------- | ------ | ------------------------------------------------------------ |
| `data.id`        | String | Unique payout identifier returned by meCash.                 |
| `data.invoice`   | String | Optional identifier for the invoice provided in the request. |
| `data.reference` | String | Your client-generated reference if supplied.                 |
| `data.state`     | String | Initial processing state (`PROCESSING`, `QUEUED`, etc.).     |
| `data.recipient` | Object | Echoes key beneficiary attributes.                           |
| `data.created`   | String | ISO timestamp for when the payout was accepted.              |

## Error responses

| Status | Message                                               | Cause                                                             | How to resolve                                                                |
| ------ | ----------------------------------------------------- | ----------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| 400    | `Insufficient wallet balance for transaction`         | Wallet balance cannot cover the payout amount.                    | Top up the wallet or lower the payout total before retrying.                  |
| 400    | `Quotes only last for 10 minutes`                     | Quote expired before you attempted to consume it.                 | Generate a fresh quote and submit the payout immediately.                     |
| 400    | `Invalid country or currency ISO code`                | Unsupported country/currency combination supplied in the request. | Use corridor-supported ISO codes for both quote and recipient data.           |
| 400    | `Account name mismatch, use account enquiry endpoint` | Account name in payload differs from bank enquiry results.        | Re-run account enquiry and match the returned account name.                   |
| 400    | `Invalid Bank Sortcode`                               | Sort code missing, malformed, or unsupported.                     | Fetch the correct sort code from the bank list and verify formatting.         |
| 400    | `{field_name} cannot be empty`                        | Required recipient field omitted from the payload.                | Fill in every mandatory field (name, account number, etc.) before submitting. |
| 401    | `API key missing or incorrect`                        | `x-api-key` header absent, invalid, or expired.                   | Supply the correct API key for the environment you are targeting.             |
| 403    | `IP not whitelisted`                                  | Request originated from an unapproved IP.                         | Add your server IP to the dashboard allowlist.                                |
| 404    | `The requested endpoint does not exist`               | Incorrect API path or version specified.                          | Confirm you are calling `POST /v2/payout` on the right base URL.              |
| 422    | `Invalid quote ID provided`                           | Quote ID missing, invalid, expired, or already consumed.          | Create a new quote and reference it in the payout call.                       |
| 500    | `Service temporarily unavailable`                     | Temporary backend/service disruption.                             | Retry with exponential backoff; contact support if it persists.               |

## Best practices

* Generate idempotency references to safely retry without duplicating transfers.
* Validate recipients locally before calling the API to reduce error handling.
* Listen to [payout webhooks](/webhook/payout-webhook) and reconcile with the [`Get Transaction API`](/transaction-docs/get-transaction) for final settlement details.
* Need to pay multiple recipients at once? Use the [Bulk Payout API](/payout-docs/bulk-payout) instead.

<Tip>
  **Testing Failed Payouts:** In the sandbox environment, you can simulate a failed payout by setting `"remark": "fail"` in your request. This will trigger a [`payout.failed`](/webhook/payout-webhook) webhook, allowing you to test your error handling logic.
</Tip>
