REST API · Version 1

API Documentation

Integrate M-Pesa STK Push payments into any website with a single API call.

Overview

The E-Payments API lets you initiate M-Pesa STK Push payments, query transaction status, and list transactions. All requests are authenticated via an API key in the X-API-Key header.

Base URLhttps://yourdomain.com/api/v1

STK Push

Trigger M-Pesa payments

Webhooks

Real-time event notifications

Sandbox

Test without going live

Authentication

Required

All /api/v1/* endpoints require an API key. Generate keys in your API Keys dashboard.

Include in every requestjavascript
fetch('https://yourapp.com/api/v1/payment', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'mpesa_test_xxxxxxxxxxxxxxxxxxxxxxxx'
  }
})

Sandbox keys

mpesa_test_...

Production keys

mpesa_live_...
Server-side only: your API key must never appear in browser JavaScript, a mobile app bundle, or any other client-side code — treat it like a password. Call /api/v1/* from your own backend, then have your backend talk to your frontend. A key leaked in client-side code can be used by anyone to trigger payments against your account.

Initiate Payment

Sends an STK Push prompt to the customer's phone. They enter their M-Pesa PIN to confirm.

POST/api/v1/paymentTrigger an STK Push to a customer
Request Bodyjson
{
  "phoneNumber": "0712345678",        // Required — Kenyan format or 254...
  "amount": 500,                       // Required — integer, min 1 KES
  "accountReference": "ORDER-123",    // Optional — max 12 chars, shown in M-Pesa
  "description": "Payment for order", // Optional
  "metadata": { "orderId": "abc" }    // Optional — stored with transaction
}
Responsejson
{
  "success": true,
  "transactionId": "3f2e8a1b-...",
  "checkoutRequestId": "ws_CO_...",
  "status": "pending",
  "message": "Payment request sent to customer's phone"
}
Note: The customer receives a PIN prompt within seconds. Poll /api/v1/transaction/:id or use webhooks for the final status.

Transaction Status

GET/api/v1/transaction/:idGet the current status of a transaction
Responsejson
{
  "transaction": {
    "id": "3f2e8a1b-...",
    "status": "completed",           // pending | completed | failed | cancelled
    "amount": "500.00",
    "phone_number": "254712345678",
    "mpesa_receipt_number": "RKL23X...",
    "account_reference": "ORDER-123",
    "created_at": "2024-01-15T10:30:00Z"
  }
}

List Transactions

GET/api/v1/transactions?page=1&limit=20&status=completedPaginated list of all transactions
Responsejson
{
  "transactions": [ { "id": "...", "status": "completed", "amount": "500.00", ... } ],
  "pagination": { "page": 1, "limit": 20, "total": 145, "pages": 8 }
}

Query Parameters

pagePage number (default: 1)
limitResults per page, max 100 (default: 20)
statusFilter: pending | completed | failed | cancelled

Webhooks

Configure endpoints in your dashboard. E-Payments sends a signed POST when these events occur.

payment.completed
payment.failed
payment.pending
order.created
order.paid
order.status_changed
invoice.paid
refund.completed
customer.created
Webhook Payloadjson
{
  "event": "payment.completed",
  "timestamp": "2024-01-15T10:32:00Z",
  "data": {
    "id": "3f2e8a1b-...",
    "status": "completed",
    "amount": "500.00",
    "phone_number": "254712345678",
    "mpesa_receipt_number": "RKL23X..."
  }
}

Verify the X-MPesa-Signature header:

Signature Verificationjavascript
const crypto = require('crypto');

app.post('/webhooks/mpesa', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-mpesa-signature'];
  const expected  = crypto.createHmac('sha256', process.env.WEBHOOK_SECRET)
                          .update(req.body).digest('hex');

  if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
    return res.status(401).send('Unauthorized');
  }

  const { event, data } = JSON.parse(req.body);
  // Handle: 'payment.completed' | 'payment.failed' | 'payment.pending' |
  //         'order.created' | 'order.paid' | 'order.status_changed' |
  //         'invoice.paid' | 'refund.completed' | 'customer.created'
  // 'data' is the raw order/invoice/refund/customer/transaction row.
  res.sendStatus(200);
});

Shopify Integration

Add M-Pesa as a checkout option in any Shopify store with our drop-in script.

Add to your Shopify themehtml
<!-- In checkout.liquid or order confirmation -->
<script>
  window.EPaymentsConfig = {
    apiKey:    'mpesa_test_your_api_key',
    apiUrl:    'https://yourapp.com/api/v1/payment',
    onSuccess: function(tx)  { console.log('Paid:', tx.transactionId); },
    onError:   function(err) { console.error('Failed:', err); }
  };
</script>
<script src="https://yourapp.com/shopify-integration.js"></script>

<!-- Place anywhere on your page -->
<button id="mpesa-pay-btn"
  data-amount="{{ cart.total_price | divided_by: 100 }}"
  data-reference="{{ order.name }}">
  Pay with M-Pesa
</button>

Already using window.MpesaSaaSConfig? It still works — the script reads either name, so existing installs don't need to change anything.

© 2026 E-Payments · Powered by NJWBack to Dashboard →