Skip to content

Response Data Definitions

Each USSD endpoint returns a standardized response structure. Below are their definitions and usage.

Both USSD endpoints return the following top-level structure. The error state uses the same structure and also arrives with a 2xx status, so read that section before you write your parser.

{
"message": "USSD session created successfully",
"data": {
"sessionId": "ussd_3278668b308502f3a562950fc8043028",
"currentState": "HOME",
"menu": {
"state": "HOME",
"text": "Select an investment option:",
"options": [
{
"key": "1",
"label": "Stocks",
"nextState": "STOCKS"
},
{
"key": "2",
"label": "My Portfolio",
"nextState": "MY_PORTFOLIO"
}
],
"isEndState": false
},
"ussdText": "Select an investment option:\n\n1. Stocks\n2. My Portfolio",
"expiresAt": "2025-11-06T14:38:12.202Z"
}
}
What the customer sees
Select an investment option:

1. Stocks
2. My Portfolio
Key Definition Required
message A string message indicating the result of the operation Yes
data An object containing the session and menu information Yes

The data object contains the session information and menu structure:

Key Definition Required
sessionId Unique identifier for the USSD session Yes
currentState The current state of the session (e.g., “HOME”, “STOCKS”, “MY_PORTFOLIO”) Yes
menu An object containing the menu structure with options Yes
ussdText The formatted USSD text to display to the user Yes
expiresAt The expiration timestamp of the session (ISO 8601 format) Yes

The menu object contains the menu structure and available options:

Key Definition Required
state The current menu state (e.g., “HOME”, “STOCKS”) Yes
text The menu text to display to the user Yes
options An array of menu options available to the user Yes
isEndState A boolean indicating whether this is an end state (session terminates if true) Yes

Each option in the options array is a MenuOption object:

Key Definition Required
key The option key that the user can select (e.g., “1”, “2”, or “Tesla”, “Apple”) Yes
label The display label for the option Yes
nextState The next state to transition to when this option is selected (optional) No
action An operation the option performs rather than a plain navigation (optional) No
data Optional additional data associated with the option (e.g., stock information) No

Simple option with next state:

{
"key": "1",
"label": "Stocks",
"nextState": "STOCKS"
}

Option without next state (e.g., “Next”):

{
"key": "7",
"label": "Next"
}

Option that performs an action instead of navigating:

{
"key": "1",
"label": "Yes, cancel",
"action": "CANCEL_ORDER"
}

Option with additional data (stock information):

{
"key": "1",
"label": "AAPL",
"nextState": "SELECT_STOCK",
"data": {
"stockId": "cmhkp4jkw0005zxfok9m0kiwg",
"symbol": "AAPL",
"name": "Apple Inc."
}
}

Example: Stocks menu response

{
"message": "USSD request processed successfully",
"data": {
"sessionId": "ussd_3278668b308502f3a562950fc8043028",
"currentState": "STOCKS",
"menu": {
"state": "STOCKS",
"text": "Select Stock:",
"options": [
{
"key": "1",
"label": "AAPL",
"nextState": "SELECT_STOCK",
"data": {
"stockId": "cmhkp4jkw0005zxfok9m0kiwg",
"symbol": "AAPL",
"name": "Apple Inc."
}
},
{
"key": "2",
"label": "AMZN",
"nextState": "SELECT_STOCK",
"data": {
"stockId": "cmhkp4kcp0008zxfohlxjtvd7",
"symbol": "AMZN",
"name": "Amazon.com Inc."
}
},
{
"key": "7",
"label": "Next"
},
{
"key": "8",
"label": "Search",
"nextState": "SEARCH_STOCK"
},
{
"key": "0",
"label": "Home",
"nextState": "HOME"
}
],
"isEndState": false
},
"ussdText": "Select Stock:\n\n1. AAPL\n2. AMZN\n7. Next\n8. Search\n0. Home",
"expiresAt": "2025-11-06T14:38:12.202Z"
}
}
What the customer sees
Select Stock:

1. AAPL
2. AMZN
7. Next
8. Search
0. Home

If the API hits an unexpected internal error while building a menu, it does not return a 4xx or 5xx. Both endpoints answer HTTP 200 carrying an error menu, so the customer on the handset still sees a readable message instead of a blank screen.

message is "USSD session created with error state" or "USSD request processed with error state". data is the same shape as the success responsesessionId, currentState, menu, ussdText and expiresAt are all present — with currentState and menu.state set to "ERROR":

{
"message": "USSD request processed with error state",
"data": {
"sessionId": "ussd_3278668b308502f3a562950fc8043028",
"currentState": "ERROR",
"menu": {
"state": "ERROR",
"text": "Sorry, something went wrong. Please try again later.",
"options": [
{
"key": "0",
"label": "Home",
"nextState": "HOME"
}
],
"isEndState": false
},
"ussdText": "Sorry, something went wrong. Please try again later.\n\n0. Home",
"expiresAt": "2025-11-06T14:38:12.202Z"
}
}

The session is real and is left in the ERROR state, so you drive the next leg from sessionId and expiresAt exactly as on the success path, and 0 still takes the customer Home. On POST /v1/ussd/session the sessionId is a new session opened in ERROR, because the session the request asked for was never created.

Errors the API can attribute — an unknown customer, an expired or inactive session, a session belonging to another organization — are not this shape. Those return proper status codes; see Errors.