Payout batches
Send up to 100 payouts in one request.
A batch sends many payouts in one call. Each item is an ordinary payout. It is accepted or refused on its own, so one refusal does not stop the others.
Send a batch
POST /v1/payout-batches
Idempotency-Key: payroll-2026-10
{
"reference": "payroll-2026-10",
"items": [
{
"reference": "payroll-2026-10-001",
"amount": "450.00",
"currency": "GHS",
"provider": "mtn",
"destination": { "type": "msisdn", "value": "233244123456" }
},
{
"reference": "payroll-2026-10-002",
"amount": "380.00",
"currency": "GHS",
"provider": "telecel",
"destination": { "type": "msisdn", "value": "233201234567" }
}
]
}
referenceis yours, and unique for each batch.itemsholds 1 to 100 payouts. Each has the same fields asPOST /v1/payouts.- Each item’s
referencemust be unique within the batch, and is the payout’s own reference.
What comes back
If the batch itself is malformed, the whole batch is refused with 400 invalid_input and nothing is sent. That covers a missing reference, no items, more than 100 items, an invalid item, or a reference used twice in the batch. message names the item.
Otherwise you get 200, with one entry per item in the order you sent them:
{
"batchId": "b2f1c7e4-5a1d-4c3e-9f0a-7d6b2e8c1a90",
"reference": "payroll-2026-10",
"items": [
{
"reference": "payroll-2026-10-001",
"status": 202,
"payout": {
"reference": "payroll-2026-10-001",
"amount": "450.00",
"currency": "GHS",
"status": "accepted",
"provider": "mtn",
"createdAt": "2026-10-05T09:00:00Z"
}
},
{
"reference": "payroll-2026-10-002",
"status": 403,
"error": {
"code": "daily_limit_exceeded",
"message": "daily limit exceeded"
}
}
]
}
The values above only show the shape.
statusis202when the payout was accepted. It then carries thepayout.- Any other
statusis the one a single payout would have been refused with.errorhas the same code, such asdaily_limit_exceeded.
A 200 does not mean every payout went out. Check each item.
Limits
Your limits apply to each item as if it were sent alone. A batch cannot move more than the same payouts sent one by one. Check GET /v1/limits before a large batch.
Retrying
After a timeout or a 5xx, retry with the same Idempotency-Key and the same body. Accepted items are not sent again.
Following the payouts
There is no batch read. Read each payout with GET /v1/payouts/{reference}. Webhooks arrive for each payout (payout.accepted, payout.status_changed), not for the batch. See Webhooks.
Permissions
| To | The key needs |
|---|---|
| Send a batch | disbursements.write |
| Read a payout | disbursements.read |
Errors
As well as the common errors:
| Status | Code | What to do |
|---|---|---|
| 400 | invalid_input |
The batch is malformed and nothing was sent. Fix the item message names and send again. |
| 409 | idempotency_key_reused |
This key was used with a different body. Send the original body, or use a new key for a new batch. |
| 409 | request_in_flight |
The first request with this key is still running. Wait, then retry the same request. |