USSD purchase API
The WIG (Wallet Initiation Gateway) endpoints for USSD-driven payments, balance queries, and card lookups.
The WIG (Wallet Initiation Gateway) API is the set of endpoints your USSD application calls to initiate payments and balance checks from a USSD session. These endpoints are grouped under /purchase/network/* and tagged WIG API in the OpenAPI reference.
For the high-level integration overview, when-to-use, and customer flow, see USSD payment. This page is the endpoint reference.
Authentication and base URL
| Value | |
|---|---|
| Sandbox | https://qa.scantopay.io/pluto |
| Production | https://scantopay.live/pluto |
| Auth | Basic Auth or JWT Bearer, EXTERNAL role |
| Content-Type | application/json |
Full auth setup is on Authentication.
Endpoint summary
| Operation | Method | Path | Use when |
|---|---|---|---|
| Network code purchase — auto network | POST | /purchase/network/code | Customer pays an existing Scan to Pay code via USSD; let the platform detect the customer's network from MSISDN |
| Network code purchase — specified network | POST | /purchase/network/{network}/code | Same as above but you already know which mobile network operator handles the customer |
| Network purchase — auto network | POST | /purchase/network | Direct purchase (e.g. airtime) without a pre-existing code; auto-detect network |
| Network purchase — specified network | POST | /purchase/network/{network} | Direct purchase with explicit network |
| Network balance — auto network | POST | /purchase/network/balance | Customer's wallet balance check; auto-detect network |
| Network balance — specified network | POST | /purchase/network/{network}/balance | Balance check with explicit network |
| Card lookup | GET | /purchase/network/cards | List the cards the customer has linked to their MSISDN — used to populate "which card?" menu in your USSD app |
| Strike purchase | POST | /purchase/strike | Re-attempt a previous transaction using its originalTxId (failure-recovery pattern) |
Auto-detect vs network-specified — pick one
The Harbour-suffixed endpoints (auto-detect) determine the customer's network from the supplied MSISDN. Use these when:
- You don't already know the customer's network operator
- You're operating through a USSD aggregator that doesn't surface the network identity to your application
The {network}-path endpoints take an explicit network value (e.g. MTN, VODACOM, CELLC, TELKOM). Use these when:
- You already have the network identity from your USSD gateway integration
- You're routing through a network-specific USSD short code
- You want to fail fast if the customer is on an unexpected network
Both end in the same TxState machine — the difference is purely in routing.
Two payment patterns
Pattern A — Pay an existing code
Your backend has already created a Scan to Pay code (via the standard POST /code/create — see Dynamic QR). The customer's USSD session quotes that code and the API initiates payment.
curl -X POST "https://qa.scantopay.io/pluto/purchase/network/code" \
-u "$USERNAME:$PASSWORD" \
-H 'Content-Type: application/json' \
-d '{
"msisdn": "27831234567",
"code": "0123456789"
}'The platform looks up the code, pushes a PIN-entry request to the customer's phone, processes the resulting authorisation, and ends with the standard webhook.
Pattern B — Direct network purchase
For airtime, data bundles, or other immediate-fulfilment products where you don't want to round-trip through /code/create first, call the network purchase endpoint directly with the basket details.
curl -X POST "https://qa.scantopay.io/pluto/purchase/network/MTN" \
-u "$USERNAME:$PASSWORD" \
-H 'Content-Type: application/json' \
-d '{
"msisdn": "27831234567",
"amount": 50.00,
"merchantReference": "topup-2025-05-14-00037",
"cartItems": [
{
"description": "R50 airtime",
"quantity": "1",
"value": 50.00,
"destination": "27831234567",
"itemType": "AIRTIME"
}
]
}'The cartItems array enables the platform's limit-checking machinery — see the airtime / airtime-bundle limits in the QR Code Payments business rules.
Card lookup
Before triggering a purchase, your USSD app often needs to ask the customer "which card?" — present the list of cards they've linked to their MSISDN.
curl -X GET "https://qa.scantopay.io/pluto/purchase/network/cards?msisdn=27831234567" \
-u "$USERNAME:$PASSWORD"Response includes the customer's linked cards with masked BIN + last 4 (no full PAN ever crosses the wire). Use the returned card IDs to drive your USSD menu, and pass the chosen card on the subsequent purchase call.
Balance check
Provides the customer's wallet balance — useful for "how much do I have left?" menus before initiating a purchase.
curl -X POST "https://qa.scantopay.io/pluto/purchase/network/balance" \
-u "$USERNAME:$PASSWORD" \
-H 'Content-Type: application/json' \
-d '{
"msisdn": "27831234567"
}'Strike purchase
A strike re-runs a previously-failed transaction. Use it to recover from transient failures (network blip, bank timeout) by replaying against the same originalTxId rather than creating a new transaction from scratch.
curl -X POST "https://qa.scantopay.io/pluto/purchase/strike" \
-u "$USERNAME:$PASSWORD" \
-H 'Content-Type: application/json' \
-d '{
"originalTxId": 81234,
"msisdn": "27831234567"
}'The platform retains the original transaction's amount, merchant reference, and basket; only the underlying card auth attempt is re-run. The webhook fires with the new TxState as if it were a fresh attempt.
What you get back
Every USSD payment ends in the same TransactionNotificationV3 webhook payload your other channels produce. The status field uses the NotificationStatus enum, mapping from the richer USSD-specific timeout TxState values (e.g. END_TIMEOUT_PURCHASE → TIMEOUT_PURCHASE). See Webhooks and Transaction states.
Errors specific to USSD
| Code | Meaning |
|---|---|
433 INVALID_NETWORK | The network in the path (or auto-detected) isn't recognised. Common with unusual MNOs. |
434 CLIENT_SUSPENDED | The customer's account is suspended. |
465 MISSING_MSISDN | MSISDN required but not provided. |
468 WIG_CNP_PURCHASE_FAIL_CARD_EXPIRY_BIN_NOT_WHIELIST | USSD CNP purchase failed: card expiry or BIN not whitelisted. |
469 WIG_3DS_PURCHASE_FAIL_CARD_EXPIRY_BIN_NOT_WHIELIST | USSD 3DS purchase failed: same reasons. |
Plus all the generic 4xx codes from Errors.
STK API — for MNO partners only
A separate endpoint group at /stk/* is reserved for Mobile Network Operator partners doing direct integration. It requires the STK role rather than EXTERNAL and isn't relevant for most merchants or PSPs. Endpoints include /stk/code, /stk/cards/list, /stk/cards/link, /stk/cards/delink, /stk/cards/binInfo, /stk/purchase, /stk/balance.
If you're an MNO and need access, contact [email protected].
What's next
- Customer-flow overview → USSD payment
- Standard code-create endpoint (for Pattern A) → Dynamic QR
- Receive the payment notification → Webhooks
- Airtime / data limit rules → QR Code Payments — business rules
- Full OpenAPI reference for the WIG endpoints → API Reference (auto-rendered)
Updated 3 days ago
