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.

Base URL: https://paywavexpress.co.ke

What You Can Do

Authentication

Every API request requires two credentials:

ParameterDescription
api_keyYour unique API key from the Paywave Express dashboard. Found under your linked account settings.
emailThe email address registered on your Paywave Express account.
Security: Never expose your api_key in client-side code. Always make API calls from your backend server.

Quick Start

  1. 1

    Create an Account

    Sign up at paywavexpress.co.ke and verify your email.

  2. 2

    Link a Payment Account

    Add your Till Number, Paybill, or Bank Account from the dashboard. You can link multiple accounts.

  3. 3

    Activate Your Account

    Subscribe (KES 400/month or KES 4,000/year) to activate your API key.

  4. 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.

POST https://paywavexpress.co.ke/v1/stkpush

Request Parameters

ParameterTypeRequiredDescription
api_keystringRequiredYour Paywave Express API key
emailstringRequiredYour registered email address
amountstringRequiredAmount in KES (minimum 1)
msisdnstringRequiredCustomer's phone number (e.g. 0712345678 or 254712345678)
referencestringRequiredPayment reference / description
account_numberstringOptionalAccount number (required for Paybill accounts)

✓ Success Response (200)

JSON
{
  "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

JSON
{
  "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.

POST https://paywavexpress.co.ke/v1/tstatus

Request Parameters

ParameterTypeRequiredDescription
api_keystringRequiredYour Paywave Express API key
emailstringRequiredYour registered email
transaction_request_idstringRequiredTransaction ID from STK Push response

✓ Success Response

JSON
{
  "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"
}
Tip: Transaction statuses are: 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

JSON
{
  "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

PHP
// 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. 1

    Link Your Account

    Add your Till Number, Paybill, or Bank Account in the Paywave Express dashboard.

  2. 2

    Get Your Payment URL

    Each account gets a unique URL like: https://paywavexpress.co.ke/pay/your-business-name

  3. 3

    Share With Customers

    Send the link via SMS, WhatsApp, email, or embed it on your website. No login required for customers.

  4. 4

    Customer Pays

    Customer enters phone number, amount (and account number for Paybill), then receives the M-Pesa STK Push.

Account Types

Account TypeCustomer FieldsDescription
Till NumberPhone, AmountLipa Na M-Pesa Buy Goods. Customer enters phone and amount only.
PaybillPhone, Amount, Account NumberM-Pesa Paybill. Customer must also provide an account number.
Bank AccountPhone, AmountPayment via bank paybill. Account number is pre-configured by the account owner.
Multiple Accounts: You can link several accounts (even different types) under one Paywave Express user. Each gets its own API key and payment page URL.

PHP Sample

Initiate STK Push

PHP
<?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
<?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

Python
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

JavaScript (Node.js)
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

JavaScript
// 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

cURL
# 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

KES 400
per month

Yearly

KES 4,000
per year (save KES 800)
Activation: Pay via M-Pesa from your dashboard. Your account activates instantly after payment confirmation.

Error Codes

CodeDescription
0Success — transaction completed
102Missing or invalid required parameter
201Invalid HTTP method (use POST)
400Account inactive or invalid account type
503Server error / Safaricom API failure
1Insufficient M-Pesa balance
1032Transaction cancelled by user
1037Timeout — user unreachable
1025Push request error
1001Transaction already in process
2001Invalid initiator information

© 2026 Paywave Express. All rights reserved.

Need help? support@paywavexpress.co.ke | WhatsApp