Paywave Express API Documentation
Paywave Express provides a simple REST API to accept M-Pesa payments in Kenya. Integrate STK Push payments into your application with a few lines of code — we handle the Daraja complexity for you.
https://paywavexpress.co.ke
What You Can Do
- Initiate M-Pesa STK Push payments (Paybill, Till Number, Bank Account)
- Check transaction status in real-time
- Receive webhook notifications for completed/failed payments
- Use payment pages for non-developer users — no coding required
Authentication
Every API request requires two credentials:
| Parameter | Description |
|---|---|
api_key | Your unique API key from the Paywave Express dashboard. Found under your linked account settings. |
email | The email address registered on your Paywave Express account. |
api_key in client-side code. Always make API calls from your backend server.
Quick Start
-
1
Create an Account
Sign up at paywavexpress.co.ke and verify your email.
-
2
Link a Payment Account
Add your Till Number, Paybill, or Bank Account from the dashboard. You can link multiple accounts.
-
3
Activate Your Account
Subscribe (KES 400/month or KES 4,000/year) to activate your API key.
-
4
Make Your First API Call
Use the STK Push endpoint to initiate a payment. See code samples below.
STK Push - Initiate Payment
Trigger an M-Pesa STK Push prompt on the customer's phone. The customer enters their M-Pesa PIN to complete the payment.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
api_key | string | Required | Your Paywave Express API key |
email | string | Required | Your registered email address |
amount | string | Required | Amount in KES (minimum 1) |
msisdn | string | Required | Customer's phone number (e.g. 0712345678 or 254712345678) |
reference | string | Required | Payment reference / description |
account_number | string | Optional | Account number (required for Paybill accounts) |
✓ Success Response (200)
{
"ResponseCode": "0",
"success": "200",
"message": "Please enter your MPESA PIN to complete the transaction",
"transaction_request_id": "FCID20022026153045123456",
"MerchantRequestID": "29115-34620561-1",
"CheckoutRequestID": "ws_CO_123456789"
}
✗ Error Response
{
"ResultCode": "102",
"errorMessage": "Request is missing required api_key!"
}
Transaction Status
Check the status of a previously initiated transaction using the transaction_request_id returned from the STK Push response.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
api_key | string | Required | Your Paywave Express API key |
email | string | Required | Your registered email |
transaction_request_id | string | Required | Transaction ID from STK Push response |
✓ Success Response
{
"ResultCode": "200",
"ResultDesc": "Success",
"TransactionStatus": "Completed",
"TransactionReceipt": "SHJ7ABCDEF",
"TransactionAmount": "100.00",
"Msisdn": "254712345678",
"TransactionDate": "20260220153045",
"TransactionReference": "ORDER-001",
"CheckoutRequestID": "ws_CO_123456789",
"MerchantRequestID": "29115-34620561-1"
}
Pending, Completed, Failed, or Cancelled.
Webhooks (Callbacks)
Paywave Express sends real-time POST notifications to your configured webhook URL whenever a transaction is completed, failed, or cancelled. Configure your webhook URL in the dashboard under your account settings.
Webhook Payload
{
"ResponseCode": 0,
"ResponseDescription": "Success",
"MerchantRequestID": "29115-34620561-1",
"CheckoutRequestID": "ws_CO_123456789",
"TransactionID": "FCID20022026153045123456",
"TransactionAmount": 100,
"TransactionReceipt": "SHJ7ABCDEF",
"TransactionDate": "20260220153045",
"TransactionReference": "ORDER-001",
"Msisdn": "254712345678"
}
Webhook Handler Sample
// webhook.php - Handle Paywave Express webhook notifications $json = file_get_contents('php://input'); $data = json_decode($json, true); // Validate webhook data if (!$data || !isset($data['TransactionID'])) { http_response_code(400); echo "Invalid webhook data"; exit; } $responseCode = $data['ResponseCode']; $transactionId = $data['TransactionID']; $amount = $data['TransactionAmount']; $receipt = $data['TransactionReceipt']; $phone = $data['Msisdn']; $reference = $data['TransactionReference']; if ($responseCode == 0) { // Payment successful - update your database processSuccessfulPayment($transactionId, $amount, $receipt, $phone); http_response_code(200); echo json_encode(['status' => 'success']); } else { // Payment failed processFailedPayment($transactionId, $responseCode); http_response_code(200); echo json_encode(['status' => 'received']); }
Payment Pages (No-Code)
Don't want to write code? Paywave Express provides hosted payment pages for each linked account. Simply share the unique URL with your customers.
How Payment Pages Work
-
1
Link Your Account
Add your Till Number, Paybill, or Bank Account in the Paywave Express dashboard.
-
2
Get Your Payment URL
Each account gets a unique URL like:
https://paywavexpress.co.ke/pay/your-business-name -
3
Share With Customers
Send the link via SMS, WhatsApp, email, or embed it on your website. No login required for customers.
-
4
Customer Pays
Customer enters phone number, amount (and account number for Paybill), then receives the M-Pesa STK Push.
Account Types
| Account Type | Customer Fields | Description |
|---|---|---|
Till Number | Phone, Amount | Lipa Na M-Pesa Buy Goods. Customer enters phone and amount only. |
Paybill | Phone, Amount, Account Number | M-Pesa Paybill. Customer must also provide an account number. |
Bank Account | Phone, Amount | Payment via bank paybill. Account number is pre-configured by the account owner. |
PHP Sample
Initiate STK Push
<?php function makePayment($api_key, $email, $amount, $msisdn, $reference) { $payload = json_encode(compact('api_key', 'email', 'amount', 'msisdn', 'reference')); $ch = curl_init('https://paywavexpress.co.ke/v1/stkpush'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $payload, CURLOPT_HTTPHEADER => ['Content-Type: application/json'], ]); $response = curl_exec($ch); curl_close($ch); return json_decode($response, true); } $result = makePayment( 'your_api_key', 'your@email.com', '100', '0712345678', 'Order #001' ); print_r($result); ?>
Check Transaction Status
<?php function verifyPayment($api_key, $email, $transaction_request_id) { $payload = json_encode(compact('api_key', 'email', 'transaction_request_id')); $ch = curl_init('https://paywavexpress.co.ke/v1/tstatus'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $payload, CURLOPT_HTTPHEADER => ['Content-Type: application/json'], ]); $response = curl_exec($ch); curl_close($ch); return json_decode($response, true); } $result = verifyPayment( 'your_api_key', 'your@email.com', 'FCID20022026153045123456' ); print_r($result); ?>
Python Sample
import requests def make_payment(api_key, email, amount, msisdn, reference): payload = { "api_key": api_key, "email": email, "amount": amount, "msisdn": msisdn, "reference": reference } response = requests.post( "https://paywavexpress.co.ke/v1/stkpush", json=payload ) return response.json() def verify_payment(api_key, email, transaction_request_id): payload = { "api_key": api_key, "email": email, "transaction_request_id": transaction_request_id } response = requests.post( "https://paywavexpress.co.ke/v1/tstatus", json=payload ) return response.json() # Initiate payment result = make_payment( "your_api_key", "your@email.com", "100", "0712345678", "Order #001" ) print(result) # Check status status = verify_payment( "your_api_key", "your@email.com", result["transaction_request_id"] ) print(status)
Node.js Sample
const axios = require('axios'); async function makePayment(apiKey, email, amount, msisdn, reference) { const response = await axios.post('https://paywavexpress.co.ke/v1/stkpush', { api_key: apiKey, email: email, amount: amount, msisdn: msisdn, reference: reference }); return response.data; } async function verifyPayment(apiKey, email, transactionId) { const response = await axios.post('https://paywavexpress.co.ke/v1/tstatus', { api_key: apiKey, email: email, transaction_request_id: transactionId }); return response.data; } // Usage (async () => { const result = await makePayment( 'your_api_key', 'your@email.com', '100', '0712345678', 'Order #001' ); console.log(result); const status = await verifyPayment( 'your_api_key', 'your@email.com', result.transaction_request_id ); console.log(status); })();
JavaScript (Fetch) Sample
// Initiate STK Push async function makePayment() { const response = await fetch('https://paywavexpress.co.ke/v1/stkpush', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ api_key: 'your_api_key', email: 'your@email.com', amount: '100', msisdn: '0712345678', reference: 'Order #001' }) }); const data = await response.json(); console.log(data); return data; } // Check Transaction Status async function checkStatus(transactionId) { const response = await fetch('https://paywavexpress.co.ke/v1/tstatus', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ api_key: 'your_api_key', email: 'your@email.com', transaction_request_id: transactionId }) }); const data = await response.json(); console.log(data); }
cURL Sample
# Initiate STK Push curl -X POST https://paywavexpress.co.ke/v1/stkpush \ -H "Content-Type: application/json" \ -d '{ "api_key": "your_api_key", "email": "your@email.com", "amount": "100", "msisdn": "0712345678", "reference": "Order #001" }' # Check Transaction Status curl -X POST https://paywavexpress.co.ke/v1/tstatus \ -H "Content-Type: application/json" \ -d '{ "api_key": "your_api_key", "email": "your@email.com", "transaction_request_id": "FCID20022026153045123456" }'
Subscription & Pricing
Activate your Paywave Express account to start processing real payments.
Monthly
Yearly
Error Codes
| Code | Description |
|---|---|
0 | Success — transaction completed |
102 | Missing or invalid required parameter |
201 | Invalid HTTP method (use POST) |
400 | Account inactive or invalid account type |
503 | Server error / Safaricom API failure |
1 | Insufficient M-Pesa balance |
1032 | Transaction cancelled by user |
1037 | Timeout — user unreachable |
1025 | Push request error |
1001 | Transaction already in process |
2001 | Invalid initiator information |
© 2026 Paywave Express. All rights reserved.
Need help? support@paywavexpress.co.ke | WhatsApp