Sandbox and Going Live¶
You get two sets of API credentials: sandbox and production. They are separate applications with separate client IDs and secrets, issued from the merchant portal, and they behave identically apart from what happens at the far end.
Sandbox is not a different API. Same host, same endpoints, same request and response shapes, same errors, same webhooks. What changes is that no money moves, and that you choose what happens by choosing who you pay.
The two environments¶
| Sandbox | Production | |
|---|---|---|
| Host and endpoints | identical | identical |
| Credentials | your sandbox client ID and secret | a separate pair |
| Wallet charged | your sandbox wallet, play balance | your real wallet |
| Outcome | chosen by the destination — see Sandbox Credentials & Test Numbers | whatever actually happens |
Webhooks to your result_url |
real HTTP, same payload | real HTTP |
| IP whitelisting | not enforced | enforced — requests from any other address are refused |
| Payouts before verification | allowed | blocked until your business is verified |
| Appears in your dashboards, statements and exports | never | yes |
Two rows there are worth reading twice.
IP whitelisting is not enforced in sandbox. You can integrate from a laptop, from CI, from anywhere, without registering an address. It is enforced in production, and an application with no whitelisted address has every request refused — which is why adding one is on the go-live checklist below, rather than being something you discover on your first real payment.
Sandbox traffic is invisible everywhere else. It is not in your dashboard totals, your statements, your exports or your real balance. You cannot inflate your own numbers by testing, and you cannot lose test data by looking at a report.
Get sandbox credentials¶
- Sign in to the merchant portal and register if you have not already. You do not need to be verified.
- Go to Developers → API Applications and create an application with environment Sandbox.
- Copy the client ID and secret. The secret is shown in full to the account owner; treat it like a production one anyway — see Token Handling.
A sandbox wallet is created for you at the same time, with a play balance of KES 1,000. You can read it and reset it from the portal. Resetting restores the balance and leaves your test payments alone, because those are what the go-live checklist reads.
The balance is small deliberately — payouts spend it and are refused when it runs out, so you meet that check early rather than in production. Collections credit it back.
You can do this the day you register. Verification is not required to build and test an integration — only to take real money.
Going live¶
When your integration works in sandbox, create a second application with environment Production. It is issued only when all of the following are true, and the portal shows you which are outstanding at Developers → Go Live:
| Requirement | Why |
|---|---|
| Your business is verified (full KYB) | The same line that unlocks payouts. Live credentials unlock with it. |
| One successful collection in sandbox | You can take money. |
| One successful payout in sandbox | You can send money. |
| Your webhook has returned a 2xx to a sandbox result | Your callback endpoint exists, is reachable, and your code handled a real delivery. This is the one that most often catches a problem. |
| At least one whitelisted IP address | Production refuses requests from anywhere else. Better found now than on your first live payment. |
Going live does not disable your sandbox application. You keep both, permanently — you will want somewhere to test your next change after you are live. Point your test environment at the sandbox credentials and your production environment at the live ones; nothing else in your integration changes.
There is no way to have this waived. The checklist is the process.
Moving your integration over¶
Everything that differs between the two is configuration, not code:
- the client ID and secret you exchange for a token,
- the
merchant_idyou send in the request body — your sandbox wallet has its own account number, and it is deliberately not derived from your live one, so a hardcoded sandbox value sent to production fails with "wallet not found" rather than touching a real wallet, - your
result_url, if your test and production handlers are different services.
If anything else has to change, something is wrong — tell us, because it means the two environments have drifted and that is our bug, not yours.
Next steps¶
- Sandbox Credentials & Test Numbers — the destinations that produce each outcome.
- Test Scenarios by Payment Method — worked flows, including the failures.
- Quickstart — a first call, end to end.