Introduction
The Infinexpay Payment Gateway API lets you collect M-Pesa STK Push payments, run card and crypto checkouts, and send payouts, all from a consistent JSON interface. This page covers configuration, request/response shapes, and a live sandbox for each endpoint.
Base URL
Every endpoint below is relative to:
https://infinexpay.co.ke/api/v2/Response format
Every response is JSON with a consistent top-level shape:
{
"success": true|false,
"message": "Descriptive message"
// additional fields depend on the endpoint
}
Authentication
Every request is authenticated with an API key/secret pair, sent as headers. Generate and rotate these from your merchant dashboard — never expose the secret in client-side code.
X-API-Key: your_api_key X-API-Secret: your_api_secret Content-Type: application/json
Keep secrets server-side
Route all API calls through your backend. If a key is ever exposed publicly, rotate it immediately from the dashboard.
Initiate your first payment
- Create an account on the Infinexpay dashboard.
- Generate an API key and secret.
- Set up at least one payment account.
function initiatePayment($apiKey, $apiSecret, $paymentAccountId, $phone, $amount, $reference, $description) { $url = "https://infinexpay.co.ke/api/v2/stkpush.php"; $data = [ 'payment_account_id' => $paymentAccountId, 'phone' => $phone, 'amount' => $amount, 'reference' => $reference, 'description' => $description ]; $ch = curl_init($url); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'X-API-Key: ' . $apiKey, 'X-API-Secret: ' . $apiSecret, 'Content-Type: application/json' ]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); $response = curl_exec($ch); curl_close($ch); return json_decode($response, true); } $result = initiatePayment("your_api_key", "your_api_secret", 14, "254712345678", 100, "ORDER123", "Test payment"); if ($result['success']) { echo "Checkout Request ID: " . $result['checkout_request_id']; } else { echo "Error: " . $result['message']; }
Endpoints
Six endpoints cover the full money-movement lifecycle: collect via STK Push, check status, list history, top up your wallet, pay customers out, and accept stablecoin deposits.
Prompts a customer's phone with an M-Pesa STK Push dialog for the given amount.
/stkpush.php| Parameter | Type | Required | Description |
|---|---|---|---|
payment_account_id | Integer | Yes | Your payment account ID |
phone | String | Yes | Customer number, e.g. 254712345678 |
amount | Float | Yes | Payment amount, minimum 1 KES |
reference | String | No | Your internal reference for the transaction |
description | String | No | Description shown in your records |
{
"success": true,
"message": "STK push sent successfully",
"checkout_request_id": "ws_CO_20260101120000_abc123",
"merchant_request_id": "ws_MR_20260101120000_xyz789"
}
Checks the status of a payment using the checkout_request_id returned from STK Push.
/status.php| Parameter | Type | Required | Description |
|---|---|---|---|
checkout_request_id | String | Yes | ID returned by the STK Push response |
{
"success": true,
"status": "completed",
"amount": 100,
"phone": "254712345678",
"transaction_code": "ABC123DEF456",
"created_at": "2026-01-01 12:00:00"
}
Status values
pending initiated, awaiting PIN entry · completed funds received · failed cancelled or timed out
Returns a paginated list of your transactions.
/transactions.php?page=1&limit=10| Parameter | Type | Required | Description |
|---|---|---|---|
page | Integer | No | Page number · default 1 |
limit | Integer | No | Items per page · max 100, default 10 |
{
"success": true,
"data": [
{
"id": 123,
"amount": 100,
"status": "completed",
"phone": "254712345678",
"transaction_code": "ABC123DEF456",
"fee_amount": 1.5,
"type": "API",
"created_at": "2026-01-01 12:00:00",
"completed_at": "2026-01-01 12:02:30"
}
],
"pagination": {
"current_page": 1,
"per_page": 10,
"total_items": 150,
"total_pages": 15
}
}
Deposits funds into your Infinexpay service wallet via STK Push. A processing fee is deducted from your service balance for each transaction.
/topup.php| Parameter | Type | Required | Description |
|---|---|---|---|
phone | String | Yes | Number to receive the STK Push prompt |
amount | Float | Yes | Deposit amount in KES, must be > 0 |
Response modes
If the customer enters their PIN within a few seconds the response resolves synchronously; otherwise it falls back to pending until the carrier callback arrives.
{
"success": true,
"status": "completed",
"transaction_id": "QGR45TX79K",
"amount_added": 100.00,
"fee_deducted": 6.00
}
{
"success": true,
"status": "pending",
"checkout_request_id": "ws_CO_18052026023512345678"
}
Insufficient service balance
If your service balance can't cover the processing fee, the request fails with success: false and a message telling you the top-up amount needed.
Sends a Business-to-Customer (B2C) disbursement from your service wallet to any M-Pesa number.
/payout.php| Parameter | Type | Required | Description |
|---|---|---|---|
phone | String | Yes | Recipient number, e.g. 254712345678 |
amount | Float | Yes | Amount to disburse · minimum 25.00 KES |
reference | String | No | Your unique ID for tracking the payout |
import requests url = "https://infinexpay.co.ke/api/v2/payout.php" headers = { "X-API-Key": "your_api_key", "X-API-Secret": "your_api_secret", "Content-Type": "application/json" } data = { "phone": "254712345678", "amount": 150.0, "reference": "PY_REF_101" } response = requests.post(url, json=data, headers=headers) print(response.json())
{
"success": true,
"message": "Payout successful",
"transaction_id": "OP_PAY_881272",
"amount_sent": 142.50,
"fee_deducted": 7.50
}
Accepts USDT deposits and settles the KES-equivalent value into your service wallet automatically.
/crypto_deposit.php| Parameter | Type | Required | Description |
|---|---|---|---|
amount | Float | Yes | Deposit amount in USD |
order_id | String | Yes | Unique identifier for this deposit |
{
"success": true,
"checkout_url": "https://infinexpay.co.ke/checkout/crypto/secure_frame"
}
Network restriction
This endpoint only supports USDT on the TRON network (TRC20). Deposits sent via Ethereum (ERC20) or BSC (BEP20) cannot be recovered.
Webhooks
Once a payout or deposit settles, Infinexpay posts the result to the webhook URL configured in your dashboard.
{
"status": "success",
"transaction_id": "OP_PAY_881272",
"mpesa_receipt": "RBC9982XX",
"amount": 150.00,
"phone": "254712345678",
"reference": "ORDER_9921",
"timestamp": "2026-03-20 10:15:00"
}
$input = file_get_contents('php://input'); $data = json_decode($input, true); if (isset($data['status']) && $data['status'] === 'success') { // mark the matching $data['reference'] as paid in your database http_response_code(200); echo json_encode(["message" => "Acknowledged"]); }
Error handling
Standard HTTP status codes indicate success or failure.
| Code | Meaning |
|---|---|
200 | Success |
400 | Bad request · invalid parameters |
401 | Unauthorized · invalid API credentials |
404 | Not found · resource doesn't exist |
405 | Method not allowed |
500 | Internal server error |
Common error messages
Insufficient service balance— top up your account to cover transaction feesInvalid payment account ID— check the ID you passedTransaction not found— thecheckout_request_iddoesn't existMissing required parameter— a required field wasn't sent
Live sandbox
Test STK Push, status checks, and transaction listing against your own credentials, right from this page.
Support
Need a hand integrating? Reach out and we'll help you get unstuck.
- Documentation: https://infinexpay.co.ke/api-doc.php