Skip to content

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.

NumberScenarioWhat happensFinal status
263771000001SuccessCustomer approves promptlycompleted
263771000002PIN declinedCustomer rejects the promptfailed
263771000003Customer timeoutPrompt delivered, never answeredexpired
263771000004Insufficient fundsWallet can’t cover itfailed
263771000005Invalid numberProvider rejects the MSISDNfailed
263771000006Duplicate referenceProvider claims it has seen this referencefailed
263771000007Delayed answerProvider answers “pending” twice, confirms on the third querycompleted
263771000008Callback never arrivesSuccess, but the provider never calls back — our resolver discovers it by askingcompleted
263771000009Provider HTTP 500The charge call itself errors — payment goes unknown, resolves on queryunknowncompleted
263771000010Connection timeoutNothing ever answers — the full unknown journeyunknownunresolved

What to actually test

Before going live, walk your integration through at least:

  1. The happy path (...01): create → webhook → fulfil.
  2. A definitive failure (...02): your UI says “declined”, your books say nothing owed.
  3. The delayed answer (...07): your code waits for the webhook rather than timing out at 5 seconds and guessing.
  4. The unknown path (...09): your UI says “confirming — don’t pay again”, not “failed”. This is the test that protects your customers from double charges.
  5. 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:

Terminal window
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.