Skip to content

Limits & quotas

The ceilings the API enforces, and the error each one returns.

Four different ceilings can refuse the same call, and each one answers with a different status code. Reading the code tells you which one you hit before you read anything else.

CeilingApplies toRefusal
Amount for the currencyEvery payment and every transfer422 at creation
Mobile money per debitOne mobile money charge422 at processing
Account limits from KYCLive volume, in and out402 on a payment, 422 on a payout
Requests per minuteEvery call429

Plan quotas are a fifth kind, and they refuse the resource rather than the amount: payment links and invoices stop being creatable once the plan's allowance is used.

Amounts, per currency

One table governs both directions. POST /payments and POST /transfers read the same per-currency bounds, so a payout is refused by exactly the figures that would refuse a payment of the same size. Amounts are in major units.

CurrencyMinimumMaximum
XAFXAF252,000,000
XOFXOF252,000,000
NGNNGN100999,999.99
GHSGHS0.50999,999.99
KESKES0.50999,999.99
TZSTZS0.50999,999.99
UGXUGX1,000999,999,999
RWFRWF500999,999,999
GNFGNF1,000999,999,999
CDFCDF0.50999,999.99
ZARZAR0.50999,999.99
ZMWZMW0.50999,999.99
EGPEGP0.50999,999.99
EUREUR0.50999,999.99

Ninety-two currencies carry bounds, not only the ones above, and the API refuses an amount outside them.

Out of bounds, the call never reaches a provider.

422 on a 10 XAF payment
{
"code": 422,
"status": "Unprocessable Content",
"message": "Amount must be between 25 and 2000000 XAF.",
"errors": {
"amount": [
"The amount must be between 25 and 2000000 XAF."
]
}
}

The same refusal on POST /transfers reads Transfer amount must be between …, with the same two figures.

One mobile money debit is capped separately

The currency ceiling is what a payment may be worth. The mobile money ceiling is what a single debit on a wallet may be worth, and it is far lower.

RailCeiling per chargeWhere it comes from
Mobile MoneyMobile Money500,000 XAF or XOFOperator rules, per debit
CardsCardsThe currency ceilingNo separate cap
BankBankThe currency ceilingNo separate cap
CryptoCryptoThe currency ceilingNo separate cap

A mobile money charge above that cap is refused at processing time, not at creation. The payment stays pending and can be retried.

422 on a 900,000 XAF mobile money charge
{
"code": 422,
"status": "Unprocessable Content",
"message": "This transaction amount exceeds the per-transaction limit for cm.mtn. Use split_count or split_amounts to split the payment.",
"payer_message": "This amount is above the limit for this payment method. Use a smaller amount or another method.",
"errors": {
"request": [
"This transaction amount exceeds the per-transaction limit for cm.mtn. Use split_count or split_amounts to split the payment."
]
}
}

A ceiling per currency, the others converted

The cap is set per currency. Today XAF and XOF carry 500,000. A payment in a currency without a cap of its own, paid through a West or Central African wallet, converts the 500,000 XAF figure at the current rate and floors it to a whole unit, so the cap follows you into USD or EUR rather than disappearing. When Wajub sets a currency's own cap, it replaces the converted figure. Those wallets are offered on a USD or EUR payment by default; narrow the list with accept.

A payment above the cap can be paid in two to four charges, each under it, once you have turned on instalments: Split payments describes the calls. A single charge above it is refused, in live and in sandbox: nothing splits a payment on its own.

What your account is allowed to move

Above the per-call bounds sit limits of your own account: a single, daily and monthly ceiling for money in, and the same three for money out. They depend on your verification, your activity and Wajub's risk assessment, not on your plan. Your current limits are shown in the Dashboard; write to support to raise them.

Once your account is verified, a payment past one of its limits reads as a decline.

402 on a payment above the single-transaction ceiling
{
"code": 402,
"status": "Payment Required",
"error_code": "limit_exceeded",
"message": "Transaction amount 180 000 XAF exceeds your single-transaction limit of 150 000 XAF. Please contact support to increase your limit.",
"payer_message": "This payment exceeds the amount this merchant can currently accept."
}

The daily and monthly counters run on credited live payments in that currency, and reset at midnight UTC and on the first of the month. Payout counters count pending, processing, review and succeeded transfers together, so a payout held for review still occupies the day's allowance.

Funds are held before they can be withdrawn

A credited payment lands in pending_balance and moves to available_balance when its hold elapses. The base hold follows the rail the money came in on.

RailDefault holdWhy
Mobile MoneyMobile Money24 hoursSettles and disputes fast on the operator side
BankBank48 hoursSlower reversal window
CardsCards72 hoursChargeback exposure
CryptoCrypto72 hoursChargeback exposure

The hold on your account can be shorter or longer than the default, depending on your activity and Wajub's risk assessment.

Payouts have their own brakes

Two mechanisms sit between a payout request and the money leaving, and they are independent of the amount ceilings above.

BrakeTriggerEffect
VelocityMore than 6 accepted payout calls, or more than 3,000,000 XAF paid out, in a rolling hourRefused with 422
ReviewWajub may hold a payout for review before it leavesHeld in review

Velocity counts what was accepted, not what was tried. A payout refused for any reason, the velocity ceiling included, takes no place in the hour, so retrying a refused payout never extends the wait. A batch is one call: it takes one of the six places whatever its number of lines, and gives it back if it ends up sending nothing. Each line still adds its amount to the 3,000,000 XAF. A payout in another currency is converted to XAF at Wajub's rate before it is added. A retry of a batch whose lines already went out is never refused whole: those lines come back as they are, and only a line still to send is refused when no place is left. Both ceilings are set per account, and only Wajub can raise them.

A held payout is not a failed one: it sits in review and moves on once approved. Treat review as a normal state in your reconciliation rather than an error.

Plan quotas

The plan governs resources and throughput, never amounts.

QuotaPay as you goGrowthScaleEnterprise
Requests per minute120360720Unlimited
Payment links25UnlimitedUnlimitedUnlimited
Invoices10UnlimitedUnlimitedUnlimited
Team members35UnlimitedUnlimited
Providers26UnlimitedUnlimited
Exports per month10UnlimitedUnlimitedUnlimited
Webhook replays per month525UnlimitedUnlimited

Link and invoice allowances count live links and invoices only, and creating past them answers 403. Links and invoices exist in live only: with a sandbox key the API answers 403 (This feature is only available in live mode.).

Requests per minute

Three counters run on every call made with a key, and the first to trip wins. All three follow your plan: a key may spend the whole team budget, and an Enterprise team has no ceiling on any of them.

CounterCeiling
TeamYour plan's figure
API keyYour plan's figure
Endpoint, per resourceSee below
Call without a key30

Endpoint ceilings are shares of the entry plan's 120 requests a minute, and they grow with the plan: three times as much on Growth, six times on Scale. Every call under the resource counts, reads included.

ResourcePay as you goGrowthScaleEnterprise
/payments3090180No ceiling
/transfers2060120No ceiling
/refunds103060No ceiling
/customers50150300No ceiling

One call has a fixed ceiling of its own, on every plan, Enterprise included: POST /beneficiaries/{id}/verify, which asks an operator for the name behind a number, takes 10 checks a minute and 200 a day per account in live, and 10 a minute in sandbox.

Rate limits carries the response headers and the two 429 body shapes.

Field limits

Validation bounds you are most likely to hit, all from the request rules themselves.

FieldBound
expires.in5 to 43,200 minutes, default 1,440
description500 characters
reference128 characters
callback2,048 characters
Idempotency-Key128 characters, A-Za-z0-9._:-
per_page1 to 100, default 25
split_count2, 3 or 4
split_amounts2 to 4 amounts, each at least 0.01
Dispute evidence file10 MB, pdf jpg jpeg png doc docx txt
Dispute message5,000 characters

Webhook delivery

ParameterValue
Retry window72 hours after the first attempt
Wait between attempts30 seconds, doubled after each failure, up to 6 hours, with jitter
Not retried410 Gone
Request timeout10 seconds
Signature tolerance300 seconds

Answer inside the timeout or the delivery is retried, which is why acknowledging first and processing after is the shape to build.

What did you think of this content?