</>CodeWithKarani
All of Payments & Fintech
Payments & Fintech

M-Pesa & Daraja

The Daraja API, its error codes and the things the docs leave out.

24 articles

Payments & Fintech7 min read

Daraja API in Production: STK Push, C2B and B2C With Callbacks That Actually Work

A build-order guide to Safaricom's Daraja API with real payloads: OAuth token caching, STK Push, C2B v2 registration, B2C v3 with RSA security credentials, and the callback URL rules nobody documents.

Read
Upeosoft7 min read

POS System Kenya: Why UpeoRetail Fits How Shops Really Sell

Looking for a POS system in Kenya that survives real trade? UpeoRetail gives shops, minimarts and distributors fast checkout, honest stock, multi-branch visibility and M-Pesa payments on a hardened ERPNext backbone.

Read
Payments & Fintech7 min read

Your M-Pesa Callback Will Fire Twice: Idempotency, Retries and the 1037 Problem

Daraja callbacks are unreliable notifications, not a source of truth. Seven production failure modes, with the database constraints, pollers and parsers that make double charges structurally impossible.

Read
Upeosoft6 min read

Property Management Software Kenya: ISHI for Landlords

ISHI is a rent management system for Kenyan landlords, agents and property managers: automated invoicing, M-Pesa allocation, water billing with a field agent portal, tenant self-service and arrears dashboards.

Read
Payments & Fintech6 min read

M-Pesa Reconciliation That Scales: From Paybill Statement to Trial Balance

Stop reconciling in spreadsheets. A three-way match between the Safaricom statement, your callback events and a double-entry ledger, with named break categories and a daily close job in Python and SQL.

Read
Upeosoft6 min read

Enterprise Integrations: Connecting M-Pesa and APIs to Your ERP

M-Pesa callbacks, payment matching, e-commerce sync and eTIMS. The patterns that survive production - idempotency, queues, raw payload logs and reconciliation - and the ones that create duplicate receipts.

Read
Payments & Fintech7 min read

Build a Payments Port, Not a Daraja Wrapper: Provider-Agnostic Money Movement in Africa

The right payments abstraction is a normalised state machine plus a normalised event, not a charge() function. Ports, adapters, webhook signature handling, minor-unit traps and config-driven routing.

Read
Payments & Fintech7 min read

Daraja invalid access token: 401.003.01 is not 404.001.03

Two Daraja errors say 'Invalid Access Token' and mean different things. One is a wrong-environment token you can fix in code, the other is an entitlement problem only Safaricom can fix.

Read
Payments & Fintech7 min read

M-Pesa 1001 Transaction In Progress: Why Retrying Instantly Fails

Daraja error 1001 is a subscriber lock, not a transient error, and the usual retry loop makes it worse. The cooldown, the state machine and the copy customers can act on.

Read
Payments & Fintech8 min read

Daraja Returns 429 With a Body Your Error Parser Cannot Read

An HTTP 429 from M-Pesa Daraja is an Apigee spike arrest fault, not Daraja JSON, so most error handlers log undefined and swallow it. Here is how to classify, pace and back off.

Read
Payments & Fintech7 min read

M-Pesa C2B Sandbox Callbacks Only Fire Half the Time

Daraja's C2B sandbox drops most confirmation callbacks, so developers debug ngrok and nginx for days. Here is why it happens and the deploy-first workflow that replaces it.

Read
Payments & Fintech7 min read

M-Pesa 'Unable to Send STK Prompt' (1025/9999): Check the Length

Daraja returns 1025 for both a too-long TransactionDesc and a genuine M-Pesa outage. One retries successfully, the other never will. Here is how to tell them apart.

Read
Payments & Fintech8 min read

M-Pesa error 2001 invalid initiator: the stale certificate trap

M-Pesa B2C returns ResultCode 2001, 'The initiator information is invalid.' It is rarely the initiator name. It is usually a certificate copied from the wrong place.

Read
Payments & Fintech9 min read

M-Pesa Daraja 500.001.1001 when your consumer key is actually correct

Daraja's 'Wrong credentials' error hides two unrelated causes, and neither is your API key. Usually it is a timestamp generated twice that drifts by one second.

Read
Payments & Fintech7 min read

M-Pesa "Invalid BusinessShortCode": The Python requests Bug Behind It

Daraja error 400.002.02 blames your shortcode, but the real cause is usually data=payload instead of json=payload in Python requests. Here is how to prove it.

Read
Payments & Fintech9 min read

M-Pesa ResultCode 4999 Is Not a Failure: Handling Undocumented Daraja Codes

Daraja's STK query can return 4999, which no Safaricom document defines. Treating it as failed causes double charges. Here is the three-bucket model that prevents it.

Read
Payments & Fintech9 min read

M-Pesa Invalid Access Token After Go-Live: It Is Not Your OAuth Code

Daraja returns 404.001.03 Invalid Access Token when your shortcode is not whitelisted, not just when the token is bad. One curl tells you which, and saves two days.

Read
Payments & Fintech6 min read

Daraja Error 1032 'Request Cancelled by User' Is Not a Bug in Your M-Pesa Integration

M-Pesa STK Push ResultCode 1032 means the customer pressed Cancel, not that anything broke. Stop paging on it and handle it as the user action it is.

Read
Payments & Fintech9 min read

Daraja 404.001.03: Cache the Access Token, Don't Mint a New One

M-Pesa Daraja tokens live about an hour. Fetching one per request gets you throttled; caching forever gets you 404.001.03. The proactive refresh pattern Safaricom never documents.

Read
Payments & Fintech9 min read

M-Pesa error 1037: the STK push that never reached the phone

Daraja 1037 is not a declined payment. It means the handset never answered the SIM toolkit prompt. How to classify it, poll for it, and retry without creating duplicate orders.

Read
Payments & Fintech8 min read

M-Pesa 1019 vs 1037 vs 1032: three STK failures that look identical and are not

1019 means the prompt arrived and the user was too slow. 1037 means it never arrived. 1032 means they cancelled. Conflating them hides whether your problem is network, copy or timeout.

Read
Payments & Fintech7 min read

Testing Payment Integrations When the Sandbox Itself Is Flaky

M-Pesa, Stripe and Paystack callbacks are where payments break, and the sandbox that fires them is unreliable. Stop chasing it: record the payloads once and test your handler against fixtures.

Read
Payments & Fintech7 min read

Your M-Pesa Integration Needs Nightly Reconciliation, Not Just Callbacks

A missing M-Pesa callback is not a failed payment, it is an unknown outcome. Build a scheduled Transaction Status reconciliation job so lost callbacks never strand a paid order.

Read
Payments & Fintech8 min read

M-Pesa STK Push Callback Never Arrives? Reconcile With the Transaction Status Query API

STK Push callbacks are not guaranteed even with a perfect URL. Build a reconciliation job that treats the Transaction Status Query API as the real source of truth.

Read