Payouts
Payouts allow you to send funds from your Maraboo wallet to recipients across multiple countries and payment channels. This guide covers everything you need to know about creating and managing outbound payments.
Overview
Maraboo supports two types of outbound payments:
- Payment Transactions: Send funds to third-party recipients (individuals, businesses)
- Withdrawal Transactions: Transfer funds to your own pre-configured accounts
Payment Transactions
When to Use
- Paying suppliers or vendors
- Sending money to individuals
- Disbursing funds to beneficiaries
- Processing payroll
Supported Payout Channels
West Africa (WAEMU) - XOF
mobile_money: MTN, Moov, Orange Money mobile money transfersdirect_deposit: Direct deposits to bank accountsxpresscash: Cash pickup at partner locationscredit_ecobank_account: Direct credits to Ecobank accountsbillpay: Bill payment services
Countries: Benin (BJ), Burkina Faso (BF), Côte d'Ivoire (CI), Guinea-Bissau (GW), Mali (ML), Niger (NE), Senegal (SN), Togo (TG)
Canada - CAD
interac_send: Real-time Interac Send transferseft: Electronic Funds Transfer to bank accountsbillpay: Bill payment processing
United States - USD (Coming Soon)
swift: SWIFT international transfersfednow: FedNow instant paymentsbank_transfer_ach: ACH bank transfers
Creating a Payout
Step 1: Prepare Recipient Information
You can either use a pre-created recipient or provide recipient details inline.
Option A: Pre-create Recipients
const response = await fetch('https://sandbox.mara.boo/api-access/recipients', {
method: 'POST',
headers: {
'Authorization': 'HMAC-SHA256 YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY',
'X-Origin': 'third-party-api',
'X-Timestamp': new Date().toISOString(),
'Content-Type': 'application/json'
},
body: JSON.stringify({
first_name: 'John',
last_name: 'Doe',
email: 'john.doe@example.com',
phone: '+22997123456',
country: 'bj',
transaction_type: 'mobile_money',
recipient_type: 'individual',
provider: 'mtn',
currency: 'xof'
})
});
const recipient = await response.json();
const recipient_id = recipient.data.id;Option B: Inline Recipients
Provide recipient details directly in the payment request (useful for one-time payments).
Step 2: Get Payment Quote
Always get a quote before creating the payment to know the exact fees and exchange rates.
const quoteResponse = await fetch('https://sandbox.mara.boo/api-access/calculators/payment', {
method: 'POST',
headers: {
'Authorization': 'HMAC-SHA256 YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY',
'X-Origin': 'third-party-api',
'X-Timestamp': new Date().toISOString(),
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: 50000,
country: 'bj',
channel: 'mobile_money',
currency: 'xof'
})
});
const quote = await quoteResponse.json();
const quote_id = quote.data.quote_id;Step 3: Create Payment Transaction
const paymentResponse = await fetch('https://sandbox.mara.boo/api-access/transactions/client/sessions/payment', {
method: 'POST',
headers: {
'Authorization': 'HMAC-SHA256 YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY',
'X-Origin': 'third-party-api',
'X-Timestamp': new Date().toISOString(),
'X-Idempotency-Key': `payment-${Date.now()}-${quote_id}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
description: 'Supplier payment',
quote_id: quote_id,
wallet_id: 'wallet-456',
transaction: {
amount: 50000,
country: 'bj',
channel: 'mobile_money',
currency: 'xof'
},
recipient: {
first_name: 'John',
last_name: 'Doe',
email: 'john.doe@example.com',
phone: '+22997123456',
country: 'bj',
transaction_type: 'mobile_money',
recipient_type: 'individual',
provider: 'mtn',
currency: 'xof'
},
metadata: {
invoice_id: 'INV-12345',
payment_purpose: 'goods'
}
})
});
const payment = await paymentResponse.json();
console.log('Transaction ID:', payment.data.transaction_id);
console.log('Session ID:', payment.data.session_id);Withdrawal Transactions
Withdrawals are used to transfer funds from your Maraboo wallet to your own bank accounts.
Key Differences from Payments
| Feature | Payments | Withdrawals |
|---|---|---|
| Recipient | Third-party recipients | Your own accounts |
| Account Setup | Inline or pre-created | Pre-configured in portal |
| Use Case | Pay others | Move your funds |
Creating a Withdrawal
const withdrawalResponse = await fetch('https://sandbox.mara.boo/api-access/transactions/client/sessions/withdrawal', {
method: 'POST',
headers: {
'Authorization': 'HMAC-SHA256 YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY',
'X-Origin': 'third-party-api',
'X-Timestamp': new Date().toISOString(),
'X-Idempotency-Key': `withdrawal-${Date.now()}-${quote_id}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
description: 'Withdrawal to bank account',
destination_account_id: 'account-123', // Pre-configured account
quote_id: 'quote-789',
transaction: {
amount: 10000,
country: 'ca',
channel: 'eft',
currency: 'cad'
},
wallet_id: 'wallet-456'
})
});
const withdrawal = await withdrawalResponse.json();Recipient Types & Requirements
Different recipient types require different fields. Here are the common patterns:
Mobile Money Recipient
Required Fields:
first_name,last_namephone: Mobile money numbercountry: Country codetransaction_type:mobile_moneyprovider:mtn,moov,orange, etc.currency: Payout currency
{
"first_name": "John",
"last_name": "Doe",
"phone": "+22997123456",
"country": "bj",
"transaction_type": "mobile_money",
"recipient_type": "individual",
"provider": "mtn",
"currency": "xof"
}Bank Transfer Recipient (EFT)
Required Fields (Canada - EFT):
first_name,last_nameemailcountry:catransaction_type:eftaccount_number: Bank account numberinstitution_number: Bank institution codetransit_number: Branch transit numbercurrency:cad
{
"first_name": "Jane",
"last_name": "Smith",
"email": "jane@example.com",
"country": "ca",
"transaction_type": "eft",
"account_number": "1234567",
"institution_number": "001",
"transit_number": "12345",
"currency": "cad"
}Direct Deposit Recipient (XOF)
Required Fields (WAEMU - Direct Deposit):
first_name,last_nameemailorphonecountry: WAEMU country codetransaction_type:direct_depositaccount_number: Bank account numberbank_code: Bank identifiercurrency:xof
{
"first_name": "Amadou",
"last_name": "Diallo",
"phone": "+22997123456",
"country": "sn",
"transaction_type": "direct_deposit",
"account_number": "SN12345678901234567890",
"bank_code": "SN001",
"currency": "xof"
}Interac Send Recipient
Required Fields:
first_name,last_nameemailorphonecountry:catransaction_type:interac_send
{
"first_name": "Bob",
"last_name": "Johnson",
"email": "bob@example.com",
"country": "ca",
"transaction_type": "interac_send",
"currency": "cad"
}View all recipient requirements →
Tracking Payout Status
Get Specific Transaction
const sessionId = 'session-123';
const response = await fetch(`https://sandbox.mara.boo/api-access/transactions/client/sessions/${sessionId}`, {
method: 'GET',
headers: {
'Authorization': 'HMAC-SHA256 YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY',
'X-Origin': 'third-party-api',
'X-Timestamp': new Date().toISOString(),
'Content-Type': 'application/json'
}
});
const transaction = await response.json();
console.log('Status:', transaction.data.status);
console.log('Amount:', transaction.data.amount);
console.log('Recipient:', transaction.data.recipient);List Transactions with Filters
const response = await fetch('https://sandbox.mara.boo/api-access/transactions/client/sessions?status=completed&limit=20', {
method: 'GET',
headers: {
'Authorization': 'HMAC-SHA256 YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY',
'X-Origin': 'third-party-api',
'X-Timestamp': new Date().toISOString(),
'Content-Type': 'application/json'
}
});
const transactions = await response.json();Available Filters:
status:pending,processing,completed,failedstart_date/end_date: Date rangerecipient_id: Filter by recipientcurrency: Filter by currencywallet: Filter by wallet ID
Handling Payout Failures
Common Failure Reasons
| Failure Reason | Description | Solution |
|---|---|---|
insufficient_funds | Wallet balance too low | Fund wallet before retrying |
invalid_recipient | Recipient details incorrect | Validate recipient information |
provider_error | Payment provider issue | Retry after some time |
blocked_recipient | Recipient on blocklist | Contact support |
limit_exceeded | Transaction limit reached | Wait for limit reset or contact support |
Retry Strategy
- Check Failure Reason: Review
failure_reasonfield in transaction response - Fix Issues: Address the root cause (e.g., fund wallet, correct recipient details)
- Use Idempotency: Use
Idempotency-Keyheader to prevent duplicates - Exponential Backoff: Wait longer between retries (1s, 2s, 4s, 8s, etc.)
Webhook Notifications
Instead of polling for status updates, configure webhooks to receive real-time notifications:
{
"event": "transaction.completed",
"data": {
"session_id": "session-123",
"transaction_id": "txn-456",
"status": "completed",
"amount": 50000,
"currency": "xof",
"recipient": {
"name": "John Doe",
"phone": "+22997123456"
},
"timestamp": "2025-10-12T14:30:00.000Z"
}
}Fees
Transaction fees vary by:
- Payment channel
- Destination country
- Transaction amount
- Currency
Use the calculator endpoints to get accurate fee quotes before creating transactions.
Testing Payouts
Sandbox Environment
Use the sandbox environment to test payouts without moving real funds:
Base URL: https://sandbox.mara.booTest Scenarios
- Successful Payout: Use valid test recipient details
- Insufficient Funds: Attempt payout with empty wallet
- Invalid Recipient: Use incorrect phone/account numbers
- Provider Failure: Test provider error handling