Before you start
- Node.js 20 or later
- pnpm (
npm install -g pnpm) - PostgreSQL 14 or later
- A telecom gateway account (such as Africa's Talking) for live USSD testing
- Docker — required only for integration tests
What this guide does
This guide walks you through forking the IXO USSD gateway, configuring it for your environment, and running it against a telecom gateway. At the end you will have a working USSD server that can accept real or simulated sessions and write results to IXO Protocol.
The gateway is designed to be forked. You define your own USSD flows as XState v5 state machines. The core session management, database layer, and IXO service integrations come pre-built.
Step 1 — Fork and clone the repository
Fork ixoworld/ixo-ussd on GitHub, then clone your fork and install dependencies.
git clone https://github.com/YOUR_USERNAME/ixo-ussd.git
cd ixo-ussd
pnpm installStep 2 — Configure environment variables
Copy the example environment file and edit it with your values.
cp env.example .envRequired variables
DATABASE_URL
- Description: PostgreSQL connection string
- Example:
postgres://user:pass@localhost:5432/ixo-ussd-dev
PIN_ENCRYPTION_KEY
- Description: 32-character key for PIN encryption
- Example: generate with
openssl rand -hex 16
LOG_LEVEL
- Description: Logging verbosity
- Example:
debug,info,warn,error
Optional variables
NODE_ENV
- Default:
development - Description: Environment mode
PORT
- Default:
3000 - Description: Server port
ZM_SERVICE_CODES
- Default:
*1234# - Description: USSD service codes, comma-separated
IXO_API_URL
- Default:
https://api.ixo.world - Description: IXO API endpoint
IXO_BLOCKCHAIN_URL
- Default:
https://rpc.ixo.world - Description: IXO blockchain RPC
To target the IXO testnet instead of mainnet, set IXO_API_URL and IXO_BLOCKCHAIN_URL to the testnet rows from Networks and endpoints.
Step 3 — Set up the database and start the server
Create a PostgreSQL database, run migrations, then start the development server.
# Build the project
pnpm build
# Run database migrations
node dist/src/migrations/run-migrations.js
# Start the development server
pnpm devThe server starts at http://localhost:3000 by default.
Step 4 — Connect a telecom gateway
Most telecom USSD gateways send HTTP POST requests with form-encoded or JSON body. The IXO USSD gateway expects JSON at POST /api/ussd.
For Africa's Talking, add a callback URL pointing to your server and adapt the request format:
// Convert Africa's Talking format and forward to the gateway
app.post('/ussd', async (req, res) => {
const response = await fetch('http://your-server/api/ussd', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sessionId: req.body.sessionId,
serviceCode: req.body.serviceCode,
phoneNumber: req.body.phoneNumber,
text: req.body.text || ''
})
});
const ussdResponse = await response.text();
res.type('text/plain').send(ussdResponse);
});See the USSD gateway API reference for the full request and response format.
Step 5 — Verify the result
Send a test request to confirm the server is accepting sessions.
curl -X POST http://localhost:3000/api/ussd \
-H "Content-Type: application/json" \
-d '{
"sessionId": "test-session-001",
"serviceCode": "*1234#",
"phoneNumber": "+260971234567",
"text": ""
}'A working server returns a CON response with the main menu text.
Check active sessions:
curl http://localhost:3000/api/ussd/sessionsCheck server health:
curl http://localhost:3000/healthTroubleshooting
Database connection failed
Confirm PostgreSQL is running and the DATABASE_URL in .env matches your setup.
# macOS
brew services start postgresql
# Ubuntu/Debian
sudo systemctl start postgresqlMissing PIN encryption key error
Generate a valid key and add it to .env:
echo "PIN_ENCRYPTION_KEY=$(openssl rand -hex 16)" >> .envIXO account does not exist on chain
New user accounts need a small token balance to cover gas fees before the gateway can write on-chain. Update your IXO feegrant configuration to cover gas for new accounts, or send a small amount to the generated address.
Migration failed
Ensure the database exists and the user has write permissions, then re-run:
pnpm build && node dist/src/migrations/run-migrations.jsNext steps
Review request/response formats, session endpoints, and error codes.
IXO USSD gateway architectureUnderstand the state machine design and integration model.
Architecture patterns guideBuild custom USSD flows with reusable architecture patterns.
(opens in a new tab)IXO networks and endpointsUse the right mainnet and testnet connection details.