Browser SDK
Add hosted M-Pesa checkout to any website. Drop in a CDN script, pass a payment account identifier, and let PayNexus handle the STK Push flow in a secure popup.
How It Works
The Browser SDK uses a hosted checkout flow — your page never touches API keys, and PayNexus handles the M-Pesa interaction securely.
Add the CDN Script
Load PayNexus from the CDN on your website. No npm install or build step required.
Open Hosted Checkout
Pass your accountId, amount, description, and return/cancel URLs to open the M-Pesa payment popup.
Receive the Result
Redirect the customer or unlock content after payment completes. Handle cancellations gracefully.
Quick Start
Add M-Pesa checkout to any page in under 5 minutes.
1. Load the CDN
2. Initialize and Open Checkout
const checkout = PayNexusHostedCheckout();
document.getElementById('payBtn').addEventListener('click', async () => {
try {
const result = await checkout.open({
accountId: 'ACC_ZVTDYYYL',
amount: 100,
description: 'Premium Article Access - AI Future',
returnUrl: 'https://example.com/thanks.html',
cancelUrl: 'https://example.com/cancelled.html',
});
console.log('Payment completed:', result.reference, result.amount);
window.location.href = 'thanks.html';
} catch (error) {
if (error.code === 'cancelled') {
window.location.href = 'cancelled.html';
} else {
alert('Payment initialization failed. Please try again.');
}
}
});
3. Add a Trigger Button
Use Your Payment Account Identifier
The hosted checkout flow uses accountId — the identifier for the payment account receiving the money. This keeps API keys completely out of the page.
The hosted checkout flow does not require publishing secret or public API keys in your HTML. Only the accountId is needed, which is safe for client-side use.
Find your accountId in the PayNexus dashboard under Payment Accounts. It looks like this:
Account ID: ACC_ZVTDYYYL
Popup vs Redirect
The Browser SDK supports two checkout modes depending on your UX needs:
Popup Mode
Uses checkout.open() to launch the M-Pesa flow in a centered popup. The customer stays on your page and can resume after payment.
const result = await checkout.open({
accountId: 'ACC_ZVTDYYYL',
amount: 100,
description: 'Premium Article',
returnUrl: 'https://example.com/thanks',
cancelUrl: 'https://example.com/cancelled'
});
Redirect Mode
Uses checkout.redirect() for a full-page hosted checkout. Ideal for simple flows where you want the customer on PayNexus-hosted pages.
checkout.redirect({
accountId: 'ACC_ZVTDYYYL',
amount: 100,
description: 'Premium Article',
returnUrl: 'https://example.com/thanks',
cancelUrl: 'https://example.com/cancelled'
});
Configuration Options
Pass the following options to checkout.open() or checkout.redirect():
| Option | Type | Required | Description |
|---|---|---|---|
accountId |
string | Yes | Your PayNexus payment account identifier (e.g. ACC_ZVTDYYYL). |
amount |
number | Yes | Payment amount in KES (minimum 1). |
description |
string | No | Payment description shown to the customer during STK Push. |
returnUrl |
string | No | URL to redirect to after successful payment. |
cancelUrl |
string | No | URL to redirect to if the customer cancels or the payment fails. |
reference |
string | No | Custom payment reference (invoice ID, order number, etc.). Auto-generated if omitted. |
phoneNumber |
string | No | Pre-fill the customer's phone number (2547... format) to skip the entry step. |
Handling the Result
After the customer completes or cancels the payment, the SDK resolves or rejects the promise accordingly.
Success Result
const result = await checkout.open({...});
console.log(result);
// {
// reference: "PAY_abc123xyz",
// amount: 100,
// status: "completed",
// phoneNumber: "254712345678",
// accountId: "ACC_ZVTDYYYL"
// }
Error Handling
try {
const result = await checkout.open({...});
} catch (error) {
switch (error.code) {
case 'cancelled':
// Customer closed popup or clicked cancel
window.location.href = cancelUrl;
break;
case 'failed':
// Payment failed (insufficient funds, timeout, etc.)
showError('Payment failed. Please try again.');
break;
case 'network':
// Network error contacting PayNexus
showError('Connection issue. Check your internet and retry.');
break;
default:
showError('Payment initialization failed. Please try again.');
}
}
| Error Code | Meaning | Suggested Action |
|---|---|---|
cancelled |
Customer closed the popup or navigated away | Redirect to cancelUrl |
failed |
Payment failed (insufficient funds, timeout, wrong PIN) | Show retry option |
network |
Network error or PayNexus unreachable | Retry after connectivity is restored |
invalid_params |
Missing or invalid checkout configuration | Check accountId, amount, and URLs |
account_not_found |
The accountId does not exist or is inactive |
Verify account ID in dashboard |
Use Cases
The Browser SDK is ideal for any scenario where you want to collect M-Pesa payments without managing payment infrastructure:
Premium Content
Unlock articles, videos, or downloads after one-time payment.
Event Tickets
Sell tickets for events, webinars, and workshops.
Donations
Accept contributions with custom or fixed amounts.
Digital Products
Sell software, templates, or digital goods.
Course Enrollments
Collect fees for online courses or training.
Service Fees
Charge for consultations, bookings, or on-demand services.
Security Notes
The Browser SDK is designed with security as the top priority:
API keys never touch the browser
The hosted checkout runs on PayNexus servers. Only your accountId is needed, which is not a secret.
STK Push is served from PayNexus domains
The actual M-Pesa authorization happens on PayNexus-hosted pages, not on your domain.
Webhook verification for server-side confirmation
Always verify payment status server-side using the PayNexus API or webhooks rather than trusting only the frontend result.
Validate returnUrl and cancelUrl
Use HTTPS URLs you control. Avoid accepting arbitrary URLs from user input to prevent open redirect vulnerabilities.
While the SDK result is reliable for UX flows, you should always confirm payment status via the PayNexus API or webhooks before delivering goods or services. Never trust only the client-side result.
Verifying Payments Server-Side
Use the Payment Reference returned by the SDK to confirm the payment status from your backend:
const response = await fetch(
'https://paynexus.co.ke/api/payments/' + reference,
{
headers: {
'X-API-Key': 'sk_...'
}
}
);
const transaction = await response.json();
if (transaction.data.status === 'completed') {
// Deliver the product / service
}
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://paynexus.co.ke/api/payments/' . $reference,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'X-API-Key: sk_...'
]
]);
$response = curl_exec($ch);
$transaction = json_decode($response, true);
if ($transaction['data']['status'] === 'completed') {
// Deliver the product / service
}
import requests
response = requests.get(
'https://paynexus.co.ke/api/payments/' + reference,
headers={'X-API-Key': 'sk_...'}
)
transaction = response.json()
if transaction['data']['status'] == 'completed':
# Deliver the product / service
pass
Build Faster
Add M-Pesa checkout to any website today. No server code required for basic checkout.
Grab your accountId from the PayNexus Dashboard and drop the CDN script into your page. You'll be accepting M-Pesa payments in minutes.