Enterprise Integrations: Connecting M-Pesa and APIs to Your ERP
In Kenya, money moves through M-Pesa. Your customers pay by paybill or till. Your suppliers invoice by email. Your bank sends statements as PDFs. Your e-commerce store sits on Shopify. Your ERP holds the truth about stock and receivables - except when it does not, because a person has to key everything in.
Integration is the work of removing that person from the middle. Done well, it is the single highest-return investment most Kenyan businesses can make in their systems, because it eliminates the two things that quietly destroy trust in an ERP: delay and transcription error.
This article covers what enterprise integration actually involves, the specific realities of M-Pesa and payment integration, the patterns that survive production, and how to scope the work.
What enterprise integration includes
"Integration" gets used loosely. In practice it covers four distinct jobs:
- Payment collection - M-Pesa STK push, paybill and till callbacks, card gateways, bank transfers, and matching each receipt to the right invoice
- Payment disbursement - supplier payments, refunds, commissions, payroll to mobile money
- System-to-system sync - e-commerce orders into the ERP, stock levels out, customers and pricing kept aligned in both directions
- Compliance and reporting - KRA eTIMS invoice transmission, bank statement ingestion, regulatory feeds
Each has different failure modes and different consequences when it breaks. A stock sync that lags by ten minutes is an inconvenience. A payment callback that is silently dropped is a customer who paid and did not get their goods.
The M-Pesa integration reality
Most businesses assume M-Pesa integration means "call the API and record the payment". The API call is the easy part. The engineering is in everything around it.
Callbacks are not guaranteed to be well-behaved
Your callback endpoint may be called twice for the same transaction. It may be called late. It may be called while your server is restarting. Any integration that assumes exactly-once, immediate delivery will eventually create duplicate receipts or lose one.
The correct pattern is idempotency: store the raw callback first, keyed on the transaction ID, before doing any accounting work.
def handle_callback(payload):
txn_id = payload["TransID"]
if frappe.db.exists("Mpesa Callback Log", txn_id):
return {"ResultCode": 0, "ResultDesc": "Already processed"}
log = frappe.get_doc({
"doctype": "Mpesa Callback Log",
"name": txn_id,
"raw": frappe.as_json(payload),
"status": "Received",
}).insert(ignore_permissions=True)
frappe.db.commit()
frappe.enqueue(
"myapp.mpesa.reconcile",
queue="short",
log_name=log.name,
)
return {"ResultCode": 0, "ResultDesc": "Accepted"}
Three things are happening there. The handler acknowledges quickly so the gateway does not retry. It refuses to process the same transaction twice. And the actual accounting happens in a background job, so a slow ledger write never causes a timeout on the callback.
Matching payments to invoices is a business problem
Customers pay the wrong amount. They pay for three invoices at once. They use their brother's phone. They put a vehicle registration in the account reference field instead of an invoice number.
A production integration needs a matching strategy with tiers: exact reference match, then phone number to customer match, then amount and date heuristics, and finally a suspense queue where a human decides. Unmatched payments must be visible, aged and chased - not silently posted to a catch-all account where they distort your receivables forever.
Reconciliation is the deliverable, not the API
The question your finance team asks at month end is not "did the API work?" It is "does the M-Pesa statement total match what the ERP recorded, to the shilling?" Build the reconciliation report on day one. It is how you discover problems in week two instead of month six.
Patterns that survive production
Log the raw payload, always
Store what the other system actually sent, unmodified, before you interpret it. When a dispute arises six months later, that log is the only evidence that exists.
Queue everything
Never do meaningful work inside a webhook handler. Accept, persist, acknowledge, then process asynchronously with retries and backoff. This one decision prevents most integration outages.
Make retries safe
Every operation that can be retried must be idempotent. If your retry logic can create a second sales invoice, you do not have retry logic - you have a duplication engine.
Fail loudly, to a human
A failed integration must produce an alert someone actually receives, with the transaction reference. Silent failure is worse than no integration, because the business keeps trusting numbers that stopped updating.
Decide direction and ownership per field
For every synced field, one system is the master. Price is owned by the ERP. Order status may be owned by the e-commerce platform. Write it down. Bidirectional sync without ownership rules produces update loops and mystery overwrites.
Treat credentials properly
Consumer keys, secrets and passkeys belong in environment variables or a secret store, never in code or a DocType field visible to every user. Rotate them, and know who has them.
What it costs to get integration wrong
| Mistake | Consequence |
| No idempotency on callbacks | Duplicate receipts, customer balances wrong, painful manual cleanup |
| Synchronous processing in the webhook | Gateway timeouts and retries, compounding the duplicate problem |
| No suspense handling | Unmatched cash hidden in a clearing account nobody reconciles |
| Silent failures | Stock or orders stop syncing and nobody notices for weeks |
| No raw payload log | Disputes cannot be investigated or proven |
| Credentials in code | Security exposure that survives every staff change |
An integration is not finished when the first transaction succeeds. It is finished when the tenth failure is handled correctly without anyone noticing.
Integrations we build most often
- M-Pesa - STK push, C2B paybill and till, B2C disbursement, B2B, with full reconciliation reporting
- Card and gateway payments - checkout flows, settlement matching, refunds
- KRA eTIMS - invoice transmission, credit notes, item classification handling
- Bank feeds - statement ingestion and automated bank reconciliation
- E-commerce - Shopify and WooCommerce order, stock, pricing and customer sync
- Messaging - WhatsApp Business and SMS for order confirmations, statements and payment reminders
- Logistics and third-party systems - dispatch, tracking, telematics, partner APIs
- Legacy systems - APIs and sync layers over software that cannot be replaced yet
How to scope an integration project
- List the systems and the direction of each flow. A one-page diagram prevents months of confusion.
- Define the master for every shared field. Who wins on conflict?
- Agree acceptable latency. Real time, five minutes and nightly have very different costs.
- Specify the failure path. Who gets alerted, who fixes it, and what the customer sees meanwhile.
- Insist on a reconciliation report as a named deliverable, not an afterthought.
- Confirm sandbox access early. Credential approval, especially for payments and eTIMS, is often the longest item on the timeline.
One caution: integration is a prerequisite for the clever things, not a substitute for them. Businesses often want an AI assistant over data that three systems disagree about. Connect and reconcile the data first. We wrote about that sequencing in don't get pressured into buying AI before your business is ready.
Let us connect your systems properly
Upeosoft Limited is a Nairobi-based ERPNext consultancy extended with custom engineering, and enterprise integration is a large part of what we do. We build with Python, TypeScript, Frappe, FastAPI, PostgreSQL, MariaDB, Redis, Docker and Kubernetes, and we have delivered over 200 systems across retail and distribution, manufacturing, automotive, real estate, waste management, security services, professional services and lending.
If your team is keying M-Pesa payments into the ERP by hand, or your online store and your stock ledger disagree, that is a solvable problem. Tell us the systems and we will map the flows with you.
- Email: consult@upeosoft.com
- Phone: 0116 888 777
- Web: upeosoft.com