Bulk Payouts API
The Bulk Payouts API lets you upload hundreds of payout instructions at once as either a CSV file or a JSON array. Settlra processes each row asynchronously and fires per-payout webhook events as they settle. Use the batch endpoints to monitor overall progress.
/v1/batchesCreate a batch (CSV or JSON)/v1/batches/:idGet batch status/v1/batches/:id/payoutsList payouts in a batchCreate a batch
/v1/batchesUploads a batch of payout instructions. Accepts either a multipart CSV file upload or a JSON array body. Settlra validates every row before enqueuing — if any row is invalid the entire batch is rejected with a validation error listing the offending rows.
CSV format
When uploading a CSV, set the Content-Type to multipart/form-data and include the file under the file field. The first row must be the header row with the exact column names shown below.
phone,network,amount_usdc,name,idempotency_key +256700123456,mtn_uganda,25.00,Grace Nakamura,order_001 +256701234567,airtel_uganda,10.50,David Opio,order_002
CSV column reference
| Column | Required | Description |
|---|---|---|
phone | Yes | Recipient phone number in E.164 format. |
network | Yes | Mobile money network slug. See Supported Networks. |
amount_usdc | Yes | USDC amount to send, up to 6 decimal places. |
name | No | Recipient full name (used for provider validation where required). |
idempotency_key | Yes | Unique key per row for deduplication. Max 128 chars. |
JSON body format
Alternatively, POST a JSON array of payout objects. Set Content-Type: application/json.
{
"payouts": [
{
"phone": "+256700123456",
"network": "mtn_uganda",
"amount_usdc": 25.00,
"name": "Grace Nakamura",
"idempotency_key": "order_001"
},
{
"phone": "+256701234567",
"network": "airtel_uganda",
"amount_usdc": 10.50,
"name": "David Opio",
"idempotency_key": "order_002"
}
]
}cURL — CSV upload
"color:#ff7b72">curl "color:#79c0ff">-X POST https://api-sandbox.settlra.com/v1/batches \ "color:#79c0ff">-H "Authorization: Bearer pk_test_your_key" \ -F "file=@payouts.csv"
cURL — JSON upload
"color:#ff7b72">curl "color:#79c0ff">-X POST https://api-sandbox.settlra.com/v1/batches \ "color:#79c0ff">-H "Authorization: Bearer pk_test_your_key" \ "color:#79c0ff">-H "Content-Type: application/json" \ "color:#79c0ff">-d '{ "payouts": [ { "phone": "+256700123456", "network": "mtn_uganda", "amount_usdc": 25.00, "name": "Grace Nakamura", "idempotency_key": "order_001" } ] }'
Node.js — CSV upload
"color:#ff7b72">import Settlra "color:#ff7b72">from '@settlra/node'; "color:#ff7b72">import fs "color:#ff7b72">from 'fs'; "color:#ff7b72">const client = "color:#ff7b72">new Settlra({ apiKey: process.env.SETTLRA_API_KEY }); "color:#ff7b72">const batch = "color:#ff7b72">await client.batches.createFromFile( fs.createReadStream('./payouts.csv'), { contentType: 'text/csv' } ); console.log(batch.id); "color:#8b949e">// "batch_01HXYZ" console.log(batch.total); "color:#8b949e">// 150
Response
| Field | Type | Description |
|---|---|---|
id | string | Unique batch identifier. |
status | string | Batch status. See status values below. |
total | number | Total number of payouts in the batch. |
completed | number | Payouts that have reached a terminal success state. |
failed | number | Payouts that reached a terminal failure state. |
pending | number | Payouts still in progress. |
created_at | string | ISO 8601 creation timestamp. |
{
"id": "batch_01HXYZ",
"status": "processing",
"total": 150,
"completed": 87,
"failed": 3,
"pending": 60,
"created_at": "2025-06-23T14:22:01Z"
}Batch status values
| Status | Description |
|---|---|
queued | Batch accepted and waiting to begin processing. |
processing | At least one payout is actively being processed. |
completed | All payouts reached a terminal state (success or failure). |
cancelled | Batch was cancelled before all payouts were processed. |
Get batch status
/v1/batches/:idReturns the current status and progress counters for a batch.
"color:#ff7b72">curl https://api-sandbox.settlra.com/v1/batches/batch_01HXYZ \ "color:#79c0ff">-H "Authorization: Bearer pk_test_your_key"
"color:#ff7b72">const batch = "color:#ff7b72">await client.batches.retrieve('batch_01HXYZ'); console.log(`${batch.completed}/${batch.total} payouts completed`); "color:#8b949e">// "87/150 payouts completed"
{
"id": "batch_01HXYZ",
"status": "processing",
"total": 150,
"completed": 87,
"failed": 3,
"pending": 60,
"created_at": "2025-06-23T14:22:01Z"
}List payouts in a batch
/v1/batches/:id/payoutsReturns a paginated list of individual payouts that belong to a batch. Filter by status to quickly surface failed rows for retry or reporting.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
status | string | — | Filter by payout status (e.g. FAILED). |
limit | number | 20 | Number of results per page (1–100). |
offset | number | 0 | Pagination offset. |
"color:#8b949e"># List all failed payouts in a batch "color:#ff7b72">curl "https://api-sandbox.settlra.com/v1/batches/batch_01HXYZ/payouts?status=FAILED" \ "color:#79c0ff">-H "Authorization: Bearer pk_test_your_key"
"color:#ff7b72">const { data } = "color:#ff7b72">await client.batches.listPayouts('batch_01HXYZ', { status: 'FAILED', }); "color:#8b949e">// Inspect and retry each failed payout "color:#ff7b72">for ("color:#ff7b72">const payout of data) { console.log(payout.payout_id, payout.failure_reason); }
{
"data": [
{
"payout_id": "pyt_01HABC123",
"idempotency_key": "order_001",
"status": "SETTLED",
"recipient_phone": "+256700123456",
"amount_usdc": 25.00,
"network": "mtn_uganda"
},
{
"payout_id": "pyt_01HABC124",
"idempotency_key": "order_002",
"status": "FAILED",
"recipient_phone": "+256701234567",
"amount_usdc": 10.50,
"network": "airtel_uganda",
"failure_reason": "invalid_recipient"
}
],
"total": 150,
"limit": 20,
"offset": 0
}