> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.crisscross.money/payout-single/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). > Send individual payouts to recipients