Settlements
The batches in which your collected money is paid out to you.
| Endpoint | What it does |
|---|---|
GET /v1/settlements |
List settlements |
GET /v1/settlements/{id} |
Retrieve a settlement |
GET /v1/settlements/{id}/items |
List a settlement’s lines |
GET /v1/withdrawals |
List withdrawals |
Try any of them in the API tester.
List settlements
Section titled “List settlements”GET /v1/settlements
Your settlement batches: one per currency per period, newest period first.
expected_payout_at is the “when do I get paid” answer. It is derived from the period end plus your configured settlement delay, so it is an ESTIMATE and expected_payout_is_estimate says so; paid_at is the fact.
MIND THE WORD pending. A settlement whose status is pending has closed and is awaiting approval in our payout queue. That is NOT the pending on /v1/balances, which means a partner has not yet funded us for your collections. Every settlement carries a status_detail sentence that says which is which.
amounts is the whole composition — gross, platform fees, commissions, refunds, reversals, reserve movements and adjustments — not just a net, so you can reproduce the arithmetic. The database enforces that identity.
A period window is always applied: omitting one defaults to the last 90 days, and a window wider than 400 days is refused rather than silently truncated.
Authentication: a secret key (server-side only) with the scope settlement.read.
Parameters
Section titled “Parameters”| Field | Type | Required | Allowed values and limits | What it is |
|---|---|---|---|---|
limit |
integer | no | min 1; max 100; default 25 |
Rows per page. Clamped to 100. |
offset |
integer | no | min 0 | Rows to skip. |
period_after |
string | no | RFC 3339. Batches whose period ENDS at or after this. Defaults to 90 days ago; the window may not exceed 400 days. | |
period_before |
string | no | RFC 3339. Batches whose period ends before this. Defaults to now. | |
currency |
string | no | e.g. GHS |
One batch exists per currency per period. |
status |
string | no | One of: accruing, pending, approved, processing, paid, failed, on_hold |
Note that pending here means awaiting approval in our payout workflow, NOT the pending on /v1/balances. |
Response 200
Section titled “Response 200”| Field | Type | What it is |
|---|---|---|
data |
array | |
has_more |
boolean | Derived from fetching one row beyond the page, so a full final page does not advertise an empty next one. |
object |
string | |
offset |
integer | |
page_size |
integer | |
window |
object | |
window.created_after |
string (date-time) | |
window.created_before |
string (date-time) |
Errors
Section titled “Errors”401: the key is missing, wrong or revoked403: the key lacks the scope, or your account may not do this422: a field is invalid;errorsnames it429: too many requests; wait forRetry-After500: Internal Server Error503: the payment partner is unreachable; safe to retry
Every error is a JSON problem with a stable code. See Errors.
Retrieve a settlement
Section titled “Retrieve a settlement”GET /v1/settlements/{id}
Adds the payout destination to what the list returns. destination.verified is the most actionable field on a settlement that is not moving: we do not pay out to an account a name enquiry has not confirmed.
A failed settlement reports the status and nothing more — the detailed reason is an internal operations note. Quote the reference to support. A settlement on_hold does carry a short hold_reason; it is prose, not a code.
Authentication: a secret key (server-side only) with the scope settlement.read.
Parameters
Section titled “Parameters”| Field | Type | Required | Allowed values and limits | What it is |
|---|---|---|---|---|
{id} |
string (uuid) | yes | The settlement batch’s id. |
Response 200
Section titled “Response 200”| Field | Type | What it is |
|---|---|---|
amounts |
object | |
amounts.adjustment |
integer | Signed. A negative net from a previous period is carried forward as a negative adjustment here rather than paid as a negative amount. |
amounts.commissions |
integer | Partner or reseller commission, deducted. |
amounts.gross |
integer | Sum of collections settled in the period. |
amounts.net |
integer | What we pay you: gross minus platform_fees minus commissions minus refunds minus reversals minus reserve_held plus reserve_released plus adjustment. The database enforces that identity, so if it does not add up the batch would not have been written. |
amounts.payouts |
integer | Payouts you made from your balance in the period, plus their fees, less any returned. A deduction: that money has already left. |
amounts.platform_fees |
integer | Our fees and taxes, deducted. |
amounts.refunds |
integer | Refunds you issued in the period, deducted. |
amounts.reserve_held |
integer | Moved into a rolling reserve this period, deducted. Mirrors the reserved figure on /v1/balances. |
amounts.reserve_released |
integer | Released from reserve this period, added back. |
amounts.reversals |
integer | Reversals and chargebacks in the period, deducted. |
closed_at |
string (date-time) | When the accrual window closed. Absent while the batch is still accruing. |
created_at |
string (date-time) | |
currency |
string | |
destination |
object | |
destination.account_name |
string | |
destination.type |
string | One of: bank, mobile_money, wallet |
destination.verified |
boolean | False means we have not confirmed this account with the bank or network. We do not pay out to an unverified destination. |
environment |
string | One of: test, live |
expected_payout_at |
string (date-time) | Derived from period_end plus your configured settlement delay. An estimate, not a commitment — read status. |
expected_payout_is_estimate |
boolean | Always true. Use paid_at for what actually happened. |
hold_reason |
string | A short note from our operations team. Prose, not a code — do not parse it. Contact support quoting the reference. |
id |
string | |
object |
string | |
paid_at |
string (date-time) | When we actually sent the money. This is the fact; expected_payout_at was the estimate. |
period |
object | |
period.end |
string (date-time) | |
period.start |
string (date-time) | |
reference |
string | Quote this to support. It also appears on the bank narration where the rail allows one. |
status |
string | One of: accruing, pending, approved, processing, paid, failed, on_hold |
status_detail |
string | |
transaction_count |
integer | Distinct collections in the batch. Fees, refunds and adjustments are lines on /items, not transactions. |
Errors
Section titled “Errors”401: the key is missing, wrong or revoked403: the key lacks the scope, or your account may not do this404: no such resource on this account422: a field is invalid;errorsnames it429: too many requests; wait forRetry-After500: Internal Server Error503: the payment partner is unreachable; safe to retry
Every error is a JSON problem with a stable code. See Errors.
List a settlement’s lines
Section titled “List a settlement’s lines”GET /v1/settlements/{id}/items
The statement, line by line. A disputed settlement is always argued at this level, which is why we store the lines and not just the total.
amount IS SIGNED AS STORED: a fee, a refund and a reversal are negative. We do not normalise them to positive numbers with a type to interpret, because that is how a reconciliation ends up summing to twice the gross.
transaction_date is the date to reconcile against, not the date we wrote the line. Each transaction_id is readable at /v1/transactions/{id}.
Pages are larger here than elsewhere — 100 by default, up to 500 — because walking a month of collections 25 at a time is hundreds of round trips.
Authentication: a secret key (server-side only) with the scope settlement.read.
Parameters
Section titled “Parameters”| Field | Type | Required | Allowed values and limits | What it is |
|---|---|---|---|---|
{id} |
string (uuid) | yes | The settlement batch whose lines to list. | |
limit |
integer | no | min 1; max 500; default 100 |
Rows per page. Clamped to 500 — higher than elsewhere because reconciling a month of collections 25 at a time is hundreds of round trips. |
offset |
integer | no | min 0 | Rows to skip. |
Response 200
Section titled “Response 200”| Field | Type | What it is |
|---|---|---|
data |
array | |
has_more |
boolean | |
object |
string | |
offset |
integer | |
page_size |
integer | |
settlement_id |
string |
Errors
Section titled “Errors”401: the key is missing, wrong or revoked403: the key lacks the scope, or your account may not do this404: no such resource on this account422: a field is invalid;errorsnames it429: too many requests; wait forRetry-After500: Internal Server Error503: the payment partner is unreachable; safe to retry
Every error is a JSON problem with a stable code. See Errors.
List withdrawals
Section titled “List withdrawals”GET /v1/withdrawals
Withdrawals you requested against your available balance, newest first. Distinct from a settlement: a settlement is us paying you on a schedule, a withdrawal is you asking for your available balance now.
amount is what you asked for, fee is deducted from it rather than added, and net is what reaches your account.
Unlike a settlement, a failed withdrawal DOES carry failure_reason: you chose the destination, so “the account number was rejected” is yours to act on.
A date window is always applied: omitting one defaults to the last 90 days, and a window wider than 400 days is refused.
Authentication: a secret key (server-side only) with the scope settlement.read.
Parameters
Section titled “Parameters”| Field | Type | Required | Allowed values and limits | What it is |
|---|---|---|---|---|
limit |
integer | no | min 1; max 100; default 25 |
Rows per page. Clamped to 100. |
offset |
integer | no | min 0 | Rows to skip. |
created_after |
string | no | RFC 3339. Defaults to 90 days ago; the window may not exceed 400 days. | |
created_before |
string | no | RFC 3339. Defaults to now. | |
status |
string | no | One of: pending, approved, processing, paid, failed, cancelled, on_hold |
Only withdrawals in this state. pending: awaiting approval. approved: released for sending. processing: being sent. paid: sent to your account. failed: the transfer failed; see failure_reason. cancelled: called off before sending. on_hold: frozen, for example by a dispute or a review. |
Response 200
Section titled “Response 200”| Field | Type | What it is |
|---|---|---|
data |
array | |
has_more |
boolean | |
object |
string | |
offset |
integer | |
page_size |
integer |
Errors
Section titled “Errors”401: the key is missing, wrong or revoked403: the key lacks the scope, or your account may not do this422: a field is invalid;errorsnames it429: too many requests; wait forRetry-After500: Internal Server Error503: the payment partner is unreachable; safe to retry
Every error is a JSON problem with a stable code. See Errors.

