USSD Webhooks

The endpoints carriers call to deliver live USSD sessions to your service.

The carrier calls these endpoints to hand off each session event. You do not have to register anything: when a USSD code or extension is approved, your platform points the carrier at the first URL below automatically. 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

Webhook routes are called by the carrier, not by your server. They are unauthenticated by design. Do not send an Authorization header, and do not expose these URLs as if they were your API token endpoints.

Carrier webhook

POST/webhooks/ussd/mobilesasa

The carrier handles USSD for every Kenyan network. It sends each session event as a form post (application/x-www-form-urlencoded). Answer with JSON.

Received form fields

sessionIdstringrequired
Unique session identifier from the carrier
phoneNumberstringrequired
Subscriber phone number
networkCodestring
Network the subscriber is on
serviceCodestringrequired
USSD code that was dialed
textstring
All input so far in the session, empty on the first request
Your response
// continue the session
{ "response": "Acme Services\n1. Check balance\n2. Buy data", "end_session": false }

// or end it
{ "response": "Thank you for using Acme Services.", "end_session": true }

No CON or END prefix here

end_session alone decides whether the session continues. Do not prefix the response text with CON or END , the subscriber would see the prefix on their handset.

Generic JSON webhook

POST/webhooks/ussd/inbound

For other carriers that speak a JSON API. Both the request from the carrier and your response use JSON.

Request body from carrier

msisdnstringrequired
Subscriber phone
service_codestringrequired
USSD code dialed
session_idstringrequired
Carrier session ID
ussd_stringstring
Subscriber input so far
networkstring
Network identifier (airtel, telkom, equitel)
Request from carrier
{
  "msisdn": "+254712345678",
  "service_code": "*657#",
  "session_id": "carrier-sess-abc123",
  "ussd_string": "*657*1#",
  "network": "airtel"
}
Your response
{
  "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.

POST to your callback_url for each session event
{
  "session_id":   "carrier-sess-abc123",
  "service_code": "*657#",
  "msisdn":       "+254712345678",
  "ussd_string":  "*657*1#",
  "network":      "safaricom"
}
Your response (continue, or end)
// 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

Exercise your menus and callback handlers end to end with USSD simulation before pointing a carrier at these webhook URLs.