StataPay Engine API Documentation

Postman collection → OpenAPI spec →

Introduction

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.

Authenticating requests

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.

Wallets

Get Merchant Wallet Balances & Total

GET
https://api.statapay.com
/api/v1/balance
requires authentication

Retrieve the real-time available and pending balance breakdown for all wallets belonging to the authenticated merchant, along with the calculated aggregate totals.

Headers

Authorization
Example:
Bearer sec_live_... or sec_test_...
Content-Type
Example:
application/json
Accept
Example:
application/json

Query Parameters

environment
string

Optional environment filter (sandbox or live). Defaults to the environment of your API key.

Example:
sandbox
Example request:
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"
Example response:
{
    "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"
            }
        ]
    }
}

Get Merchant Wallet Balances & Total

GET
https://api.statapay.com
/api/v1/wallets/balance
requires authentication

Retrieve the real-time available and pending balance breakdown for all wallets belonging to the authenticated merchant, along with the calculated aggregate totals.

Headers

Authorization
Example:
Bearer sec_live_... or sec_test_...
Content-Type
Example:
application/json
Accept
Example:
application/json

Query Parameters

environment
string

Optional environment filter (sandbox or live). Defaults to the environment of your API key.

Example:
sandbox
Example request:
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"
Example response:
{
    "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"
            }
        ]
    }
}

Collections

APIs for initiating incoming payments via Mobile Money (MTN MoMo, Airtel Money, Zamtel Kwacha) and Card checkout.

Initiate a Collection (USSD Push / Card Session)

POST
https://api.statapay.com
/api/v1/collections
requires authentication

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.

Headers

Authorization
Example:
Bearer sec_live_... or sec_test_...
Idempotency-Key
Example:
string required Unique client-generated key (up to 128 chars) to prevent duplicate charges. Example: order-1042-uuid
Content-Type
Example:
application/json
Accept
Example:
application/json

Body Parameters

Example request:
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\"
    }
}"
Example response:
{
    "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
    }
}

Disbursements

APIs for sending outbound payouts and transfers directly to mobile money subscribers.

Initiate a Disbursement (Mobile Money Payout)

POST
https://api.statapay.com
/api/v1/disbursements
requires authentication

Transfer funds directly to a recipient mobile money wallet (MTN or Airtel).

Headers

Authorization
Example:
Bearer sec_live_... or sec_test_...
Idempotency-Key
Example:
string required Unique client-generated key (up to 128 chars) to prevent duplicate payouts. Example: payout-2049-uuid
Content-Type
Example:
application/json
Accept
Example:
application/json

Body Parameters

Example request:
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\"
    }
}"
Example response:
{
    "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
    }
}

Submit Batch Disbursements (Mass Payouts)

POST
https://api.statapay.com
/api/v1/disbursements/batch
requires authentication

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.

Headers

Authorization
Example:
Bearer sec_live_... or sec_test_...
Content-Type
Example:
application/json
Accept
Example:
application/json

Body Parameters

Example request:
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\"
}"

Transactions

Query transaction history, status, and details for collections and disbursements.

List Transactions

GET
https://api.statapay.com
/api/v1/transactions
requires authentication

Retrieve a paginated list of transactions with optional filtering by status, rail, direction, and date range.

Headers

Authorization
Example:
Bearer sec_live_... or sec_test_...
Content-Type
Example:
application/json
Accept
Example:
application/json

Query Parameters

status
string

Filter by status (pending, successful, failed, expired, cancelled).

Example:
successful
rail
string

Filter by payment rail (mtn, airtel, zamtel, cards).

Example:
mtn
direction
string

Filter by direction (collection or disbursement).

Example:
collection
reference
string

Filter by exact merchant reference.

Example:
ORD-987654
per_page
integer

Number of results per page (1 to 100). Default: 20.

Example:
20
Example request:
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"
Example response:
Headers
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."
}

Get Transaction Details

GET
https://api.statapay.com
/api/v1/transactions/{id}
requires authentication

Fetch complete details of any transaction by its public ID (01ARZ...).

Headers

Authorization
Example:
Bearer sec_live_... or sec_test_...
Content-Type
Example:
application/json
Accept
Example:
application/json

URL Parameters

id
string
required

The ID of the transaction.

Example:
architecto
transaction
string
required

The public transaction ID.

Example:
01ARZ3NDEKTSV4RRFFQ69G5FAV
Example request:
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"
Example response:
Headers
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."
}

Get Collection Status

GET
https://api.statapay.com
/api/v1/collections/{transaction}/status
requires authentication

Check the real-time status of a collection transaction by its public ID (01ARZ...).

Headers

Authorization
Example:
Bearer sec_live_... or sec_test_...
Content-Type
Example:
application/json
Accept
Example:
application/json

URL Parameters

transaction
string
required

The public transaction ID (ULID starting with 01...).

Example:
01ARZ3NDEKTSV4RRFFQ69G5FAV
Example request:
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"
Example response:
{
    "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"
    }
}

Get Disbursement Status

GET
https://api.statapay.com
/api/v1/disbursements/{transaction}/status
requires authentication

Check the real-time status of a payout transaction by its public ID (01ARZ...).

Headers

Authorization
Example:
Bearer sec_live_... or sec_test_...
Content-Type
Example:
application/json
Accept
Example:
application/json

URL Parameters

transaction
string
required

The public transaction ID (ULID starting with 01...).

Example:
01ARZ3NDEKTSV4RRFFQ69G5FAV
Example request:
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"
Example response:
{
    "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"
    }
}

Account Lookup

KYC lookup tools to verify subscriber name and account status before charging or paying.

Resolve Mobile Money Account Holder (KYC Name Lookup)

GET
https://api.statapay.com
/api/v1/lookups/mobile-account
requires authentication

Queries the telecom network to resolve the official registered name and account validity for a mobile subscriber. Supported rails: mtn, airtel.

Headers

Authorization
Example:
Bearer sec_live_... or sec_test_...
Content-Type
Example:
application/json
Accept
Example:
application/json

Query Parameters

rail
string
required

Mobile network rail (mtn or airtel).

Example:
mtn
msisdn
string
required

Subscriber phone number (096... or 26096...).

Example:
0961234567

Body Parameters

Example request:
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\"
}"
Example response:

System

Engine health monitoring.

Service Health Check

GET
https://api.statapay.com
/api/v1/health

Check if the API engine and database connectivity are healthy and operational.

Headers

Content-Type
Example:
application/json
Accept
Example:
application/json
Example request:
curl --request GET \
    --get "https://api.statapay.com/api/v1/health" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
Example response:
{
    "status": "ok",
    "service": "statpay-engine",
    "checks": {
        "database": "ok"
    },
    "time": "2026-11-06T08:00:00+02:00"
}

Refunds

APIs for reversing and refunding completed collections back to customer mobile wallets.

Initiate a Refund

POST
https://api.statapay.com
/api/v1/collections/{transaction}/refund
requires authentication

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.

Headers

Authorization
Example:
Bearer sec_live_... or sec_test_...
Idempotency-Key
Example:
string required Unique client-generated key (up to 128 chars) to prevent duplicate refunds.
Content-Type
Example:
application/json
Accept
Example:
application/json

URL Parameters

transaction
string

The public ID of the collection to refund (01ARZ...).

Example:
01ARZ3NDEKTSV4RRFFQ69G5FAV

Body Parameters

Example request:
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.\"
}"

Initiate a Refund

POST
https://api.statapay.com
/api/v1/refunds
requires authentication

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.

Headers

Authorization
Example:
Bearer sec_live_... or sec_test_...
Idempotency-Key
Example:
string required Unique client-generated key (up to 128 chars) to prevent duplicate refunds.
Content-Type
Example:
application/json
Accept
Example:
application/json

URL Parameters

transaction
string

The public ID of the collection to refund (01ARZ...).

Example:
01ARZ3NDEKTSV4RRFFQ69G5FAV

Body Parameters

Example request:
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.\"
}"

Sandbox Testing

Developer utilities to fund test wallets and simulate transaction outcomes without real money or telecom network dependencies.

Top-Up Sandbox Wallet

POST
https://api.statapay.com
/api/v1/sandbox/wallets/{wallet}/top-up
requires authentication

Add virtual test balance to a sandbox wallet to test disbursements and balance queries.

Headers

Authorization
Example:
Bearer sec_test_...
Content-Type
Example:
application/json
Accept
Example:
application/json

URL Parameters

wallet
string
required

The wallet ID.

Example:
wlt_test_01jc2x8k9m4p5q6r7s8t9v0w1x

Body Parameters

Example request:
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
}"

Simulate Transaction Callback

POST
https://api.statapay.com
/api/v1/sandbox/simulate/callback
requires authentication

Manually trigger an approval, decline, or timeout for any pending sandbox transaction.

Headers

Authorization
Example:
Bearer sec_test_...
Content-Type
Example:
application/json
Accept
Example:
application/json

Body Parameters

Example request:
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\"
}"

Webhooks

APIs to monitor outbound webhook deliveries, inspect delivery logs, and request event redeliveries.

List Webhook Deliveries

GET
https://api.statapay.com
/api/v1/webhooks/deliveries
requires authentication

Retrieve paginated history of outbound webhook dispatch attempts, HTTP status codes, and payload delivery states.

Headers

Authorization
Example:
Bearer sec_live_... or sec_test_...
Content-Type
Example:
application/json
Accept
Example:
application/json

Query Parameters

status
string

Filter by delivery status (succeeded, failed, retrying, pending).

Example:
failed
event
string

Filter by event type (transaction.successful, etc.).

Example:
transaction.successful
transaction_id
string

Filter by transaction public ID.

Example:
01ARZ3NDEKTSV4RRFFQ69G5FAV
per_page
integer

Items per page (1 to 100). Default: 20.

Example:
20
Example request:
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"
Example response:
Headers
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."
}

Resend Webhook

POST
https://api.statapay.com
/api/v1/webhooks/resend
requires authentication

Re-trigger and dispatch an outbound webhook for any completed transaction. Useful when a merchant endpoint was temporarily unreachable or returning HTTP 500 errors.

Headers

Authorization
Example:
Bearer sec_live_... or sec_test_...
Content-Type
Example:
application/json
Accept
Example:
application/json

URL Parameters

transaction
string

The transaction public ID (01ARZ...) or reference.

Example:
01ARZ3NDEKTSV4RRFFQ69G5FAV

Body Parameters

Example request:
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\"
}"

Resend Webhook

POST
https://api.statapay.com
/api/v1/transactions/{transaction}/webhooks/resend
requires authentication

Re-trigger and dispatch an outbound webhook for any completed transaction. Useful when a merchant endpoint was temporarily unreachable or returning HTTP 500 errors.

Headers

Authorization
Example:
Bearer sec_live_... or sec_test_...
Content-Type
Example:
application/json
Accept
Example:
application/json

URL Parameters

transaction
string

The transaction public ID (01ARZ...) or reference.

Example:
01ARZ3NDEKTSV4RRFFQ69G5FAV

Body Parameters

Example request:
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\"
}"