Reconciliation & Webhooks
Callbacks, status queries, orphaned payments and keeping the books straight.
9 articles
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.
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.
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.
KES, TZS and UGX: Multi-Currency Ledgers and the FX Gap Eating Your Margin
There is no single exchange rate in East Africa. Minor-unit traps, largest-remainder allocation, quote expiry, realised versus unrealised FX, and a schema that records the rate you actually transacted at.
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.
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.
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.
Payment Webhook Signature Fails on One Server: The Clock-Drift Check Nobody Runs
Stripe webhook verification fails on one box but not the others? Its signature is time-bound and your clock drifted. Why Paystack and Flutterwave are immune, and the NTP fix.
When the Webhook Succeeds but Your Database Write Doesn't: Handling Orphaned Payments
The provider took the money, your write crashed, and now you have a payment with no order. Why try/catch cannot fix it, and the idempotency, outbox and reconciliation design that can.