Mpesa Payments
Made Simple
The modern SDK for integrating M-Pesa payments. Type-safe, fully documented.
Without the SDK
Raw Daraja HTTP calls with fetch/httpx
import crypto from "node:crypto";
const API = process.env.MPESA_ENV === "prod"
? "https://api.safaricom.co.ke"
: "https://sandbox.safaricom.co.ke";
const AUTH_PATH = "/oauth/v1/generate";
const STK_PATH = "/mpesa/stkpush/v1/processrequest";
const AUTH_QS = "grant_type=client_credentials";
const KEY = process.env.MPESA_KEY ?? "";
const SECRET = process.env.MPESA_SECRET ?? "";
const SHORTCODE = process.env.MPESA_SHORTCODE ?? "";
const PASSKEY = process.env.MPESA_PASSKEY ?? "";
const CB_URL = process.env.MPESA_CB_URL ?? "";
type StkParams = {
amount: number;
phone: string;
accountRef: string;
desc?: string;
};
function normalize(phone: string): string {
const digits = phone.replace(/\D/g, "");
if (digits.startsWith("0")) {
return "254" + digits.slice(1);
}
return digits;
}
function stamp(): string {
const d = new Date();
const p = (n: number) => String(n).padStart(2, "0");
let s = String(d.getFullYear());
s += p(d.getMonth() + 1) + p(d.getDate());
s += p(d.getHours()) + p(d.getMinutes());
s += p(d.getSeconds());
return s;
}
function password(time: string): string {
const raw = SHORTCODE + PASSKEY + time;
return Buffer.from(raw).toString("base64");
}
async function getToken(): Promise<string> {
const raw = KEY + ":" + SECRET;
const creds = Buffer.from(raw).toString("base64");
const url = API + AUTH_PATH + "?" + AUTH_QS;
const res = await fetch(url, {
headers: { Authorization: "Basic " + creds },
});
if (!res.ok) {
throw new Error("Token failed: " + res.status);
}
return (await res.json()).access_token;
}
export async function stkPush(p: StkParams) {
const at = await getToken();
const time = stamp();
const payload = {
BusinessShortCode: SHORTCODE,
Password: password(time),
Timestamp: time,
TransactionType: "CustomerPayBillOnline",
Amount: p.amount,
PartyA: normalize(p.phone),
PartyB: SHORTCODE,
PhoneNumber: normalize(p.phone),
CallBackURL: CB_URL,
AccountReference: p.accountRef,
TransactionDesc: p.desc ?? "",
};
const res = await fetch(API + STK_PATH, {
method: "POST",
headers: {
Authorization: "Bearer " + at,
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
if (!res.ok) {
const text = await res.text();
throw new Error(res.status + ": " + text);
}
return res.json();
}
With the SDK
@singularity-payments/core
import { createMpesa } from
"@singularity-payments/core";
// Reads MPESA_* env vars for you.
const mpesa = createMpesa();
const res = await mpesa.stkPush({
amount: 100,
phoneNumber: "254708374149",
accountReference: "ORDER-123",
});
Works with your favourite languages
and
your favourite frameworks
Async first
Non-blocking requests with automatic retries and exponential backoff built in.
Type safe
Full type coverage in TypeScript and validated Pydantic models in Python.
Complete coverage
STK Push, C2B, B2C, B2B, reversals, balances, QR codes and callbacks.
Quick start
Install the SDK, configure your credentials and start accepting payments in minutes.
TypeScript / JavaScript
1
Install the package
npm install @singularity-payments/nextjs2
Create a client
const mpesa = createMpesa({
consumerKey: process.env.MPESA_CONSUMER_KEY!,
consumerSecret: process.env.MPESA_CONSUMER_SECRET!,
shortcode: process.env.MPESA_SHORTCODE!,
passkey: process.env.MPESA_PASSKEY!,
});3
Collect a payment
await mpesa.client.stkPush({
amount: 100,
phoneNumber: "254712345678",
accountReference: "ORDER-123",
transactionDesc: "Quick start",
});Python
1
Install the package
pip install singularity-payments2
Create a client
import os
from singularity_payments import MpesaClient, MpesaConfig
mpesa = MpesaClient(
MpesaConfig(
consumer_key=os.environ["MPESA_CONSUMER_KEY"],
consumer_secret=os.environ["MPESA_CONSUMER_SECRET"],
shortcode=os.environ["MPESA_SHORTCODE"],
passkey=os.environ["MPESA_PASSKEY"],
callback_url=os.environ["MPESA_CALLBACK_URL"],
)
)3
Collect a payment
from singularity_payments import STKPushRequest
await mpesa.stk_push(
STKPushRequest(
amount=100,
phone_number="254712345678",
account_reference="ORDER-123",
transaction_desc="Quick start",
)
)Ready to get started?
Read the guides and ship your first M-Pesa integration today.
