All insights
Payments·8 April 2026·9 min read

M-Pesa integration: a developer's quick start

Daraja is well-documented but the details trip up most teams. Here's the shortest path from zero to production-ready M-Pesa STK push, with the gotchas spelled out.

If you've been asked to add M-Pesa to a product, the official Daraja documentation will get you 80% of the way there. The remaining 20% is where most teams lose two weeks. This is the short version of what we wish we'd known on day one.

Sandbox vs. production credentials

Daraja gives you sandbox credentials immediately. Production credentials require a Safaricom paybill or till number registered to a business, and the application process takes 5–10 business days. Start that paperwork in parallel with development — not after.

STK push: the happy path

The STK push (Lipa na M-Pesa Online) flow is:

  • 1. Get an OAuth access token (cache it; tokens are valid for ~1 hour).
  • 2. POST the STK push request with the customer phone number, amount, and your callback URL.
  • 3. Customer receives the prompt on their phone.
  • 4. Daraja calls your callback URL with the result (success, cancelled, timeout, etc).
  • 5. You confirm with the customer and update your order.

Callback URLs in development

Daraja must be able to reach your callback URL over public internet. In dev, that means tunneling — ngrok or Cloudflare Tunnel both work. Don't try to test against localhost; the request will silently fail.

The reconciliation problem

M-Pesa callbacks are not always reliable. Network blips, deploys, or downtime can mean a payment succeeds but your callback never lands. Always pair the callback flow with a polling reconciliation job that queries Daraja's transaction status endpoint for orders stuck in 'pending' state for more than ~3 minutes.

Idempotency

Use the CheckoutRequestID returned by the STK push as your idempotency key. Customers will sometimes pay twice if your UI doesn't disable the button properly — your backend should never double-fulfill an order for the same key.

Phone number formatting

Daraja expects MSISDN format: 254712345678 (no plus sign, no leading zero). Validate and normalize aggressively at your input boundary — half of all sandbox failures we've debugged came down to a phone number with the wrong prefix.

If you'd rather not own this end-to-end, we offer M-Pesa integration as a service starting from KES 80,000. The integration includes STK push, B2C disbursements, reconciliation, and a small admin dashboard for your finance team.

Written by

Jabarli Inc.

Have a project we could help with?

We do free 30-minute scoping calls — honest, no sales pitch.

Start a conversation