Bulk payouts: paying salaries and commissions by mobile money
Field agents, riders, commission-based sellers, contractors: many African teams are paid on mobile money. Here is how to run reliable bulk payouts, with no double payment and no one left out.
In many African businesses, month end is not a single bulk transfer at the bank, but dozens or hundreds of mobile money transfers: field agents, riders, commission-based sellers, contractors, partners. Done by hand from a phone, these payments take hours, and a single typo is enough to send money to the wrong number.
This guide describes a reliable method to pay salaries, bonuses and commissions by mobile money or bank transfer, at scale, with no double payment and no one left out.
Why pay your teams by mobile money
For a large share of workers, the mobile money wallet is the everyday account: it is where they get paid, save and spend. Paying straight into that wallet has several advantages:
- Money arrives fast, usually instantly, including evenings and weekends.
- The recipient receives the full amount: at Monerails, the fee is debited on your side, on top of the amount.
- Every payout leaves a record, with a reference, a status and a proof of payment.
- It works across borders: the same method pays a rider in Douala, a seller in Abidjan and an agent in Nairobi, each in their own currency.
Prepare clean data
Most payout incidents come from the data, not the technology. Before the first payout, build a reliable recipient file:
| Field | Why it matters |
|---|---|
| Full name | It goes with every payout and is used in checks. Use the name as it appears on the recipient’s account. |
| Number in international format | Country code included (237…, 225…, 254…), so the country is never ambiguous. |
| Operator | The recipient’s actual wallet, which is not always the operator of their phone line. |
| Country and currency | Essential for shared currencies: XOF covers eight countries, XAF six. |
| Amount and reference | One unique reference per payout, for example payroll-2026-11-AG042. |
Have each recipient confirm their number and operator when they join, and again whenever it changes. For recipients paid into a bank account, Monerails supports local bank transfers in twelve countries, including Cameroon, Côte d’Ivoire, Senegal, Nigeria and Kenya.
Bulk payouts through the API
With the Monerails API, a bulk payout is a loop: one call per recipient, each with its own idempotency key. The Node.js example below walks through a list and sends each payout.
for (const p of recipients) {
await fetch('https://api.monerails.com/v1/payouts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MONERAIL_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': `payroll-2026-11-${p.employeeId}`,
},
body: JSON.stringify({
amount: p.amount, // 85000 = 85,000 CFA francs
currency: p.currency, // 'XAF', 'XOF', 'KES'…
country: p.country, // 'CI' for Côte d'Ivoire
recipient: { type: 'mobile_money', name: p.name,
phone: p.phone, operator: p.operator },
client_reference: `payroll-2026-11-${p.employeeId}`,
}),
});
}
Three points separate a script that works from a script you can trust:
- A stable idempotency key per payout. Built from the period and the recipient’s ID, it lets you rerun the whole script after an interruption without ever paying the same person twice.
- Respect for rate limits. On a
429response, wait for the delay given in theRetry-Afterheader before resuming. - No new creation after a
202. That response means the payout is on its way: wait for the webhook.
What happens to your balance
When each payout is created, Monerails reserves the amount and the fee on your balance in that currency. If the balance does not cover both, the request is refused (402 balance_insufficient) and nothing is sent. Check your balance before starting a batch, taking into account the fees published on the pricing page.
If a payout fails, for example to a number that does not exist, the amount and the fee return to your balance automatically, with the reason for the failure. You fix the line and resend that single payout, with a new key.
Track every payout
A payout moves through pending and processing, then becomes succeeded or failed. Subscribe to the payout.succeeded and payout.failed webhooks to update your payroll software as you go, without polling the API.
Thanks to client_reference, every event carries your own reference, so reconciling with your payroll file happens line by line. At the end, compare three totals: payouts planned, succeeded and failed. Until they add up, the batch is not closed.
Example: commissions for a sales network
Take a distribution company that pays 180 commission-based sellers in Cameroon and Côte d’Ivoire. Every month end, its management software calculates each seller’s commission from recorded sales.
- The software exports the list: seller ID, name, number, operator, country, amount.
- Finance checks both balances, XAF and XOF, fees included, and approves the total.
- The payout script walks through the list, with a
commission-2026-11-<id>key per seller. - Webhooks update each line: paid, or failed with its reason.
- The few failures, often a changed number, are fixed with the seller and resent the same day.
The next day, every seller has their commission in their wallet, and the company has a complete record: who was paid, when, with which reference. If a payment is disputed, proof of payment is available for every payout.
Internal controls and security
Payouts are the most sensitive operation on an account. Organise them accordingly:
- Separate roles. At Monerails, the Owner, Finance, Approver and Developer roles decide who can pay out, settle or issue cards. API keys that can pay out must be created by an Owner, Finance or Approver member.
- Keep the live key out of your code, in a secret manager, with only the role it needs.
- Test first. Replay your full batch in test mode: payouts go through the whole flow without moving real money.
- Start small. For a new recipient, a modest first payout confirms the number before larger amounts.
Every payout is also screened against sanctions lists before it leaves.
And without a developer?
From the dashboard, you can already send payouts one at a time, to a wallet or a bank account, and see the fee before you confirm. CSV file import, checked line by line and submitted for approval before sending, is coming soon: it will let you launch an entire batch from a spreadsheet, with a report and a webhook for every payout.
Whichever route you choose, the principles stay the same: clean data, a unique reference per payout, a balance that covers amounts and fees, and a reconciliation at the end. The dashboard and the API share the same balances, so payouts sent either way appear side by side in your transactions.
The payday checklist
- Recipient file up to date: name, number, operator, country.
- Enough balance in each currency, fees included.
- A unique reference and idempotency key per payout.
payout.succeededandpayout.failedwebhooks active.- Final reconciliation: planned = succeeded + failed, failures fixed and resent.
To go further, the mobile money API guide covers webhooks and idempotency in detail, and our article on mobile money in Cameroon, Côte d’Ivoire and Senegal lists each country’s number formats. The technical details are in the payouts guide, and the offer on the payouts page.
Ready to collect, pay out and issue cards?
Open an account in minutes. The sandbox is free, with no subscription.