Ship M-Pesa STK Push
in Lines, Not Hours
A lightweight TypeScript client for Safaricom's Daraja API that runs anywhere fetch does. Automatic OAuth token refresh, EAT timestamp math, and typed payload normalization so you write payments logic, not boilerplate.
Not even a fetch polyfill.
Every request and response, typed.
No Node-only APIs, runs anywhere.
Cached and refreshed for you.
Import or require, either works.
Core Engine Design
The tricky parts of Daraja integrations handled before you write a single line of application logic.
OAuth 2.0 Lifecycle
Automates token acquisition, in-memory caching, and proactive background refresh with a 60-second buffer before expiry.
EAT Timezone Sync
Normalizes timestamps to East Africa Time (UTC+3) and handles Base64 password derivation to prevent drift rejections.
Webhook Payload Parsing
Flattens nested Daraja callback arrays and stringified booleans into strongly typed TypeScript domain models.
Pre-Flight Validation
Validates request structures, callback URL formats, and phone number prefixes before executing network requests.
Edge Runtime Compatible
Built strictly on native Fetch API and AbortController without Node.js standard library dependencies.
Zero Dependencies & Dual Build
Ships with ESM and CJS outputs, zero third-party runtime dependencies, and full TypeScript declarations.
Every Endpoint We've
Actually Tested.
Tested end to end against Safaricom's sandbox. When something fails because Daraja's own upstream server is down, that's transparently status-flagged.
Authentication
OAuth 2.0 tokens cached in memory and refreshed automatically before expiration.
M-Pesa Express (STK Push)
Send prompt requests to customer phones and query status via CheckoutRequestID.
C2B Payments
Register callback URLs and simulate customer PayBill or Till transactions.
B2C Account Top Up
Disburse payments from Working/MMF accounts to customer phones or utility shortcodes.
B2B Hakikisha
Verify recipient business names and account shortcodes prior to fund transfers.
Dynamic QR
Generate scannable M-Pesa QR codes for merchant store checkouts.
Mobile Data Bundles
Purchase and query status for Safaricom internet bundle offerings.
SIM Swap & IMSI
Fraud check tools: evaluate last SIM swap timestamp and network age.
Mobile Number Validation
Confirm whether a phone number is an active, reachable Safaricom subscriber.
Missing an endpoint?
Reversals, generic B2C, generic B2B, and Account Balance wrappers are being finalized for the next minor release.
Clean API. Zero Boilerplate.
Usage patterns across TypeScript, Next.js App Router, Express, and Callback Webhooks.
Built in, not bolted on
How @lumierelabs/daraja compares with raw HTTP fetch implementations and legacy Node-only SDK packages.
| CAPABILITY | @lumierelabs/daraja Modern TypeScript SDK | Manual Native Fetch Raw HTTP requests | Legacy Node SDKs Node-only packages |
|---|---|---|---|
| Zero Runtime Dependencies | 0 dependencies | 0 dependencies | Multiple deps |
| Edge Runtime & Multi-Runtime (Workers / Vercel / Deno) | Native web fetch | Native web fetch | Node.js only |
| OAuth 2.0 Token Caching & Auto-Refresh | Automatic in-memory | Manual boilerplate | Basic / Manual |
| EAT (UTC+3) Timezone Auto-Parsing | Auto-normalized Date | Raw string | Raw string |
| Callback Payload Metadata Unwrapper | Clean key-value object | Nested Array parsing | Nested Array parsing |
| End-to-End TypeScript Definitions | Strict types & inference | Manual `any` casting | Outdated types |
Assessment based on package specifications and public developer documentation, April 2026.
One Client. Every Runtime You Ship On.
There's no Node-specific API anywhere in the client. Whatever you deploy on, from a single VPS to Cloudflare's edge network, the same code runs unchanged.
Safaricom's Docs, Rebuilt Properly.
No more digging through scattered PDFs and portal pages. Every endpoint gets one clean, searchable guide.
Every Field, Documented
Field-LevelRequest parameters, response shapes, and exact Safaricom error codes laid out per endpoint.
Defects Marked, Not Hidden
Called OutWhere Safaricom's docs contradict themselves or misspell field names, it's explicitly called out.
Tested, Not Just Transcribed
Status-TrackedEndpoints are categorized as sandbox-tested or blocked by upstream issues rather than assumed supported.
Explore Safi: Private M-Pesa Statement Analytics
A private, browser-based M-PESA statement analyzer and financial dashboard built with Next.js. Parse statements locally with complete privacy and instant insights.

Built in public.
Improved by everyone.
Every contribution helps make Daraja SDK more reliable, resilient, and developer-friendly.
Technical Questions
Common issues encountered during M-Pesa integrations and how to resolve them.
Still stuck? Open an issue on GitHub