Sandbox mode
The same API, a different database, and outcomes you choose.
Sandbox is not a separate product or a mock server. It is the same code, the same routes and the same validation, writing to a different database. What changes is where the money comes from: no operator is contacted, and the outcome is decided by the test number, card or account you use.
How the environment is chosen
By the key. There is no parameter, no header and no flag.
| Prefix | Environment |
|---|---|
pk_test., sk_test., rk_test., hsk_test. | Sandbox |
pk., sk., rk., hsk. | Live |
A sandbox key cannot read live data, and the reverse is equally true, because the two live in separate databases. That is also why a payment you created in sandbox will never appear in your live Konsole, and why there is nothing to filter.
Deleting sandbox data does not exist as a mistake you can make
There is no button and no endpoint that wipes an environment. But there is also no migration path: nothing you build up in sandbox, customers, beneficiaries, endpoints, comes with you when you switch to live. Recreate them deliberately.
What is real
| Real in sandbox | Meaning |
|---|---|
| Validation | The same rules, the same 422 messages |
| Limits | Amount floors and ceilings are enforced identically |
| Events and webhooks | Real events, real signatures, real retries |
| Idempotency | The same behaviour on a repeated key |
| Rate limits | The same counters |
| Balance | A separate sandbox balance, credited by sandbox payments |
| Platform fees | 2% is charged on successful payments and transfers, producing fee.charged |
The last one surprises people: a sandbox payment of 5,000 XAF credits less than 5,000 to your sandbox balance, exactly as a live one would.
What is simulated
| Simulated | How |
|---|---|
| The operator | The test number decides the outcome, nothing is dialled |
| The card network | The test card decides the outcome |
| 3D Secure | Hosted checkout shows a simulated challenge you can pass or fail |
| The bank | The last two digits of the account decide the outcome |
| Crypto | The wallet address suffix decides the outcome, and a deposit address is generated |
| Timing | A fixed delay rather than a real network |
The delays are short and fixed, which is what makes an automated test suite possible.
| Operation | Delay before the terminal status |
|---|---|
| Payment | 3 seconds |
| Refund | 2 seconds |
| Transfer | 2 seconds |
Asynchronous, not instant
A sandbox payment is still pending when the call returns. A test that asserts succeeded
immediately after creating it will fail. Wait for the webhook, or poll until the status is
terminal.
Outcomes are deterministic
This is the part worth internalising: nothing in the sandbox is random, with one narrow exception.
| Object | What decides the outcome |
|---|---|
| Payment, mobile money | The suffix of the payer number |
| Payment, card | The exact card number |
| Payment, bank | The last two digits of the account |
| Payment, crypto | The suffix of the wallet address |
| Refund | The original payment's card or phone |
| Transfer | The beneficiary's test number or account |
The exception: a refund on a payment with no payment method attached falls back to a 70% chance of success. In practice this only happens on payments created without a payer, which is not a flow you ship.
Transfers are deterministic too
A sandbox transfer to a mobile money beneficiary requires a recognised test number and refuses
anything else with a 422 that lists the valid ones. There is no probability involved.
The sandbox balance
Payouts need money. Sandbox payments credit a sandbox balance, and transfers debit it, so the order of your test matters: create and complete a payment before testing a payout, or the transfer fails for insufficient funds exactly as it would in production.
A failed transfer returns the amount to the balance. The 2% platform fee is not returned, which mirrors live behaviour.
Crypto is off unless asked for
The crypto channel is disabled in sandbox by default. When it is enabled, a deposit address and a payment URI are generated per scenario, valid for 30 minutes, and the address itself is deterministic, so you can reproduce the same scenario twice.