Single Payouts

Send individual payouts to recipients

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 below.
    • currency: Must be a supported payout currency (NGN, XOF, XAF, GHS, KES, ZAR, AED, EGP, USDT, USDC)
  4. paymentMethodId: "banktransfer", "mobilemoney", or "crypto"
  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 below.
  7. sender (optional): Sender details with KYC fields (required for some destinations)
  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, mobile wallet, or crypto 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.

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 crypto wallets: type: "crypto_wallet", address, network (ERC20 or TRC20), optional memo

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)
  • 5000 minorAmount = 50.00 KES (Kenyan Shillings)
  • 10000 minorAmount = 100.00 EGP (Egyptian Pounds)
  • 1000000 minorAmount = 1.000000 USDT

Important: Fiat currencies use 2 decimal places (multiply by 100). USDT/USDC use 6 decimal places (multiply by 1,000,000).

Request Examples

Bank Account Payout

1{
2 "merchantId": "your-merchant-id",
3 "merchantReference": "PAYOUT-2024-001",
4 "destinationValue": {
5 "minorAmount": 1000000,
6 "currency": "NGN"
7 },
8 "paymentMethodId": "banktransfer",
9 "paymentLocation": "NGA",
10 "recipient": {
11 "type": "bank_account",
12 "accountNumber": "0123456789",
13 "bankCode": "044",
14 "accountHolderName": "John Doe",
15 "country": "NGA"
16 },
17 "attributes": {}
18}

Note: minorAmount: 1000000 = 10,000.00 NGN (multiply by 100 to convert from major to minor units).

Mobile Wallet Payout

1{
2 "merchantId": "your-merchant-id",
3 "merchantReference": "PAYOUT-2024-002",
4 "destinationValue": {
5 "minorAmount": 500000,
6 "currency": "KES"
7 },
8 "paymentMethodId": "mobilemoney",
9 "paymentLocation": "KEN",
10 "recipient": {
11 "type": "mobile_money",
12 "phoneNumber": "254712345678",
13 "country": "KEN",
14 "operator": "mpesa",
15 "name": "Jane Smith"
16 },
17 "attributes": {}
18}

Note: minorAmount: 500000 = 5,000.00 KES.

Crypto Wallet Payout

1{
2 "merchantId": "your-merchant-id",
3 "merchantReference": "PAYOUT-2024-003",
4 "destinationValue": {
5 "minorAmount": 1250000,
6 "currency": "USDT"
7 },
8 "paymentMethodId": "crypto",
9 "paymentLocation": "USA",
10 "recipient": {
11 "type": "crypto_wallet",
12 "address": "0x1111222233334444555566667777888899990000",
13 "network": "ERC20"
14 },
15 "attributes": {}
16}

Note: minorAmount: 1250000 = 1.250000 USDT.

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.

1{
2 "merchantId": "your-merchant-id",
3 "merchantReference": "PAYOUT-2024-004",
4 "destinationValue": {
5 "minorAmount": 5000000,
6 "currency": "UGX"
7 },
8 "paymentMethodId": "mobilemoney",
9 "paymentLocation": "UGA",
10 "payoutBeneficiaryId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
11 "attributes": {}
12}

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 for the full registration and lifecycle.

Response Structure

Successful Response

A successful payout response (HTTP 201) includes:

1{
2 "status": "PENDING",
3 "transactionId": "payout_9f8b7c6d5e4a3b2c1d0e",
4 "message": "Payout transaction initiated successfully",
5 "merchantReference": "PAYOUT-2024-001",
6 "paymentMethodId": "banktransfer",
7 "processorReference": "PROC-123456"
8}

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:

1{
2 "error": {
3 "code": "INSUFFICIENT_BALANCE",
4 "message": "Insufficient balance in payout source account"
5 }
6}

Example error responses:

Insufficient Balance (400):

1{
2 "error": {
3 "code": "INSUFFICIENT_BALANCE",
4 "message": "Insufficient balance in payout source account"
5 }
6}

Invalid Parameters (400):

1{
2 "error": {
3 "code": "INVALID_REQUEST",
4 "message": "Invalid recipient details provided"
5 }
6}

Unauthorized (401):

1{
2 "error": {
3 "code": "UNAUTHORIZED",
4 "message": "Invalid or expired access token"
5 }
6}

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)

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

The merchantReference field enables idempotency. If you send a payout request with a merchantReference that was used in a previous successful request, the API will return the original payout instead of creating a duplicate. This prevents accidental duplicate payouts if a request is retried.

Best practice: Use unique, meaningful references for each payout (e.g., PAYOUT-2024-001, REFUND-ORDER-12345).

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.