Balances API
Last updated: 2026-07-17
Balance operations use a secret key (sk_*). All monetary values are minor-unit
integers encoded as JSON strings.
List balances
GET /merchant/api/v2/balances
Auth: Secret key
The response contains one entry per merchant balance position.
curl "https://merchants-api.example.com/merchant/api/v2/balances" \
-H "Authorization: Bearer sk_test_..."
Example response:
{
"balances": [
{
"currencyCode": "GHS",
"countryCode": "GH",
"availableMinor": "125000",
"pendingMinor": "18000",
"pendingInMinor": "15000",
"pendingOutMinor": "3000",
"holdMinor": "2000",
"currentMinor": "145000",
"payoutAvailableMinor": "100000",
"version": 42
}
]
}
The OpenAPI schema does not mark response properties as required. Clients must therefore tolerate omitted properties and should apply defaults only where their integration contract defines them.
Position identity and market scope
A position is scoped by currencyCode and, when populated, countryCode.
Do not merge rows only because they share a currency. Use the market country
from the payment flow to select a country-scoped row, and treat an empty-country
row as a separate unscoped position.
Position fields
| Response field | JSON type | Detailed meaning |
|---|---|---|
balances[].currencyCode | string | Currency of the position; use it together with country scope |
balances[].countryCode | string | Market country when the position is country-scoped; it can be empty for an unscoped position |
balances[].availableMinor | string (int64) | Value in the available bucket; do not substitute it for payout availability |
balances[].pendingMinor | string (int64) | Combined pending amount: pendingInMinor + pendingOutMinor |
balances[].pendingInMinor | string (int64) | Value currently pending inbound |
balances[].pendingOutMinor | string (int64) | Value currently pending outbound |
balances[].holdMinor | string (int64) | Value currently in the hold bucket |
balances[].currentMinor | string (int64) | Aggregate position: availableMinor + pendingMinor + holdMinor |
balances[].payoutAvailableMinor | string (int64) | Value currently exposed for an advisory payout pre-check |
balances[].version | integer (int32) | Opaque version of this position snapshot; do not calculate or increment it client-side |
All amount fields are minor-unit integer strings, not decimal major-unit amounts. Keep them as lossless integers while comparing or adding values, then apply the currency exponent only for display.
Use payoutAvailableMinor, not availableMinor, for a payout pre-check. The
value can change before the payout request and does not reserve funds.
Get balance history
GET /merchant/api/v2/balances/history
Auth: Secret key
Example request for the first page of one market position:
curl -G "https://merchants-api.example.com/merchant/api/v2/balances/history" \
-H "Authorization: Bearer sk_test_..." \
--data-urlencode "currencyCode=GHS" \
--data-urlencode "countryCode=GH" \
--data-urlencode "limit=50" \
--data-urlencode "offset=0"
| Query parameter | Type | Presence | Meaning |
|---|---|---|---|
limit | integer | Optional | Page size; defaults to 50 and is capped at 200 |
offset | integer | Optional | Zero-based result offset |
currencyCode | string | Optional | Filter by currency |
countryCode | string | Optional | Filter by market country |
sourceType | string | Optional | Exact filter by movement source type; treat values as forward-compatible strings |
sourceId | string | Optional | Exact filter by movement source identifier |
Filters are combined. An omitted filter does not constrain that field. Results are ordered newest first by creation time, with a stable identifier tie-break.
Each movements[] entry contains:
| Field | JSON type | Meaning |
|---|---|---|
id | string | Movement identifier |
operationId | string | Balance operation identifier used to correlate movements from one operation |
currencyCode | string | Movement currency |
countryCode | string | Market country when country-scoped |
bucket | string | Balance bucket changed by the movement; current values include available, pending_in, pending_out, and hold |
direction | string | Movement direction; current values are CREDIT and DEBIT |
amountMinor | string (int64) | Movement amount in minor units |
balanceBeforeMinor | string (int64), optional | Recorded bucket value before the movement; omitted when no before-value is available |
balanceAfterMinor | string (int64), optional | Recorded bucket value after the movement; omitted when no after-value is available |
sourceType | string | Forward-compatible source category |
sourceId | string | Source identifier when the movement has one |
sourceReference | string | Merchant-visible source reference when available |
description | string | Merchant-visible movement description when available |
createdAt | string (date-time) | Movement timestamp |
The response also contains page.limit, page.offset, and page.totalPages.
limit defaults to 50, is capped at 200, and offset is zero-based. Keep
requesting pages while the page metadata indicates more results.
The current bucket and direction values above are useful for presentation, but
clients must still tolerate unknown future string values. Use sourceType and
sourceId as filters only with values already observed or supplied by the
integration context; do not hard-code an exhaustive public enum.
Related guide: Balances.