Skip to main content

USSD API

USSD (Unstructured Supplementary Service Data) is the menu-over-dial-code channel for feature phones. A subscriber dials a short code such as *384*1#, the mobile network opens a synchronous session and posts each keypress to your application, and the application replies with the next screen. It needs no data plan, which makes it the reach channel for markets where a large share of devices are 2G feature phones. Orbit hosts the menu and the session engine for you. You configure a menu tree once, point your aggregator (for example Africa’s Talking) at the tenant-scoped callback, and Orbit resolves each step. Base path: /api/v1/ussd Authentication: API key (X-API-Key) or session JWT — except the aggregator callback, which is a public, tenant-scoped webhook.

How a session works

The engine speaks the de-facto African-aggregator protocol. On every step the aggregator sends the full accumulated input string, with each prior keypress joined by * (the initial dial is an empty string). Orbit replies with a plain-text body whose first token is:
  • CON — show the message and keep the session open for more input.
  • END — show the message and terminate the session.
Because the aggregator replays the entire input chain on each callback, the engine is stateless: the next screen is a deterministic function of (menu, accumulated input). There is no per-session storage to manage.

Endpoints

The menu definition

A menu is a tree of nodes (screens) navigated from a root node. Each branch node lists numbered options; a node with no options (or final: true) terminates the session. On PUT /menu the tree is validated for unique node ids and that root plus every option next resolves to an existing node; the request is rejected otherwise. A successful write replaces any previously configured menu.

Create or replace a menu

The configured menu is returned under data.menu. GET /api/v1/ussd/menu returns the same shape, or data.menu: null when none has been configured yet.

Simulate a session step

Run the live engine against an input string without touching your aggregator — useful while building and testing menus. Pass an inline menu to preview an unsaved definition; omit it to use the tenant’s configured menu.
raw is the exact plain-text body the callback would return for the same input. When no menu is configured the simulator returns an END screen rather than an error.

Aggregator callback

Configure this URL in your aggregator dashboard (for example Africa’s Talking). It is a public webhook: the {tenantId} path segment scopes the call to the tenant that owns the menu, so no API key is sent. The aggregator posts it on every step of a session. It accepts both JSON and application/x-www-form-urlencoded bodies with the fields below, and responds with a text/plain body beginning CON (continue) or END (terminate).
USSD has no “back” affordance, so an input that doesn’t match any option — or that arrives after a terminal screen — ends the session cleanly. A callback for a tenant with no configured menu ends the session with END Service is not available. rather than leaving the subscriber hanging.

Network-initiated (push) sessions

The endpoints above all answer a session the subscriber opened by dialling a short code. Push works in the opposite direction: your application asks your aggregator to open a USSD session on a subscriber’s handset — for balance prompts, mobile-money confirmations, and feature-phone OTP flows. Push has no company-wide provider. You register your own aggregator push endpoint per tenant, exactly like the inbound callback URL you set in your aggregator dashboard, and Orbit POSTs each push to it. The push URL must be an https:// URL and is re-validated and DNS-pinned against the SSRF guard on every send.

Configure the push provider

Set the aggregator endpoint your push sessions go out through with PUT /api/v1/ussd/push/config.
GET /api/v1/ussd/push/config returns the stored config under data.config, or data.config: null when none is set. The credential is never echoed back: instead of authHeaderValue, the read response carries authConfigured — a boolean reporting whether a credential is stored.

Open a push session

POST /api/v1/ussd/push opens the session on the subscriber’s handset via the configured aggregator.
providerStatus is the HTTP status your aggregator returned (a 2xx). accepted means the aggregator took the session; the subscriber’s reply, if any, then arrives on your aggregator callback like any other step.

Error codes

USSD sessions never originate outbound voice or SMS. The reply is returned synchronously to the aggregator inside the open session, so no termination path is involved.

See also