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.
| Ceiling | Applies to | Refusal |
|---|---|---|
| Amount for the currency | Every payment and every transfer | 422 at creation |
| Mobile money per debit | One mobile money charge | 422 at processing |
| Account limits from KYC | Live volume, in and out | 402 on a payment, 422 on a payout |
| Requests per minute | Every call | 429 |
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.
| Currency | Minimum | Maximum |
|---|---|---|
| 25 | 2,000,000 | |
| 25 | 2,000,000 | |
| 100 | 999,999.99 | |
| 0.50 | 999,999.99 | |
| 0.50 | 999,999.99 | |
| 0.50 | 999,999.99 | |
| 1,000 | 999,999,999 | |
| 500 | 999,999,999 | |
| 1,000 | 999,999,999 | |
| 0.50 | 999,999.99 | |
| 0.50 | 999,999.99 | |
| 0.50 | 999,999.99 | |
| 0.50 | 999,999.99 | |
| 0.50 | 999,999.99 |
Ninety-two currencies carry bounds, not only the ones above. A currency absent from that table is not bounded at all at this layer, and the account limits further down are then the only ceiling.
Out of bounds, the call never reaches a provider.
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.
| Rail | Ceiling per charge | Where it comes from |
|---|---|---|
| 500,000 XAF or XOF | Operator rules, per debit | |
| The currency ceiling | No separate cap | |
| The currency ceiling | No separate cap | |
| The currency ceiling | No 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.
Other currencies are converted, not exempt
Only XAF and XOF carry an explicit mobile money cap. A payment in another currency 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.
Splitting a payment into two to four charges is documented here. Today the instalment executor runs in sandbox, so treat the cap as a hard ceiling in live and size the charge under it.
What your account is allowed to move
Above the per-call bounds sit six figures attached to your team: a single, daily and monthly ceiling for money in, and the same three for money out. They are written by compliance verification, not by your plan.
| Tier | Single payment | Daily in | Single payout | Daily out |
|---|---|---|---|---|
basic | 500,000 | 2,000,000 | 500,000 | 1,000,000 |
verified | 5,000,000 | 20,000,000 | 5,000,000 | 10,000,000 |
premium | 50,000,000 | 200,000,000 | 50,000,000 | 100,000,000 |
enterprise | 500,000,000 | 2,000,000,000 | 500,000,000 | 1,000,000,000 |
Those are base figures in XAF, and nobody gets them as written. Four multipliers apply on top, and they compound.
| Multiplier | Values |
|---|---|
| Risk level | low 1.5, medium 1.0, high 0.5, critical 0.2 |
| Business category | High risk 0.5, medium 0.8, low 1.2, otherwise 1.0 |
| Legal structure | Company 1.5, NGO 1.2, individual 0.8, otherwise 1.0 |
| Compliance status | verified 1.0, anything else 0 |
A verified low-risk company therefore runs at 1.5 × 1.2 × 1.5 = 2.7 times the base, while an individual trader under review runs at zero.
Zero is a block, not an absence
An unverified account has its six limits written as 0, and 0 is enforced as a refusal rather than
read as unlimited. Every live payment then answers 402 with error_code: merchant_not_verified,
and every payout answers 422 with Payouts are not available for this account yet. Sandbox is
unaffected.
Once the ceiling is real, breaching it reads as a decline.
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.
Only on the Wajub rail
Inbound limits are enforced only for teams whose single active provider is Wajub. Route through your own PSP credentials and the ceiling belongs to that provider, not to us. Payout limits have no such exemption.
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.
| Rail | Default hold | Why |
|---|---|---|
| 24 hours | Settles and disputes fast on the operator side | |
| 48 hours | Slower reversal window | |
| 72 hours | Chargeback exposure | |
| 72 hours | Chargeback exposure |
Your risk level scales that base by 0.5, 1, 2 or 3, and the result is clamped between 6 and 168 hours. A team with an explicit ops override skips the scaling entirely.
Payouts have their own brakes
Three mechanisms sit between a payout request and the money leaving, and they are independent of the amount ceilings above.
| Brake | Trigger | Effect |
|---|---|---|
| Velocity | More than 6 payouts, or more than 3,000,000 XAF, in a rolling hour | Refused |
| Manual review | Any payout at or above 1,000,000 XAF | Held for review |
| Manual review | Your first live payout, ever | Held for review |
| Manual review | More than 5 times your own average, after 3 successful payouts | Held for review |
| Account freeze | 2 review rejections within 24 hours | Transfers restricted until ops lifts it |
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.
| Quota | Pay as you go | Growth | Scale | Enterprise |
|---|---|---|---|---|
| Requests per minute | 120 | 360 | 720 | Unlimited |
| Payment links | 25 | Unlimited | Unlimited | Unlimited |
| Invoices | 10 | Unlimited | Unlimited | Unlimited |
| Team members | 3 | 5 | Unlimited | Unlimited |
| Providers | 2 | 6 | Unlimited | Unlimited |
| Exports per month | 10 | Unlimited | Unlimited | Unlimited |
| Webhook replays per month | 5 | 25 | Unlimited | Unlimited |
Link and invoice allowances count live rows only, and creating past them answers 403. Sandbox
links and invoices are free.
Requests per minute
Four counters run on every call, and the first to trip wins. They are not alternatives: a request under the team ceiling can still be refused by the IP one.
| Counter | Ceiling | Keyed on |
|---|---|---|
| Team | Your plan's figure | Team id |
| API key | 100 | The Authorization header |
| IP | 120 | Client IP |
| Endpoint | See below | Team id and resource |
| Unauthenticated | 30 | Client IP |
Endpoint ceilings are a base figure times a plan multiplier.
| Resource | Pay as you go | Growth | Scale and Enterprise |
|---|---|---|---|
/payments | 60 | 180 | 30 |
/transfers | 40 | 120 | 20 |
/refunds | 20 | 60 | 10 |
/customers | 100 | 300 | 50 |
The endpoint multiplier does not reward the top plans
The multiplier is chosen from the team ceiling by exact match: 360 gets 6x, 120 gets 2x, and anything else gets 1x. A Scale team on 720 and an Enterprise team on no ceiling both fall into that last branch, which leaves them with lower per-endpoint ceilings than Growth. Size your concurrency against the figures above rather than against your plan tier.
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.
| Field | Bound |
|---|---|
expires.in | 5 to 43,200 minutes, default 1,440 |
description | 500 characters |
reference | 128 characters |
callback | 2,048 characters |
Idempotency-Key | 128 characters, A-Za-z0-9._:- |
per_page | 1 to 100, default 25 |
split_count | 2, 3 or 4 |
split_amounts | 2 to 4 amounts, each at least 0.01 |
| Dispute evidence file | 10 MB, pdf jpg jpeg png doc docx txt |
| Dispute message | 5,000 characters |
Webhook delivery
| Parameter | Value |
|---|---|
| Attempts per event | 5 |
| Retry schedule | 30s, 1min, 5min, 10min, 1h |
| Request timeout | 10 seconds |
| Signature tolerance | 300 seconds |
Answer inside the timeout or the delivery is retried, which is why acknowledging first and processing after is the shape to build.