Skip to content

Processes a customer's USSD request

POST
/process
curl --request POST \
--url https://api.pipevest.com/v1/ussd/process \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'X-Idempotency-Key: 2489E9AD-2EE2-8E00-8EC9-32D5F69181C0' \
--header 'x-client-id: <x-client-id>' \
--data '{ "sessionId": "ussd_3278668b308502f3a562950fc8043028", "choice": "1" }'

Advances an existing session. The body is { sessionId, choice } — it does not take a customerId.

What the customer sees (example: the Stocks menu):

Select Stock:

1. AAPL
2. AMZN
7. Next
8. Search
0. Home
X-Idempotency-Key
required
string format: uuid

Idempotency key (UUID) scoped to your credential. Mandatory on both USSD endpoints in Sandbox (UAT) and Production alike — a request without one is rejected with 400. Retrying with the same key replays the stored response verbatim rather than re-running the operation.

The session and the customer’s menu choice.

Media typeapplication/json
object
sessionId
required

Unique session identifier.

string
Example
ussd_3278668b308502f3a562950fc8043028
choice
required

The customer’s menu choice, always sent as a string. May be a numeric key like “1” or a free-text search term like “Tesla”. Alphanumeric, 1–10 characters.

string
Example
1

USSD request processed. Two bodies share this status.

On the normal path message is "USSD request processed successfully". On an unexpected internal failure the session is moved to ERROR and message becomes "USSD request processed with error state"data is the SAME ProcessResponse shape either way, with currentState and menu.state set to "ERROR". Detect the error state on the payload, not on the status code.

Media typeapplication/json
object
message
required
string
data
required
object
data
required

The USSD process request response data.

object
sessionId
required

Unique session identifier.

string
currentState
required
string
menu
required

The menu structure with state, text, options, and end state flag.

object
state
required
string
text
required
string
options
required
Array<object>

A menu option with key, label, optional next state, and optional data.

object
key
required

The option key (e.g. “1”, “2”, or a search term).

string
label
required

The display label for the option.

string
nextState

The next state to transition to (some options, like “Next”, omit this).

string
action

An operation the option performs rather than a plain navigation. Mutually exclusive with nextState; most options carry neither. Today the only option that carries it is “Yes, cancel” in the CANCEL_REQUEST_CONFIRMATION menu.

string
data

Optional additional data associated with the option (e.g. stock information).

object
stockId
string
symbol
string
name
string
isEndState
required
boolean
ussdText
required
string
expiresAt
required
string format: date-time
Examples

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"
}
}

Request failed schema validation, the session is expired, the session is no longer active, or the mandatory X-Idempotency-Key header is missing.

Media typeapplication/json
One of:
object
error
string
details
Array<object>
object
field
string
message
string
Examples
{
"error": "Validation failed",
"details": [
{
"field": "choice",
"message": "Choice must be alphanumeric"
}
]
}

Missing, invalid, expired or revoked token; x-client-id missing or not matching the token; or the request signature / Content-Digest failed verification.

Media typeapplication/json
object
error
required
string
message
required
string
Example
{
"error": "Unauthorized",
"message": "Organization authentication token is required"
}

Either the session belongs to another organization, or the client IP is outside the credential’s allowlist.

Media typeapplication/json
object
error
required
string
message
required
string
Example
{
"error": "SESSION_FORBIDDEN",
"message": "Session does not belong to this organization"
}

No session with that sessionId

Media typeapplication/json
object
error
required
string
message
required
string
Example
{
"error": "SESSION_NOT_FOUND",
"message": "USSD session not found"
}

A request with this X-Idempotency-Key is still in progress

Media typeapplication/json
object
error
required
string
message
required
string
Example
{
"error": "Conflict",
"message": "A request with this X-Idempotency-Key is already in progress"
}

The X-Idempotency-Key was already used with a different body

Media typeapplication/json
object
error
required
string
message
required
string
Example
{
"error": "Unprocessable Entity",
"message": "X-Idempotency-Key was already used with a different request payload"
}

Rate limit exceeded

Media typeapplication/json
object
error
required
string
message
required
string
Example
{
"error": "Too Many Requests",
"message": "Too many requests. Please slow down and try again shortly."
}