Testing USSD Flows
Carrier provisioning is slow and live testing is costly, so validate your full flow in the sandbox first. This guide covers simulating sessions, asserting responses, and a pre-launch checklist.
๐ Quick Startโ
Point your service code at the sandbox and dial the simulator.
curl -X POST https://api.afriroute.ai/api/v1/ussd/simulate \
-H "Authorization: Bearer $AFRIROUTE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"service_code": "*123#",
"phone": "+254712345678",
"text": ""
}'
The simulator calls your webhook exactly as a live gateway would and returns your CON/END reply.
๐งช Driving a Multi-Step Sessionโ
Replay a sequence of keypresses by building up the text field, keeping the same session_id.
import requests
BASE = 'https://api.afriroute.ai/api/v1/ussd/simulate'
H = {'Authorization': 'Bearer $AFRIROUTE_API_KEY'}
sid = 'test-session-1'
def step(text):
r = requests.post(BASE, headers=H, json={
'session_id': sid, 'service_code': '*123#',
'phone': '+254712345678', 'text': text})
return r.json()['response']
assert step('').startswith('CON') # root menu
assert 'balance' in step('1').lower() # selected option 1
โ What to Assertโ
| Check | Why |
|---|---|
Root returns CON | Menu renders on empty input |
| Each option routes correctly | No mis-mapped digits |
Terminal steps return END | Sessions close cleanly |
| Invalid input re-prompts | No dead ends |
| Screen length โค ~160 chars | No truncation |
| Response time < timeout | No gateway drops |
test('invalid input re-prompts', async () => {
const res = await simulate({ text: '9' });
expect(res).toMatch(/^CON/);
expect(res.toLowerCase()).toContain('invalid');
});
๐ฆ Pre-Launch Checklistโ
- All menu paths reach an
END. - Invalid input handled at every step.
- Money flows confirmed by SMS receipt.
- State expires within the carrier session window.
- Screens fit within character limits.
- Webhook responds well under the timeout.
- Tested with the live
service_codeonce provisioned.
๐ก Best Practicesโ
- Automate flow tests so regressions are caught on every deploy.
- Test the unhappy paths (timeouts, invalid keys) as much as the happy path.
- Use a fixed
session_idper test to keep runs deterministic. - Verify against the real service code before public launch.
- Load-test the webhook โ gateways are unforgiving of latency.
๐ Related Resourcesโ
- USSD API
- USSD Best Practices Guide
- USSD Sessions Guide
- USSD Menu Patterns Guide
- USSD Error Handling Guide
Last Updated: May 2026