Payouts
Disburse to many destinations in one batch. Submitted async (202), executed item-by-item, partial-failure tolerant: one bad item never sinks the batch. completed, partially_completed, or failed.
A payout is a batch of disbursements: one call, many destinations, executed item-by-item. It's how you pay out a marketplace's sellers, a payroll run, a round of creator earnings, without firing N separate calls and hand-rolling your own retry loop. Acute runs the batch asynchronously and, crucially, is partial-failure tolerant: one item bouncing doesn't fail the other ninety-nine.
Submit the whole batch at once:
# batch payout
curl -X POST https://sandbox.api.acute.network/v1/payouts \
-H "Authorization: Bearer acuinf_test_..." \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "destinationWalletId": "acuinf830192847561wlt", "amount": 500000, "reference": "seller-1" },
{ "destinationWalletId": "acuinf771204938651wlt", "amount": 300000, "reference": "seller-2" }
]
}'The call returns 202 Accepted, not 201. The batch is validated (funds checked,
every destination must be tier1) and enqueued; the items run on a worker. You get the
payout back as processing immediately, with every item pending.
{
"success": true,
"statusCode": 202,
"data": {
"id": "acuinf093817264550pyo",
"sourceWalletId": "acuinf601928374651wlt",
"totalAmount": 800000,
"totalFee": 12000,
"itemCount": 2,
"status": "processing",
"items": [
{
"id": "acuinf093817264551poi",
"amount": 500000,
"fee": 7000,
"status": "pending",
"counterparty": { "accountNumber": "0123456789", "accountName": "Ada Lovelace", "bankCode": "000013" },
"failureReason": null
},
{
"id": "acuinf093817264552poi",
"amount": 300000,
"fee": 5000,
"status": "pending",
"counterparty": { "accountNumber": "0987654321", "accountName": "Grace Hopper", "bankCode": "000014" },
"failureReason": null
}
],
"currency": "NGN",
"createdAt": "2026-06-26T12:00:00.000Z"
}
}202, not 201
Payout creation is the one money endpoint that returns 202 Accepted, because the work
is genuinely asynchronous: the batch hasn't run yet. Don't read item statuses off the
create response and call it done; they're all pending there. Poll GET /payouts/:id or,
better, wait for the payout.completed / payout.partially_completed webhook.
Every payout item disburses on the bank rail: same posting and same non-lossy resolver as
a withdrawal. When the worker executes an item, it posts the hold,
fires the NIP, and lets the resolver confirm. The fee per item is the withdrawal clamp
(clamp(₦5, 1%, ₦180)) plus the flat ₦20.00 NIP charge from the provider.
One payout item executes
₦5,000.00 to a seller · ₦50.00 Acute fee · ₦20.00 flat provider fee
- DRsource debited item amount + both fees
- CRprincipal + provider fee parked for NIP
- CRAcute fee remitted
A failed item is reversed exactly like a returned withdrawal: a reversing ledger
transaction re-credits the source wallet. The batch's successCount / failureCount move
accordingly, and one item's failure leaves every other item untouched.
A payout's status is a rollup of its items. While any item is still pending or
processing, the batch is processing. Once they've all resolved, the batch lands on one
of three terminals.
processingentry statusThe batch is running. At least one item is still pending or processing; the rollup stays here until every item resolves.
Transitions out
processingcompletedAll items resolve to completed
fires
payout.completedprocessingpartially_completedItems resolve to a mix of completed and failed
fires
payout.partially_completedprocessingfailedAll items resolve to failed (every hold reversed)
The rollup rule, exactly:
- any item still
pending/processing→ batchprocessing - all items
completed→ batchcompleted→payout.completed - all items
failed→ batchfailed - otherwise (a mix) → batch
partially_completed→payout.partially_completed
Each item has its own status (pending, processing, completed, or failed), so
when a batch comes back partially_completed, you read the items[] to see which seller
didn't get paid and why (failureReason).
partially_completed is a success-ish status, so read the items
partially_completed means the batch finished and some money moved. It is not an error
you can ignore: the failed items were reversed to your source wallet, but the intended
recipients didn't get paid. Inspect items[], surface the failures, and re-pay the
failed ones (a fresh payout, fresh Idempotency-Key).
{
"id": "acuinf774012398561evt",
"type": "payout.partially_completed",
"createdAt": "2026-06-26T12:03:20.000Z",
"data": {
"id": "acuinf093817264550pyo",
"status": "partially_completed",
"totalAmount": 800000,
"itemCount": 2
}
}- Source defaults to settlement. Omit
sourceWalletIdand the batch draws from your org's settlement wallet. Point it at anytier1wallet you control. - Funds checked up front. The batch validates that the source can cover the total (amounts + fees) before enqueueing. Insufficient funds → the create call fails; nothing runs half-paid.
- Every destination must be
tier1. AkycStatus: nonedestination fails validation: fix KYC before the batch, not after. Idempotency-Keyrequired. Resubmitting the same batch with the same key returns the same payout: you won't double-disburse a payroll because a request timed out.