Payments Updated 24 Sep 2026 · first published 28 Mar 2025 · 5 min read

M-Pesa Daraja API: The Complete Integration Guide (2026)

Simon & Coster
· Founders, ByKabiro Labs

Daraja is Safaricom's developer platform for M-Pesa. It is how a website, app or system asks a customer to pay, finds out whether they paid, and sends money back out. This guide covers what we actually do on client projects and in our own products, including the mistakes that only show up once real money flows.

The APIs you will actually use

Till or paybill?

Both can receive STK Push payments. With a paybill, the customer's account reference (for example an order number) comes through with the payment. With a till (Buy Goods), set the transaction type to CustomerBuyGoodsOnline; the BusinessShortCode is the store or head-office number your till sits under and PartyB is the till number itself. Mixing these two up is the most common reason a till integration fails on day one.

The bigger difference is paying out. Refunds and payouts use B2C, which needs a separate B2C shortcode. A till on its own cannot send money to customers, so if your business model involves refunds or paying vendors, plan for that from the start.

STK Push, step by step

  1. Get an access token. Call the OAuth endpoint with your Consumer Key and Secret (Basic auth). The token lasts about an hour, so cache it rather than requesting a new one for every payment.
  2. Build the password. Base64 of Shortcode + Passkey + Timestamp, where the timestamp is YYYYMMDDHHmmss and must match the timestamp you send.
  3. Send the request to /mpesa/stkpush/v1/processrequest with the amount, the customer's number in 2547XXXXXXXX format, your callback URL and an account reference.
  4. Save the CheckoutRequestID against the order straight away. It is how you match the result later.
  5. Receive the callback. Safaricom posts the result to your HTTPS callback URL. A ResultCode of 0 means paid, and the metadata includes the M-Pesa receipt number.
  6. Confirm before you deliver. See the next section.

Do not trust the callback on its own

Your callback URL is a public web address. Anyone who discovers it can post a message that looks like a successful payment. Before an order is marked paid, confirm it: query the status with STK Push Query (or Transaction Status with the receipt code), and check that the amount and the CheckoutRequestID match what you stored. Make the handler idempotent too, so a callback that arrives twice can never credit an order twice.

Callbacks can also simply not arrive. Run a scheduled job, every few minutes, that queries every payment still pending after a short wait and settles it one way or the other. Without it you will eventually have a customer who paid and never got their order.

Result codes you will see most

Show the customer a plain message for each one ("You cancelled the payment — try again?") instead of a generic failure.

The "who is this?" problem

The prompt shows the business name registered on your shortcode, not your brand. If a customer is buying from "Tixa" and the prompt says "BYKABIRO LABS", some will cancel, thinking it is a scam. We saw this ourselves. The fix is simple: tell the customer the exact name they will see, on the checkout page and in any chat, before the prompt arrives.

Security basics

Sandbox, then go-live

Build everything against the sandbox first: it has its own test shortcode and passkey, and the simulated prompts let you test success, cancellation and timeouts. When it works, apply to go live from the Daraja portal for your real shortcode. Safaricom will issue production credentials and the passkey for that shortcode. Then test with a few real payments of small amounts before opening it to customers.

Checklist before launch: token cached, CheckoutRequestID stored, callback confirmed with a status query, idempotent handler, reconciliation job running, payment name shown to the customer, secrets off the web root.

Rather not deal with Daraja yourself? We build and run M-Pesa integrations with server-side confirmation and daily reconciliation.

M-Pesa integration →
Chat with Us