High-performance Mobile Money & Card payment gateway engine for Zambia (MTN Mobile Money, Airtel Money, Zamtel Kwacha, and Card Checkout).
Welcome to the StataPay Engine API Documentation (https://api.statapay.com).
The StataPay Engine processes mobile money and card payments for Zambia. Merchants create and manage wallets in the StataPay portal. The portal communicates with the engine over private internal endpoints.
Use the wallet's sec_live_... or sec_test_... API secret as a Bearer token for merchant payment requests. Internal portal credentials are not used by merchant integrations.
To authenticate requests, include an Authorization header with the value "Bearer sec_live_... or sec_test_...".
All authenticated endpoints are marked with a requires authentication badge in the documentation below.
Pass your merchant API key in the Authorization: Bearer <API_KEY> request header. The key can be retrieved from your StataPay Merchant Dashboard.
Retrieve the real-time available and pending balance breakdown for all wallets belonging to the authenticated merchant, along with the calculated aggregate totals.
Optional environment filter (sandbox or live). Defaults to the environment of your API key.
curl --request GET \
--get "https://api.statapay.com/api/v1/balance?environment=sandbox" \
--header "Authorization: Bearer sec_live_... or sec_test_..." \
--header "Content-Type: application/json" \
--header "Accept: application/json" {
"status": "success",
"data": {
"client_id": 1,
"merchant_name": "Acme Retail Zambia",
"environment": "sandbox",
"currency": "ZMW",
"total_available_balance": "1470.00",
"total_pending_balance": "0.00",
"total_balance": "1470.00",
"wallets_count": 2,
"wallets": [
{
"wallet_id": "wlt_test_01jc2x8k9m4p5q6r7s8t9v0w1x",
"name": "Main Store Wallet",
"environment": "sandbox",
"currency": "ZMW",
"status": "active",
"available_balance": "1000.00",
"pending_balance": "0.00",
"total_balance": "1000.00",
"is_current_wallet": true,
"created_at": "2026-11-06T10:00:00.000000Z"
},
{
"wallet_id": "wlt_test_01jc2x9y8b7c6d5e4f3g2h1j0k",
"name": "Secondary Sandbox Wallet",
"environment": "sandbox",
"currency": "ZMW",
"status": "active",
"available_balance": "470.00",
"pending_balance": "0.00",
"total_balance": "470.00",
"is_current_wallet": false,
"created_at": "2026-11-06T10:05:00.000000Z"
}
]
}
}
Retrieve the real-time available and pending balance breakdown for all wallets belonging to the authenticated merchant, along with the calculated aggregate totals.
Optional environment filter (sandbox or live). Defaults to the environment of your API key.
curl --request GET \
--get "https://api.statapay.com/api/v1/wallets/balance?environment=sandbox" \
--header "Authorization: Bearer sec_live_... or sec_test_..." \
--header "Content-Type: application/json" \
--header "Accept: application/json" {
"status": "success",
"data": {
"client_id": 1,
"merchant_name": "Acme Retail Zambia",
"environment": "sandbox",
"currency": "ZMW",
"total_available_balance": "1470.00",
"total_pending_balance": "0.00",
"total_balance": "1470.00",
"wallets_count": 2,
"wallets": [
{
"wallet_id": "wlt_test_01jc2x8k9m4p5q6r7s8t9v0w1x",
"name": "Main Store Wallet",
"environment": "sandbox",
"currency": "ZMW",
"status": "active",
"available_balance": "1000.00",
"pending_balance": "0.00",
"total_balance": "1000.00",
"is_current_wallet": true,
"created_at": "2026-11-06T10:00:00.000000Z"
},
{
"wallet_id": "wlt_test_01jc2x9y8b7c6d5e4f3g2h1j0k",
"name": "Secondary Sandbox Wallet",
"environment": "sandbox",
"currency": "ZMW",
"status": "active",
"available_balance": "470.00",
"pending_balance": "0.00",
"total_balance": "470.00",
"is_current_wallet": false,
"created_at": "2026-11-06T10:05:00.000000Z"
}
]
}
}
APIs for initiating incoming payments via Mobile Money (MTN MoMo, Airtel Money, Zamtel Kwacha) and Card checkout.
Request a payment from a customer. For mobile money rails (MTN, Airtel, Zamtel),
a USSD prompt will be sent directly to the customer's phone to approve the payment.
For card payments, a hosted checkout URL is returned in redirect_url.
curl --request POST \
"https://api.statapay.com/api/v1/collections" \
--header "Authorization: Bearer sec_live_... or sec_test_..." \
--header "Idempotency-Key: string required Unique client-generated key (up to 128 chars) to prevent duplicate charges. Example: order-1042-uuid" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"rail\": \"mtn\",
\"amount\": 150,
\"currency\": \"ZMW\",
\"msisdn\": \"0961234567\",
\"reference\": \"ORD-987654\",
\"description\": \"Order #987654 Payment\",
\"return_url\": \"https:\\/\\/merchant.example.com\\/checkout\\/return\",
\"webhook_url\": \"https:\\/\\/merchant.example.com\\/api\\/webhooks\\/statapay\",
\"customer\": {
\"name\": \"b\",
\"email\": \"zbailey@example.net\",
\"phone\": \"i\"
}
}"
{
"data": {
"id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
"reference": "ORD-987654",
"rail": "mtn",
"direction": "collection",
"status": "pending",
"amount": "150.00",
"currency": "ZMW",
"msisdn": "260961234567",
"provider_reference": "5c1f2a3e-7b9d-4c8e-9f10-112233445566",
"failure_reason": null,
"redirect_url": null,
"metadata": {
"cart_id": "c-88"
},
"created_at": "2026-11-06T08:00:00+02:00",
"submitted_at": "2026-11-06T08:00:01+02:00",
"completed_at": null
}
}
APIs for sending outbound payouts and transfers directly to mobile money subscribers.
Transfer funds directly to a recipient mobile money wallet (MTN or Airtel).
curl --request POST \
"https://api.statapay.com/api/v1/disbursements" \
--header "Authorization: Bearer sec_live_... or sec_test_..." \
--header "Idempotency-Key: string required Unique client-generated key (up to 128 chars) to prevent duplicate payouts. Example: payout-2049-uuid" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"rail\": \"mtn\",
\"amount\": 75,
\"currency\": \"ZMW\",
\"msisdn\": \"0961234567\",
\"reference\": \"PAYOUT-2049\",
\"description\": \"Vendor Settlement #2049\",
\"webhook_url\": \"https:\\/\\/merchant.example.com\\/api\\/webhooks\\/statapay\",
\"customer\": {
\"name\": \"b\",
\"email\": \"zbailey@example.net\",
\"phone\": \"i\"
}
}"
{
"data": {
"id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
"reference": "PAYOUT-2049",
"rail": "mtn",
"direction": "disbursement",
"status": "pending",
"amount": "75.00",
"currency": "ZMW",
"msisdn": "260961234567",
"provider_reference": "9c1f2a3e-7b9d-4c8e-9f10-112233445566",
"failure_reason": null,
"redirect_url": null,
"metadata": {
"vendor_id": "vnd_12"
},
"created_at": "2026-11-06T08:00:00+02:00",
"submitted_at": "2026-11-06T08:00:01+02:00",
"completed_at": null
}
}
Transfer funds to multiple mobile money subscribers simultaneously (e.g. for payroll, bulk refunds, supplier payouts). Up to 100 payouts can be submitted in a single request. The entire batch is balance-checked upfront before execution.
curl --request POST \
"https://api.statapay.com/api/v1/disbursements/batch" \
--header "Authorization: Bearer sec_live_... or sec_test_..." \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"batch_reference\": \"PAYROLL-NOV-2026\",
\"payouts\": [
\"architecto\"
],
\"webhook_url\": \"http:\\/\\/www.bailey.biz\\/quos-velit-et-fugiat-sunt-nihil-accusantium-harum.html\"
}"
Query transaction history, status, and details for collections and disbursements.
Retrieve a paginated list of transactions with optional filtering by status, rail, direction, and date range.
Filter by status (pending, successful, failed, expired, cancelled).
Filter by payment rail (mtn, airtel, zamtel, cards).
Filter by direction (collection or disbursement).
Filter by exact merchant reference.
Number of results per page (1 to 100). Default: 20.
curl --request GET \
--get "https://api.statapay.com/api/v1/transactions?status=successful&rail=mtn&direction=collection&reference=ORD-987654&per_page=20" \
--header "Authorization: Bearer sec_live_... or sec_test_..." \
--header "Content-Type: application/json" \
--header "Accept: application/json" cache-control: no-cache, private
content-type: application/json
x-ratelimit-limit: 30
x-ratelimit-remaining: 29
access-control-allow-origin: *
{
"message": "A valid API key is required."
}
Fetch complete details of any transaction by its public ID (01ARZ...).
The ID of the transaction.
The public transaction ID.
curl --request GET \
--get "https://api.statapay.com/api/v1/transactions/architecto" \
--header "Authorization: Bearer sec_live_... or sec_test_..." \
--header "Content-Type: application/json" \
--header "Accept: application/json" cache-control: no-cache, private
content-type: application/json
x-ratelimit-limit: 30
x-ratelimit-remaining: 28
access-control-allow-origin: *
{
"message": "A valid API key is required."
}
Check the real-time status of a collection transaction by its public ID (01ARZ...).
The public transaction ID (ULID starting with 01...).
curl --request GET \
--get "https://api.statapay.com/api/v1/collections/01ARZ3NDEKTSV4RRFFQ69G5FAV/status" \
--header "Authorization: Bearer sec_live_... or sec_test_..." \
--header "Content-Type: application/json" \
--header "Accept: application/json" {
"data": {
"id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
"reference": "ORD-987654",
"rail": "mtn",
"direction": "collection",
"status": "successful",
"is_final": true,
"is_successful": true,
"amount": "150.00",
"currency": "ZMW",
"failure_reason": null,
"redirect_url": null,
"updated_at": "2026-11-06T08:01:12+02:00",
"completed_at": "2026-11-06T08:01:12+02:00"
}
}
Check the real-time status of a payout transaction by its public ID (01ARZ...).
The public transaction ID (ULID starting with 01...).
curl --request GET \
--get "https://api.statapay.com/api/v1/disbursements/01ARZ3NDEKTSV4RRFFQ69G5FAV/status" \
--header "Authorization: Bearer sec_live_... or sec_test_..." \
--header "Content-Type: application/json" \
--header "Accept: application/json" {
"data": {
"id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
"reference": "PAYOUT-2049",
"rail": "mtn",
"direction": "disbursement",
"status": "successful",
"is_final": true,
"is_successful": true,
"amount": "75.00",
"currency": "ZMW",
"failure_reason": null,
"redirect_url": null,
"updated_at": "2026-11-06T08:01:12+02:00",
"completed_at": "2026-11-06T08:01:12+02:00"
}
}
KYC lookup tools to verify subscriber name and account status before charging or paying.
Queries the telecom network to resolve the official registered name and account validity for a mobile subscriber.
Supported rails: mtn, airtel.
Mobile network rail (mtn or airtel).
Subscriber phone number (096... or 26096...).
curl --request GET \
--get "https://api.statapay.com/api/v1/lookups/mobile-account?rail=mtn&msisdn=0961234567" \
--header "Authorization: Bearer sec_live_... or sec_test_..." \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"rail\": \"mtn\",
\"msisdn\": \"bngzmiyvdljnikhw\"
}"
{
"data": {
"rail": "mtn",
"msisdn": "260961234567",
"found": true,
"name": "Jane Doe",
"first_name": "Jane",
"last_name": "Doe"
}
}
Engine health monitoring.
Check if the API engine and database connectivity are healthy and operational.
curl --request GET \
--get "https://api.statapay.com/api/v1/health" \
--header "Content-Type: application/json" \
--header "Accept: application/json" {
"status": "ok",
"service": "statpay-engine",
"checks": {
"database": "ok"
},
"time": "2026-11-06T08:00:00+02:00"
}
APIs for reversing and refunding completed collections back to customer mobile wallets.
Reverse or refund an earlier completed collection. Supports both full and partial refunds. The refund amount will be debited from the merchant's wallet and transferred back to the customer.
The public ID of the collection to refund (01ARZ...).
curl --request POST \
"https://api.statapay.com/api/v1/collections/01ARZ3NDEKTSV4RRFFQ69G5FAV/refund" \
--header "Authorization: Bearer sec_live_... or sec_test_..." \
--header "Idempotency-Key: string required Unique client-generated key (up to 128 chars) to prevent duplicate refunds." \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"collection_id\": \"01ARZ3NDEKTSV4RRFFQ69G5FAV\",
\"amount\": 150,
\"reference\": \"REF-ORD-987654\",
\"reason\": \"Customer cancelled order.\"
}"
Reverse or refund an earlier completed collection. Supports both full and partial refunds. The refund amount will be debited from the merchant's wallet and transferred back to the customer.
The public ID of the collection to refund (01ARZ...).
curl --request POST \
"https://api.statapay.com/api/v1/refunds" \
--header "Authorization: Bearer sec_live_... or sec_test_..." \
--header "Idempotency-Key: string required Unique client-generated key (up to 128 chars) to prevent duplicate refunds." \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"collection_id\": \"01ARZ3NDEKTSV4RRFFQ69G5FAV\",
\"amount\": 150,
\"reference\": \"REF-ORD-987654\",
\"reason\": \"Customer cancelled order.\"
}"
Developer utilities to fund test wallets and simulate transaction outcomes without real money or telecom network dependencies.
Add virtual test balance to a sandbox wallet to test disbursements and balance queries.
The wallet ID.
curl --request POST \
"https://api.statapay.com/api/v1/sandbox/wallets/wlt_test_01jc2x8k9m4p5q6r7s8t9v0w1x/top-up" \
--header "Authorization: Bearer sec_test_..." \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"amount\": 5000
}"
Manually trigger an approval, decline, or timeout for any pending sandbox transaction.
curl --request POST \
"https://api.statapay.com/api/v1/sandbox/simulate/callback" \
--header "Authorization: Bearer sec_test_..." \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"transaction_id\": \"01ARZ3NDEKTSV4RRFFQ69G5FAV\",
\"action\": \"approve\"
}"
APIs to monitor outbound webhook deliveries, inspect delivery logs, and request event redeliveries.
Retrieve paginated history of outbound webhook dispatch attempts, HTTP status codes, and payload delivery states.
Filter by delivery status (succeeded, failed, retrying, pending).
Filter by event type (transaction.successful, etc.).
Filter by transaction public ID.
Items per page (1 to 100). Default: 20.
curl --request GET \
--get "https://api.statapay.com/api/v1/webhooks/deliveries?status=failed&event=transaction.successful&transaction_id=01ARZ3NDEKTSV4RRFFQ69G5FAV&per_page=20" \
--header "Authorization: Bearer sec_live_... or sec_test_..." \
--header "Content-Type: application/json" \
--header "Accept: application/json" cache-control: no-cache, private
content-type: application/json
x-ratelimit-limit: 30
x-ratelimit-remaining: 27
access-control-allow-origin: *
{
"message": "A valid API key is required."
}
Re-trigger and dispatch an outbound webhook for any completed transaction. Useful when a merchant endpoint was temporarily unreachable or returning HTTP 500 errors.
The transaction public ID (01ARZ...) or reference.
curl --request POST \
"https://api.statapay.com/api/v1/webhooks/resend" \
--header "Authorization: Bearer sec_live_... or sec_test_..." \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"transaction_id\": \"01ARZ3NDEKTSV4RRFFQ69G5FAV\"
}"
Re-trigger and dispatch an outbound webhook for any completed transaction. Useful when a merchant endpoint was temporarily unreachable or returning HTTP 500 errors.
The transaction public ID (01ARZ...) or reference.
curl --request POST \
"https://api.statapay.com/api/v1/transactions/01ARZ3NDEKTSV4RRFFQ69G5FAV/webhooks/resend" \
--header "Authorization: Bearer sec_live_... or sec_test_..." \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"transaction_id\": \"01ARZ3NDEKTSV4RRFFQ69G5FAV\"
}"