> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.crisscross.money/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.crisscross.money/_mcp/server.

# Single Payouts

Single payouts allow you to send funds to one recipient at a time. This is ideal for one-off transactions, refunds, or when you need to process payouts individually.

## When to Use Single Payouts

* One-time payments to individual recipients
* Refunds or customer disbursements
* Small-scale operations
* Testing and development

## Creating a Single Payout

To create a single payout, you'll need:

1. **merchantId**: Your merchant identifier
2. **merchantReference**: Your internal reference for tracking and idempotency
3. **destinationValue**: Object with:
   * `minorAmount`: Amount in **minor units** (integer, e.g., `10000` = 100.00 NGN). See [Amount Format](#amount-format) below.
   * `currency`: Must be a supported payout currency (NGN, XOF, XAF, GHS, KES, TZS, UGX, ZAR, EGP — availability depends on the processors configured on your account)
4. **paymentMethodId**: `"banktransfer"`, `"mobilemoney"`, `"cash"`, or `"institutionwallet"` (note: no underscore, unlike the matching `recipient.type`)
5. **paymentLocation**: 3-letter ISO country code (e.g., NGA, KEN, EGY)
6. **Destination** — supply **either** `recipient` (inline details) **or** `payoutBeneficiaryId` (reference to a pre-registered, pre-validated recipient). The two are mutually exclusive. See [Choosing a Destination](#choosing-a-destination) below.
7. **sender**: Sender details for KYT/KYC screening — `fullName`, `identity` (document type, e.g. `passport` or `nationalId`), and `identityNumber` are required for all payouts; some destinations require additional fields (see the market pages)
8. **attributes** (optional): Key-value map for additional payout metadata or provider-specific options. Pass `{}` if not needed. See the API reference for supported keys per destination.

## Choosing a Destination

Each payout names its destination in one of two ways. Pick one — they are mutually exclusive on a single request.

* **Inline `recipient`** — supply the recipient's account details (bank account or mobile wallet) directly on every payout call. Details are validated synchronously at payout time. Fastest path for one-off payouts.
* **`payoutBeneficiaryId`** — pre-register the recipient once with `POST /v1/payout-beneficiaries`. CrissCross verifies the destination against the receiving network and runs AML pre-screening up front; once it reaches `status: approved` you reference it by `payoutBeneficiaryId` on every subsequent payout. This shrinks the per-call payload, surfaces verification failures **before** a payout is attempted, and prevents accidental detail drift between repeat payouts to the same recipient.

For the full registration, lifecycle, and signal flow, see [Payout Beneficiaries](/payout-beneficiaries).

**Recipient field shapes** — used when supplying `recipient` inline:

* For bank accounts: `type: "bank_account"`, `accountNumber`, `bankCode`, `accountHolderName`, `country`, optional `phoneNumber`
* For mobile wallets: `type: "mobile_money"`, `phoneNumber`, `country`, `operator`, optional `name`
* For cash pickup: `type: "cash"`, `fullName`, `country`, optional `phoneNumber`
* For institution wallets: `type: "institution_wallet"`, `fullName`, `country`, optional `phoneNumber`

### Amount Format

Amounts are specified in **minor units** (the smallest currency unit, like cents). The `minorAmount` field is an **integer**.

**Examples:**

* `10000` minorAmount = 100.00 NGN (Nigerian Naira, 2 decimal places)
* `5000` minorAmount = 50.00 KES (Kenyan Shillings, 2 decimal places)
* `5000` minorAmount = 5,000 XOF (CFA franc has **no** minor unit — the integer is the whole-unit amount)

**Important:** The number of decimal places follows the currency's ISO 4217 exponent. Most currencies have 2, but XOF, XAF, UGX, RWF, BIF, and GNF have none — for those, no multiplication applies.

## Request Examples

### Bank Account Payout

```json
{
  "merchantId": "your-merchant-id",
  "merchantReference": "PAYOUT-2024-001",
  "destinationValue": {
    "minorAmount": 1000000,
    "currency": "NGN"
  },
  "paymentMethodId": "banktransfer",
  "paymentLocation": "NGA",
  "recipient": {
    "type": "bank_account",
    "accountNumber": "0123456789",
    "bankCode": "044",
    "accountHolderName": "John Doe",
    "country": "NGA"
  },
  "sender": {
    "fullName": "Jane Smith",
    "identity": "passport",
    "identityNumber": "A12345678"
  },
  "attributes": {}
}
```

**Note:** `minorAmount: 1000000` = 10,000.00 NGN (NGN has 2 decimal places).

### Mobile Wallet Payout

```json
{
  "merchantId": "your-merchant-id",
  "merchantReference": "PAYOUT-2024-002",
  "destinationValue": {
    "minorAmount": 500000,
    "currency": "KES"
  },
  "paymentMethodId": "mobilemoney",
  "paymentLocation": "KEN",
  "recipient": {
    "type": "mobile_money",
    "phoneNumber": "254712345678",
    "country": "KEN",
    "operator": "mpesa",
    "name": "Jane Smith"
  },
  "sender": {
    "fullName": "Jane Smith",
    "phoneNumber": "27821234567",
    "nationality": "ZAF",
    "identity": "passport",
    "identityNumber": "A12345678",
    "dateOfBirth": "1990-01-15",
    "purposeOfFunds": "salary",
    "sourceOfFunds": "business income",
    "relationship": "employer"
  },
  "attributes": {}
}
```

**Note:** `minorAmount: 500000` = 5,000.00 KES. Kenya payouts require additional sender fields — see [Kenya](/payout-market-kenya).

### Payout Against a Pre-Registered Beneficiary

When the recipient was registered ahead of time via `POST /v1/payout-beneficiaries`, drop `recipient` and reference the beneficiary by `payoutBeneficiaryId` instead. Every other field on the request is unchanged.

```json
{
  "merchantId": "your-merchant-id",
  "merchantReference": "PAYOUT-2024-004",
  "destinationValue": {
    "minorAmount": 5000000,
    "currency": "UGX"
  },
  "paymentMethodId": "mobilemoney",
  "paymentLocation": "UGA",
  "payoutBeneficiaryId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "sender": {
    "fullName": "Jane Smith",
    "identity": "passport",
    "identityNumber": "A12345678"
  },
  "attributes": {}
}
```

**Note:** The referenced beneficiary must be in `status: approved` — a payout that references a `pending_review`, `rejected`, or `failed` beneficiary is rejected with `422`. See [Payout Beneficiaries](/payout-beneficiaries) for the full registration and lifecycle.

## Response Structure

### Successful Response

A successful payout response (HTTP 201) includes:

```json
{
  "status": "PENDING",
  "transactionId": "payout_9f8b7c6d5e4a3b2c1d0e",
  "message": "Payout transaction initiated successfully",
  "merchantReference": "PAYOUT-2024-001",
  "paymentMethodId": "banktransfer",
  "processorReference": "PROC-123456"
}
```

**Response fields:**

* `status`: Current status (`PENDING`, `PROCESSING`, `COMPLETED`, `FAILED`, `CANCELLED`)
* `transactionId`: Unique transaction identifier
* `message`: Status message
* `merchantReference`: Your provided merchant reference (if supplied)
* `sessionId`: Session ID (if applicable)
* `identifiers`: Additional identifiers related to the transaction
* `paymentAttributes`: Payment-specific attributes and metadata
* `paymentMethodId`: Payment method identifier
* `processorName`: Payment processor name
* `processorReference`: Payment processor reference
* `financialTransactionReference`: Financial transaction reference from the processor
* `currentAttemptId`: Current attempt identifier
* `batchPayoutId`: Batch payout identifier, if part of a bulk payout

## Payout Statuses

* **PENDING**: Payout has been created and is awaiting processing
* **PROCESSING**: Payout is currently being processed
* **COMPLETED**: Payout has been successfully completed
* **FAILED**: Payout has failed (check `message`, `identifiers`, and `paymentAttributes` for details)
* **CANCELLED**: Payout was cancelled

## Error Handling

The API returns standard HTTP status codes:

* `201`: Payout transaction initiated successfully
* `400`: Bad Request - Invalid payout parameters or insufficient balance
* `401`: Unauthorized - Invalid or missing authentication
* `422`: Request validation failed
* `500`: Internal server error

### Error Response Structure

Error responses (HTTP 400, 401, 422) include an `error` object with `code` and `message` fields:

```json
{
  "error": {
    "code": "INSUFFICIENT_BALANCE",
    "message": "Insufficient balance in payout source account"
  }
}
```

**Example error responses:**

**Insufficient Balance (400):**

```json
{
  "error": {
    "code": "INSUFFICIENT_BALANCE",
    "message": "Insufficient balance in payout source account"
  }
}
```

**Invalid Parameters (400):**

```json
{
  "error": {
    "code": "INVALID_REQUEST",
    "message": "Invalid recipient details provided"
  }
}
```

**Unauthorized (401):**

```json
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid or expired access token"
  }
}
```

**Common error codes:**

* `INSUFFICIENT_BALANCE`: Not enough funds in the payout currency
* `INVALID_REQUEST`: Invalid request parameters (e.g., invalid currency, missing required fields)
* `INVALID_RECIPIENT`: Invalid recipient details (e.g., invalid account number, phone number)
* `UNAUTHORIZED`: Invalid or expired access token
* `RATE_LIMIT_EXCEEDED`: Too many requests (see [Rate Limiting](/rate-limiting))

## Example Use Cases

* **Refund Processing**: Send refunds to customers who returned products
* **Vendor Payments**: Pay individual suppliers or service providers
* **Customer Rewards**: Distribute loyalty rewards or cashback
* **One-off Disbursements**: Send individual payments as needed

## Idempotency

Each payout must use a `merchantReference` that is unique within your merchant account. The reference guards against accidental duplicate payouts.

If you initiate a payout with a `merchantReference` that was already used by a previous payout, the request is **rejected** with a `DUPLICATE_REFERENCE` error (HTTP `409 Conflict`). The API does **not** create a second payout, and it does **not** replay or return the original payout. This protects you from sending the same payout twice if a request is retried after a network error or timeout.

Uniqueness is enforced per merchant account and does not expire — a `merchantReference` cannot be reused once it has been accepted, regardless of how much time has passed.

**Safely retrying:** If you don't know whether a request succeeded (e.g. a timeout), retry it with the same `merchantReference`. A `409 Conflict` confirms the original payout was already accepted — look it up via the [history endpoints](#tracking-payouts) rather than resending. Any other error means the payout was not created and is safe to retry.

**Best practice:** Generate a unique, meaningful reference for each payout (e.g., `PAYOUT-2024-001`, `REFUND-ORDER-12345`) and store it alongside the returned transaction ID for reconciliation.

## Best Practices

* Always verify recipient details before initiating payouts
* Use unique, meaningful references for idempotency and easy tracking
* Monitor payout status through the history endpoints or webhooks
* Ensure sufficient balance before initiating payouts
* Handle failed payouts by checking `status`, `message`, and any returned `identifiers` or `paymentAttributes`
* Store payout IDs and references for reconciliation and tracking
* Implement retry logic with exponential backoff for transient failures

For detailed API documentation, see the [Payouts API Reference](/api-reference/payouts/payouts/create-payout).