Quick Overview
Integrate payments in three simple steps: create a session, redirect to Mopay, and handle the response.
Your App → Create Payment Session → Redirect to Mopay → User Pays → Redirect Back
API Service
https://pay.mopay.co.lsCreate payment sessions
Payment UI
https://mopay.co.lsUser payment interface
Getting Started
Get Your API Key
- Go to https://mopay.co.ls
- Create an account and log in
- Create a new Project
- Copy your API Key from the project settings
Security: Keep your API key secure. Store it in environment variables, never in client-side code.
Integration Steps
Step 1: Create a Payment Session
Make a POST request to create a payment session:
POST https://pay.mopay.co.ls/api/external/payment
Headers:
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Body:
{
"amount": "100.00",
"reference": "ORDER12345",
"redirectUrl": "https://yourwebsite.com/payment-complete",
"description": "Order #12345",
"customerEmail": "customer@example.com",
"customerName": "John Doe"
}Required Fields
| Field | Type | Description |
|---|---|---|
amount | string | Payment amount (e.g., "100.00") |
reference | string | Unique order reference (alphanumeric only) |
redirectUrl | string | URL to redirect after payment |
Reference Format: Must contain only alphanumeric characters. No spaces, hyphens, underscores, or special characters.
Optional Fields
| Field | Type | Description |
|---|---|---|
description | string | Payment description shown to user |
customerEmail | string | Customer's email address |
customerName | string | Customer's name |
paymentFrequency | string | ONCE, MONTHLY, or ANNUALLY |
productName | string | Product name (for product payments) |
productDetails | string | Product or payment description |
productImage | string | URL to product image |
payWhatYouWant | boolean | Allow custom amounts |
minimumAmount | string | Minimum amount if payWhatYouWant is true |
Note on paymentFrequency:
ONCE- One-time payment onlyMONTHLY- (Coming Soon) Monthly debit orders/subscriptionsANNUALLY- (Coming Soon) Annual debit orders/subscriptions
⚠️ Debit order functionality for MONTHLY and ANNUALLY is not yet available. All payments currently process as one-time payments.
Success Response (200):
{
"success": true,
"sessionId": "MOP_abc123_ORDER12345",
"paymentUrl": "https://mopay.co.ls/pay/MOP_abc123_ORDER12345",
"reference": "ORDER12345",
"amount": "100.00"
}Step 2: Redirect User to Mopay
After receiving the response, redirect the user to the payment URL:
// JavaScript example
window.location.href = response.paymentUrl;
// Or use a link
<a href="https://mopay.co.ls/pay/MOP_abc123_ORDER12345">Complete Payment</a>The user will be taken to Mopay's payment page where they can select a payment method (M-Pesa, EcoCash, or Card) and complete the transaction.
Step 3: Handle the Redirect Back
After payment completion, users are redirected to your URL with query parameters:
✅ Successful Payment:
https://yourwebsite.com/payment-complete?status=success&reference=ORDER12345&transactionId=TXN123&sessionId=MOP_abc123_ORDER12345&amount=100.00&paymentMethod=mpesa❌ Failed Payment:
https://yourwebsite.com/payment-complete?status=failed&reference=ORDER12345&sessionId=MOP_abc123_ORDER12345&error=Payment+declined&paymentMethod=card⚠️ Cancelled Payment:
https://yourwebsite.com/payment-complete?status=cancelled&reference=ORDER12345&amount=100.00&paymentMethod=none&sessionId=MOP_abc123_ORDER12345When a user clicks "Cancel Payment" on the Mopay payment page, they are redirected with status=cancelled. The paymentMethod will be none if cancelled before selecting a payment method.
Query Parameters
| Parameter | Description |
|---|---|
status | success, failed, or cancelled |
reference | Your original reference |
transactionId | Mopay transaction ID (on success only) |
sessionId | The payment session ID |
amount | Payment amount |
paymentMethod | mpesa, ecocash, card, or none (if cancelled before selection) |
error | Error message (on failure only) |
Complete Code Examples
// Create payment session
async function createPaymentSession(orderData) {
const response = await fetch("https://pay.mopay.co.ls/api/external/payment", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.MOPAY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
amount: orderData.total.toFixed(2),
reference: orderData.orderId,
redirectUrl: "https://yoursite.com/payment-complete",
description: `Order #${orderData.orderId}`,
customerEmail: orderData.customerEmail,
customerName: orderData.customerName,
}),
});
const data = await response.json();
if (!data.success) {
throw new Error(data.error);
}
return data;
}
// Usage
const payment = await createPaymentSession({
orderId: "ORD001",
total: 150.0,
customerEmail: "john@example.com",
customerName: "John Doe",
});
// Redirect user to payment page
window.location.href = payment.paymentUrl;Payment Methods
M-Pesa
Mobile money by Vodacom Lesotho. User receives USSD prompt and enters PIN to confirm.
EcoCash
Mobile money by Econet Telecom Lesotho. User receives USSD prompt and enters PIN to confirm.
Card
Visa and Mastercard supported. Processed through iVeri payment gateway with secure card entry.
Retrieving Session Details
You can retrieve payment session details using the session ID:
Recommended: Always verify the transaction status by retrieving the session details from the API. Do not rely solely on the redirect parameters as they can be tampered with.
GET https://pay.mopay.co.ls/api/external/session/v1/{sessionId}
curl -X GET "https://pay.mopay.co.ls/api/external/session/v1/MOP_abc123_ORDER12345" \
-H "Accept: application/json"Response:
{
"success": true,
"session": {
"id": "...",
"sessionId": "MOP_abc123_ORDER12345",
"amount": "100.00",
"reference": "ORDER12345",
"transactionStatus": "success",
"redirectUrl": "https://yoursite.com/payment-complete",
"status": "COMPLETED",
"selectedPaymentMethod": "mpesa",
"transactionId": "TXN123",
"createdAt": "2025-12-04T14:00:00Z",
"completedAt": "2025-12-04T14:05:00Z"
}
}Session Status Values
| Status | Description |
|---|---|
CREATED | Session created, awaiting payment |
PROCESSING | Payment in progress |
COMPLETED | Payment successful |
FAILED | Payment failed |
CANCELLED | Payment cancelled by user |
EXPIRED | Session expired |
Transaction Status Values
| Status | Description |
|---|---|
success | Payment successful |
failed | Payment failed |
cancelled | Payment cancelled |
Note: transactionStatus can be null
Error Handling
Always check the success field in responses:
const response = await fetch("https://pay.mopay.co.ls/api/external/payment", {
// ...
});
const data = await response.json();
if (!data.success) {
// Handle error
console.error("Error:", data.error);
throw new Error(data.error);
}
// Proceed with data.paymentUrlCommon Errors
| Error | Cause | Solution |
|---|---|---|
| Invalid API key | Wrong or missing API key | Check your API key |
| Invalid request data | Missing required fields | Include amount, reference, redirectUrl |
| Valid redirect URL is required | Invalid redirectUrl | Use full URL with https:// |
Security Best Practices
Never expose your API key
- • Store in environment variables
- • Only make API calls from server-side code
Validate payments server-side
- • Don't trust client-side redirect parameters alone
- • Use the session retrieval API to verify payment status
Use unique references
- • Generate unique order IDs
- • Prevents duplicate payments
Use HTTPS
- • Always use https:// for your redirectUrl
- • Protects customer data
Testing
For testing, use the same endpoints. Create test orders with small amounts to verify your integration works correctly.
Quick Summary
- 1Get API key from https://mopay.co.ls
- 2Create session via POST https://pay.mopay.co.ls/api/external/payment
- 3Redirect user to the returned paymentUrl
- 4Handle redirect back to your redirectUrl with payment status