USSD Webhooks
The endpoints carriers call to deliver live USSD sessions to your service.
Carriers call these endpoints to hand off each session event. Register the URLs in your carrier portal (or ask an admin to). Unlike the rest of the API, these routes take no authentication token, they are publicly accessible endpoints trusted by carrier IP ranges, so never put secrets in the URLs.
No Bearer token here
Authorization header, and do not expose these URLs as if they were your API token endpoints.Safaricom webhook
Safaricom sends session events as query parameters. Your response must be plain text (not JSON) starting with CON to continue the session or END to terminate it.
Subscriber phone number
USSD code that was dialed
Unique session identifier from the carrier
All input so far in the session (e.g. *657*1*2#)
CON Acme Services
1. Check balance
2. Buy data
0. Exit
# End the session
END Thank you for using Acme Services.Generic JSON webhook
For other carriers that speak a JSON API. Both the request from the carrier and your response use JSON.
Subscriber phone
USSD code dialed
Carrier session ID
Subscriber input so far
Network identifier (airtel, telkom, equitel)
{
"msisdn": "+254712345678",
"service_code": "*657#",
"session_id": "carrier-sess-abc123",
"ussd_string": "*657*1#",
"network": "airtel"
}{
"response": "CON Acme Services\n1. Check balance\n2. Buy data",
"end_session": false
}Callback mode, your own server
When a code or extension is set to mode=callback, the platform forwards each session event to your callback_url as a POST. Your server must respond within 3 seconds with a JSON body.
{
"session_id": "carrier-sess-abc123",
"service_code": "*657#",
"msisdn": "+254712345678",
"ussd_string": "*657*1#",
"network": "safaricom"
}// continue the session
{ "response": "CON Your balance is KES 1,200.\n0. Back", "end_session": false }
// or end it
{ "response": "END Thank you!", "end_session": true }Test the whole flow first