Sandbox and test numbers
Test keys (sk_test_) hit the same API against a simulated provider. No real money can move on
a test key, ever — the environments are separated at the key level, not by a flag you could
get wrong.
The test numbers
The last two digits of the customer number choose the scenario. Any other suffix behaves as success.
| Number | Scenario | What happens | Final status |
|---|---|---|---|
263771000001 | Success | Customer approves promptly | completed |
263771000002 | PIN declined | Customer rejects the prompt | failed |
263771000003 | Customer timeout | Prompt delivered, never answered | expired |
263771000004 | Insufficient funds | Wallet can’t cover it | failed |
263771000005 | Invalid number | Provider rejects the MSISDN | failed |
263771000006 | Duplicate reference | Provider claims it has seen this reference | failed |
263771000007 | Delayed answer | Provider answers “pending” twice, confirms on the third query | completed |
263771000008 | Callback never arrives | Success, but the provider never calls back — our resolver discovers it by asking | completed |
263771000009 | Provider HTTP 500 | The charge call itself errors — payment goes unknown, resolves on query | unknown → completed |
263771000010 | Connection timeout | Nothing ever answers — the full unknown journey | unknown → unresolved |
What to actually test
Before going live, walk your integration through at least:
- The happy path (
...01): create → webhook → fulfil. - A definitive failure (
...02): your UI says “declined”, your books say nothing owed. - The delayed answer (
...07): your code waits for the webhook rather than timing out at 5 seconds and guessing. - The
unknownpath (...09): your UI says “confirming — don’t pay again”, not “failed”. This is the test that protects your customers from double charges. - A retry with the same
Idempotency-Key: confirm you get the same payment back, not a second one.
Forcing outcomes without numbers
POST /v1/test/simulate (test keys only) advances a payment directly — useful in automated
test suites where you don’t want to wait for the resolver’s schedule:
curl https://api.lango.co.zw/v1/test/simulate \ -H "Authorization: Bearer sk_test_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "payment_id": "pay_...", "outcome": "completed" }'Webhooks in the sandbox
Test-mode webhooks deliver and sign exactly like live ones. Point an endpoint at a tunnel
(ngrok or similar) during development, and use POST /v1/events/{id}/replay to re-fire any
event while debugging your handler.