API Documentation

MoPay Integration Guide

Integrate MoPay into your website to accept M-Pesa, EcoCash, and card payments in Lesotho. Simple, secure, and developer-friendly.

Overview

Quick Overview

The MoPay flow is intentionally short: create a session, redirect the customer, then verify the payment result when they return.

Your backend owns the session creation, MoPay owns the payment experience, and your app regains control once the customer is redirected back.

Your App → Create Payment Session → Redirect to MoPay → User Pays → Redirect Back

API Service

https://pay.mopay.co.ls

Create and manage payment sessions from your backend.

Payment UI

https://mopay.co.ls

Hosted customer-facing checkout for mobile money and card payments.

Setup

Getting Started

Start by creating a MoPay account and generating the API key your server will use for payment session creation.

1

Get Your API Key

  1. Go to https://mopay.co.ls
  2. Create an account and log in
  3. Create a new Project
  4. Copy your API Key from the project settings

Security: Keep your API key secure. Store it in environment variables, never in client-side code.

Core Flow

Integration Steps

Build the integration in three predictable moves: create the session, redirect the customer to MoPay, then verify what happened on return.

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

FieldTypeDescription
amountstringPayment amount (e.g., "100.00")
referencestringUnique order reference (alphanumeric only)
redirectUrlstringURL to redirect after payment

Reference Format: Must contain only alphanumeric characters. No spaces, hyphens, underscores, or special characters.

✅ Valid: ORDER12345❌ Invalid: ORDER-12345

Optional Fields

FieldTypeDescription
descriptionstringPayment description shown to user
customerEmailstringCustomer's email address
customerNamestringCustomer's name
paymentFrequencystringONCE, MONTHLY, or ANNUALLY
productNamestringProduct name (for product payments)
productDetailsstringProduct or payment description
productImagestringURL to product image
payWhatYouWantbooleanAllow custom amounts
minimumAmountstringMinimum amount if payWhatYouWant is true

Note on paymentFrequency:

  • ONCE - One-time payment only
  • MONTHLY - (Coming Soon) Monthly debit orders/subscriptions
  • ANNUALLY - (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_ORDER12345

When 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

ParameterDescription
statussuccess, failed, or cancelled
referenceYour original reference
transactionIdMopay transaction ID (on success only)
sessionIdThe payment session ID
amountPayment amount
paymentMethodmpesa, ecocash, card, or none (if cancelled before selection)
errorError message (on failure only)
Examples

Complete Code Examples

Switch between working examples to see the same flow translated into the stack you already use.

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

One integration, the payment methods your customers already trust.

MoPay keeps the checkout surface consistent while each payment option stays visually grounded in its real brand.

Mobile money stays native for Lesotho customers, while card payments use the same hosted flow and session model documented across the rest of the API.

M-Pesa
Mobile money

M-Pesa

Vodacom Lesotho mobile money checkout with a familiar USSD approval flow and locally optimized payment completion.

Customer approves on phonevia MoPay
EcoCash
Mobile money

EcoCash

Econet EcoCash collections through the same MoPay session architecture, with a simple redirect and return flow.

Customer confirms via handsetvia MoPay
VisaMastercard
Card payments

Cards

Visa and Mastercard payments are processed through iVeri inside the hosted MoPay experience for a secure checkout.

Hosted card entry via MoPayvia MoPay
Verification

Retrieving Session Details

Once you receive the customer back, use the session ID to confirm the final payment state from the API.

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

StatusDescription
CREATEDSession created, awaiting payment
PROCESSINGPayment in progress
COMPLETEDPayment successful
FAILEDPayment failed
CANCELLEDPayment cancelled by user
EXPIREDSession expired

Transaction Status Values

StatusDescription
successPayment successful
failedPayment failed
cancelledPayment cancelled

Note: transactionStatus can be null

Reliability

Error Handling

Treat every response as data to validate. A simple success check upfront keeps your checkout flow predictable.

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

Common Errors

ErrorCauseSolution
Invalid API keyWrong or missing API keyCheck your API key
Invalid request dataMissing required fieldsInclude amount, reference, redirectUrl
Valid redirect URL is requiredInvalid redirectUrlUse full URL with https://
Security

Security Best Practices

Keep the integration server-led, validate outcomes from the API, and treat your API key like production infrastructure.

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
Launch Prep

Testing

Use low-value transactions and the real session lifecycle to confirm redirects, callbacks, and state handling before go-live.

Ready to integrate?

Get started today and start accepting payments in minutes.

Create Account
Quick Summary
  1. 1Get API key from https://mopay.co.ls
  2. 2Create session via POST https://pay.mopay.co.ls/api/external/payment
  3. 3Redirect user to the returned paymentUrl
  4. 4Handle redirect back to your redirectUrl with payment status