If you sell to Kenyan customers, M-PESA is not optional. It is the default rail. The question is no longer whether to integrate it — it is how to do it in a way that does not silently break six months in, and how to choose the right flow for your actual workflow.
This guide is a practical, opinionated walkthrough of M-PESA integration in 2026. We build, audit, and rescue these systems every month, and the patterns here come from production integrations that are still running cleanly years after launch.
The five M-PESA flows you will actually use
Safaricom's Daraja API exposes a long menu of endpoints. Most businesses only need one or two of these, well implemented:
1. M-PESA Express (STK Push)
The customer enters a phone number at checkout. Your system calls Daraja, which pushes a payment prompt to the customer's phone. They enter their M-PESA PIN to confirm. You receive a callback when payment completes — success or failure.
Note: Safaricom rebranded "Lipa Na M-PESA Online" to M-PESA Express in 2024. Some older documentation and tutorials still use the legacy name. The API endpoint is the same.
When to use it: online checkout, fee payment, deposit collection, app top-ups — anywhere the customer is actively in your interface and you initiate the payment request.
What it needs: a Paybill or Till number, Daraja API credentials, and a publicly reachable callback URL.
2. C2B (Customer to Business)
The customer pays your Paybill or Till number directly from their phone. You receive validation and confirmation webhooks. No prompt is pushed from your side.
When to use it: offline scenarios, fee payments with reference numbers (school fees with admission numbers, utility bills, rent), and any flow where the customer initiates payment outside your interface.
What it needs: a registered shortcode, validation and confirmation URLs registered with Safaricom, and a system that can map references back to customers.
3. B2C (Business to Customer)
You send money from your business shortcode to a customer's M-PESA wallet — for refunds, marketplace seller payouts, supplier payments, or casual labour disbursement.
When to use it: refund automation, marketplace seller payouts, agent commissions, payroll for casual labour, prize disbursement.
What it needs: organisational shortcode with adequate float, B2C API access, and tight operational controls. B2C is real money leaving your account — it deserves stronger guardrails than the inbound flows.
4. Account Balance & Transaction Status
Two often-overlooked utility APIs that turn unreliable integrations into reliable ones.
Account Balance tells you how much float is in your B2C shortcode — essential before initiating a B2C send, otherwise the API will fail mid-flow.
Transaction Status queries the state of a specific transaction by its M-PESA receipt number — essential when callbacks fail or arrive late.
5. Buy Goods (Till Number)
Till numbers are for retail and restaurant point-of-sale style payments where the amount is determined at the till, not pre-set with a reference.
Till 2.0 introduced a single till number that supports both Buy Goods and Pochi La Biashara accounting flows. If you opened a till after 2023, you are most likely on Till 2.0. The integration is similar to C2B but with subtle differences in the validation flow.
Paybill vs Till — quick rule: Paybill for fee-style payments with reference numbers (school fees, rent, utility). Till for ecommerce-style payments where the amount is dynamic at checkout.
What Safaricom charges (transaction fees)
This is the question buyers ask within five minutes. The honest answer in 2026:
- C2B and M-PESA Express (incoming): Safaricom takes a transaction fee from you, the merchant. Rates depend on tier and are negotiable for higher-volume merchants. Typical rates land between 0.5% and 1.5% per transaction with a maximum cap.
- B2C (outgoing): Per-transaction fees apply, typically around KES 20–30 per send depending on amount and tier.
- Withdrawal to bank: When you sweep funds from your Paybill or Till to a bank account, Safaricom charges a tiered fee.
Always confirm current rates with your Safaricom account manager — published rates change and high-volume merchants can negotiate.
The seven things that actually break
If you only read one section, read this one
Every M-PESA integration we have rescued failed in one of the seven ways below. If your current integration is missing protection against any of them, it is technical debt waiting to bite.
1. Treating the callback as authoritative
The M-PESA Express callback can fail, arrive late, or be missed entirely — especially during peak hours when Safaricom's systems are under load. If your "order paid" state depends only on the callback, you will have phantom failed payments where customers were charged but your system never recorded it.
Fix: poll the Transaction Status API on a sensible schedule when callbacks don't arrive within ~60 seconds. Reconcile against M-PESA statements daily.
2. No idempotency on the callback handler
M-PESA can deliver the same callback twice or more. If your handler does not check whether you have already processed that transaction ID, you will double-credit orders, double-mark fees as paid, or send refunds twice. Worse, you will not know until a customer complains.
Fix: store the M-PESA transaction ID (MpesaReceiptNumber) with a unique constraint and treat duplicate callbacks as no-ops. This is the single most important production safety measure.
3. Phone number normalisation
The same Kenyan number can arrive as 0712345678, 254712345678, +254712345678, or 712345678 depending on which channel triggered the entry. If your system stores them inconsistently, lookups will silently fail when reconciling payments against customers, or worse, the STK push will hit the wrong number.
Fix: normalise to a single canonical format (we recommend 254XXXXXXXXX without the leading plus) at every entry point — checkout, admin, imports, callbacks.
4. Slow or unreliable callback URLs
If your callback URL takes more than a few seconds to respond with HTTP 200, Safaricom will retry, time out, or stop trusting it over time. We have seen integrations degrade silently because the callback handler was doing too much work synchronously — sending notifications, generating receipts, updating analytics — all on the callback hot path.
Fix: acknowledge the callback fast (under one second is the safe target). Queue the actual processing and handle it asynchronously. Return HTTP 200 immediately with the required ResultCode: 0 body.
5. Skipping the test shortcode and sandbox
The Daraja sandbox is not glamorous, but the integrations that skip it end up debugging in production with real customer money. Test every state — successful payment, customer cancellation, timeout, insufficient balance, invalid PIN, network failure — before you go live.
Fix: run a full state matrix in the sandbox, then again with a small production amount to a controlled test number, before opening it to real customers.
6. No reconciliation against M-PESA statements
Even with idempotent callbacks, the system of record at Safaricom is the paybill statement or till statement, downloadable from the M-PESA Business portal. If your internal ledger diverges from the Safaricom statement and nobody catches it, you have a real accounting problem that compounds daily.
Fix: schedule a daily reconciliation job that compares your internal transaction ledger to the M-PESA statement, alerts on mismatches, and produces an exception report.
7. No observability
When the M-PESA integration silently breaks at 2am, you need to know before customers do. Most integrations have no alerting, no metrics, and no visibility into success rates, callback latency, or failure patterns.
Fix: instrument the integration with at least: success rate by hour, callback latency p95, failed-but-deducted alerts, and rate limit warnings. Run a daily health check.
What clean M-PESA integration looks like in 2026
A production-grade integration has these properties:
- Idempotent — handles duplicate callbacks safely via unique transaction ID constraints
- Auditable — every M-PESA transaction ID, amount, phone, timestamp, and state transition is logged
- Reconcilable — a daily job compares your ledger against M-PESA statements and alerts on drift
- Resilient — works when callbacks are late or missing, falls back to Transaction Status polling
- Observable — success rates, latencies, failure patterns visible on a dashboard
- Tested — sandbox state matrix, production smoke test, regression suite for failure modes
If your current integration is missing any of these, it is technical debt waiting to bite. We have helped businesses recover from "we lost track of fees for two months" situations more times than we want to admit, and the fix is always the same: re-architect around these six properties.
Practical advice if you are starting today
- Pick the right shortcode. Paybill for fee-style payments with references, till for ecommerce-style payments where the amount is determined at checkout. Get this wrong and you will be migrating in a year.
- Use M-PESA Express where you can. It is the smoothest customer experience and the easiest to reconcile.
- Plan for reconciliation from day one. It is not optional, and bolting it on later is twice the work.
- Test the failure cases. Cancellations, timeouts, and double callbacks are not edge cases — they are weekly events at any reasonable volume.
- Treat security seriously. Daraja credentials in source control or shared in Slack are the #1 cause of compromised merchant accounts.
- Talk to someone who has shipped this before. Daraja documentation is improving but the production gotchas are not in the docs.
Need M-PESA wired in properly?
Our M-PESA Integration & Reconciliation flagship build does exactly this — production-grade Daraja integration with idempotent callbacks, daily reconciliation, and an audit-ready ledger. Standalone, for businesses that already have a website or system but need the payment plumbing done right.
When to call us
If you would like a walk-through of your current M-PESA integration or are planning a new one, we run planning calls specifically for businesses on Daraja. We will tell you honestly what is working, what is risky, and what would take more effort than it is worth.
We have audited integrations that looked fine on the surface but were silently losing money on duplicate callbacks. We have rebuilt reconciliation flows for businesses that had stopped trusting their own ledger. And we have shipped clean greenfield integrations for retailers, schools, and service businesses across Kenya.
If any of that sounds like where you are now, book a call. We will be straight with you about what to do.