Balance & settlements
What you hold, what you can send today, and when the rest becomes available.
Wajub does not hold your money. Collections are settled by a licensed payment partner who holds the funds on your behalf, and the balance is that position read through the API.
One number on it can pay someone: available. Everything else is money you have but cannot spend
yet, and most of the questions merchants ask about payouts are really questions about the gap
between the two.
One call
https://api.wajub.com/balanceThe secret key is required. A public key answers 406 Private Key Required, like every other payout
route. There are no other balance endpoints: no history, no per-wallet read, no adjustment.
curl https://api.wajub.com/balance \
-H "Authorization: sk.xxxxxxxxxxxxxxxx…"The live response carries ten fields. Seven describe your money, and three are there for reasons that have nothing to do with it.
These seven are the ones to read. The first five answer different questions about the same money, and the last two say how it is being expressed.
totalnumberoptionalavailable plus pending plus reserved plus disputed.availablenumberoptionalpendingnumberoptionalreservednumberoptionaldisputednumberoptionalavailable when a dispute opens. It returns to available if you win, and leaves if you lose.currencystringoptionalenvironmentstringoptionallive or sandbox.The three missing from that table are missing on purpose.
Three fields are always zero
in.transit, hold and credit are in the response and are always zero: they are reserved for
future use. Do not build a display on them, and do not subtract them from anything. Note the dot
in in.transit: it is a key containing a period, so balance.in.transit resolves to nothing in
every language. Read it as balance["in.transit"] if you read it at all.
Amounts are in the major unit, the same convention as a transfer. 1250000 in XAF is one million
two hundred fifty thousand francs, not twelve thousand five hundred.
It is not one wallet, it is all of them
Wajub keeps one wallet per currency. GET /balance does not return one of them: it reads every
wallet you hold, converts each into a single currency, and adds them up.
So currency is a unit of presentation, not a selection. Passing ?currency=XOF does not show you
your XOF wallet, it shows you everything you own expressed in XOF. The underlying money does not
move and no wallet is excluded.
curl "https://api.wajub.com/balance?currency=USD" \
-H "Authorization: sk.xxxxxxxxxxxxxxxx…"Only cURL is shown because the SDKs take no argument here: balance.retrieve() has no parameters in
any of them. Leave the query out and you get the currency set on your account, which is XAF until
someone changes it, whatever country you operate from.
The conversion is indicative
Rates come from Wajub's own currency table, refreshed periodically, and they are not a dealt FX price. Send only a currency code Wajub supports: an unknown code is not refused. Use the conversion to read a number, never to settle an account.
Why available is smaller than total
A collection does not land as spendable money. It is credited to pending and held there for a
fixed window before it moves, which is what protects the platform against a payment that gets
contested after you have already withdrawn it.
The window is computed per payment, from the channel it came in on.
| Channel | Base hold |
|---|---|
Mobile Money, including cm.mtn, cm.orange and cm.eu | 24 hours |
| Bank | 48 hours |
| Card | 72 hours |
| Crypto | 72 hours |
The hold can be shorter or longer than that base depending on your account's risk profile, and it never exceeds seven days. Your plan, or an agreement with Wajub, can replace the base outright.
Once a hold expires the money can lag the deadline by a few minutes before it becomes available, so read that lag as normal rather than as a stuck balance.
What reserved means
reserved is money committed to payouts that have not finished. Creating a transfer moves the
amount, plus an estimate of the fee, out of available and into reserved before the operator is
ever contacted.
It leaves reserved on the outcome, and which way it goes decides where it lands. On
transfer.succeeded it is debited for real and total drops. On transfer.failed it returns to
available and nothing was charged. A payout held for review keeps its funds reserved for as long
as the hold lasts, which is the one case where reserved can sit still for hours.
The figure you read is up to three minutes old
The figure can lag by up to three minutes. A payout you created a minute ago may not have moved
available yet.
That makes the balance the wrong instrument for a loop. Read it once before a batch to know roughly
where you stand, then let the transfer calls themselves be the authority: a payout that cannot be
funded is refused at creation with its own 422, rather than overdrawing you.
Do not gate each payout on a balance read
Checking the balance before every call in a loop of fifty payouts gives you fifty stale answers and burns your rate limit. Check once, send, and handle the funding error if it comes.
Sandbox is flat
The sandbox reports a single figure repeated: total and available carry the same number, and
pending, reserved and the rest stay at zero. There is no retention, no reservation, and no
settlement to model.
It also starts empty. There is no top-up endpoint and no button in the Konsole. The only thing that credits a sandbox balance is a sandbox payment that succeeds, which is why Transfers Quickstart begins by collecting money before it sends any.
Watching it change
Rather than polling, subscribe to balance.updated. It fires on every movement, and its payload is
the movement itself rather than the new balance object.
balance_type says which bucket moved, pending or available, which is how you tell a fresh
collection from a hold that just expired. direction is credit or debit.
Fees do not arrive as balance.updated
A fee debit is deliberately excluded from this event and published as fee.charged instead, so a
reconciliation built only on balance.updated will find money missing. Subscribe to both.
Settlement to your payout account
Every day at 02:00 UTC, Wajub pays out what you collected on the Wajub rail to your payout account, one payout per currency. The amount is what those payments credited, less the refunds, the fees and the lost disputes already taken on them. Nothing is sent below 1 000 in the credited currency, and payments collected through your own provider are never part of it. With several payout accounts and none chosen for settlement, the day is skipped: Wajub never guesses where your money goes.
Adding funds, and reading your revenue
Revenue, Funding tops up your live balance, with Mobile Money on cm.mtn, cm.orange or
cm.eu, or by bank transfer when it is offered: you send the transfer, then upload the proof on
the same page. The rest of Revenue reads your collected payments by channel and currency, the
processing costs Wajub charged, what went back to customers, and a balance report that shows what
is held for disputes and when recent collections should settle. It is live only, and exports to
PDF or Excel.
There is no ledger endpoint
Nothing on the API returns the list of movements behind a balance. To reconcile a period, list the
resources that caused the movements, GET /payments, GET /transfers and GET /refunds, and add
the fees from your fee.charged events. The Konsole exports the same thing for accounting.