How to Integrate Mpesa with a Billing System: 8 Options
Learn how to integrate Mpesa with a billing system using APIs, gateways, and platforms. Compare 8 top solutions for Kenyan ISPs and find the best fit.

At 8:15 p.m., a customer clears an overdue invoice on M-Pesa and expects the internet back in minutes. Instead, the payment sits in an SMS inbox, the billing record stays open, and the MikroTik session remains suspended until someone notices in the morning. That gap is where revenue gets delayed, support tickets stack up, and churn starts.
For an ISP, learning how to integrate mpesa with a billing system is an operations job as much as a payments job. The work starts at the payment rail, but it only pays off when the billing platform, subscriber account, callback handler, and router policy all agree on the same transaction state. A clean setup turns one customer action into a chain of verified events: payment received, invoice matched, account updated, and service restored or extended.
That full path matters more than the API choice. Direct Daraja integration gives tighter control and fewer intermediaries. A gateway can reduce build time and help with settlement across channels. Router-side modules can speed up deployment, but they often trade away flexibility in reconciliation and failure handling. The right design depends on whether you care most about speed to launch, control over callbacks, or how cleanly payments map back to invoices and MikroTik profiles.
This guide looks at the whole stack, not just collection. It covers the gateway layer, webhook processing, adapter design, reconciliation, reporting, and the network access handoff that closes the loop for an ISP. If you want a practical example of that end-to-end approach, this guide to ISP billing with M-Pesa mobile money integration shows how the payment event connects to subscriber management and service control.
Manual invoicing usually creates the same bottleneck one step earlier. If invoice creation, matching, or follow-up still relies on staff work, these steps for efficient invoice automation are worth reviewing too.
1. Safaricom M-Pesa Daraja API
A customer pays from the self-care portal at 10:14 p.m. If your stack is wired properly, the invoice closes, the account status changes, and MikroTik or RADIUS can permit access again without anyone on your team touching the ticket queue. Daraja is the option for ISPs that want that full path under their own control.
For a Kenyan ISP, the starting point is usually a Safaricom Paybill or BuyGoods till, then access to the Daraja developer portal for API credentials and callback setup. The paperwork and approval steps are part of the job, but the bigger decision is architectural. Direct integration means your billing system owns the payment event from the API layer down to subscriber state, instead of depending on a third party to translate it for you.

What works well
STK Push fits ISP collections because it maps cleanly to an invoice-driven workflow. The billing system can raise a charge, pass the account or invoice reference into the request, and wait for the callback before changing service state. That is a better fit for arrears recovery, renewals, and customer self-service than sending people through a separate payment page with weak reference matching.
The primary value is not the API call itself. The value is what your platform does after the callback arrives. A solid implementation marks the invoice as paid, posts the receipt against the customer ledger, updates the service plan dates, and sends the access change to MikroTik or your RADIUS layer. That end-to-end billing and network-control flow is the part many teams miss. This practical guide to ISP billing with M-Pesa mobile money integration shows how the payment event ties back to subscriber management and service restoration.
One rule saves a lot of support time. Store the M-Pesa receipt number, invoice reference, account identifier, and callback payload hash in one transaction record. If finance can trace a payment but support cannot see which subscriber it affected, reconciliation slows down and reactivations become manual again.
Trade-offs
Daraja gives tighter control than an aggregator, but you also inherit the failure modes. Duplicate callbacks happen. Timeout windows happen. Router updates fail at the worst moment. A payment can be confirmed while the network access change is still pending, which means your billing logic needs a queued retry path instead of assuming one successful webhook closes the whole job.
This route also demands cleaner engineering discipline than many first builds expect:
Reuse OAuth tokens properly: Fetch them on schedule and cache them. Requesting a token for every operation adds avoidable latency and failure points.
Acknowledge callbacks fast: Write the event, return success, then process invoice posting and service activation asynchronously.
Make handlers idempotent: The same receipt or callback can arrive more than once. Your code should recognise that and avoid double-posting a payment.
Separate payment success from service success: Mark the invoice paid when funds are confirmed, then track router or RADIUS actions as a second state.
Log with audit in mind: Keep raw callback payloads, internal status changes, and outbound provisioning attempts for dispute handling and month-end reconciliation.
For operators with in-house development capacity, that trade-off is often worth it. You get cleaner invoice matching, direct callback control, and fewer abstractions between Safaricom, the billing core, and the network edge. For operators that need faster rollout or broader payment rails, the extra control may not justify the build and maintenance overhead.
2. Pesapal M-Pesa Integration SDK
Pesapal makes sense when you need faster merchant onboarding and don't want to build every payment detail around one provider from day one. For many smaller operators, that trade-off is worth it. You give up some low-level control, but you gain a cleaner commercial and operational starting point.
This route is especially practical for ISPs that want M-Pesa plus cards and bank rails behind one adapter. If you're running hotspots in multiple towns, or you're setting up a regional operation that may expand beyond Kenya, an aggregator can keep your billing code simpler.
Where it fits best
A common pattern looks like this. The billing system raises an invoice. Pesapal handles the customer payment interaction. Your application listens for a standardised callback, updates the invoice, and then pushes the account state to MikroTik or your RADIUS layer.
That works well when the actual problem isn't just “take payment”, but “standardise how payment events reach the billing core”. In that setup, the SDK matters less than the event model and dashboard visibility.
What usually works:
Use a single internal payment state model: Map “pending”, “paid”, “failed”, and “reversed” to your own statuses, not the gateway's wording.
Rely on webhooks first: Polling is useful as a fallback, but you don't want your billing loop built around constant status checks.
Match settlement to billing operations: If your finance team closes books on a certain schedule, align gateway settlement reporting with that cadence.
Trade-offs
Aggregators reduce implementation friction, but they add one more dependency between the customer and your ledger. When a payment is delayed or a callback looks wrong, your team may need to check both the gateway dashboard and the billing logs.

I've found this option works best when the ISP wants speed and reporting consistency more than direct Daraja ownership. If your business later needs tighter control over Paybill references, callback validation, or M-Pesa-specific workflows, you can still move to a direct integration with less guesswork because your billing side already speaks in clean payment events.
3. Flutterwave Billing API and partner mobile money rails
Flutterwave is usually a billing-first choice rather than an M-Pesa-first choice. That distinction matters. If your operation needs subscriptions, retry logic, invoicing workflows, and broader regional payment support, Flutterwave can sit above the mobile money rail and manage the commercial lifecycle around it.
For an ISP, that helps when customers don't always pay on the first reminder. The payment problem isn't just collection. It's retries, reminders, account state changes, and deciding when service should stay active, downgrade, or disconnect.
When this approach is useful
This model fits operators with mixed payment channels or cross-border ambitions. A hotspot business that starts in Kenya may later want one billing platform that also handles other markets. A direct Daraja build won't help much there, but a broader billing API may.
The stronger use case is dunning. Your system can create an invoice, trigger the customer payment flow, record partial or failed outcomes, and feed that status into your account policy engine. Then your network layer only reacts to approved billing states instead of reading gateway noise directly.
Use the payment provider to collect money. Use your billing system to decide service policy. Mixing those two responsibilities creates brittle automations.
What to watch
The downside is abstraction. Partner-led mobile money support can hide details that an ISP finance team sometimes needs, especially when reconciling account references or investigating edge cases. If your support desk often asks, “Which invoice did this handset payment clear?”, the integration needs to preserve that metadata cleanly.
What I recommend in this setup:
Push invoice IDs into metadata: Don't rely only on phone numbers to match payments to subscribers.
Keep webhook events authoritative: Status in the dashboard is helpful, but your database should record the event trail.
Route reporting back into the billing core: If billing reports live in one system and payment truth lives elsewhere, disputes take longer to resolve.

For straightforward Kenyan Paybill automation, this can be more platform than you need. For recurring billing across different customer types and payment channels, it can be a sensible layer.
4. MikroTik RouterOS M-Pesa payment modules
A subscriber clears an M-Pesa bill at 8:07 p.m. and immediately starts calling support because the link is still down. That is usually why operators start with RouterOS-side payment modules. The pressure is operational. They want paid customers back online in minutes, not after someone checks a phone and reconnects the session manually.
That instinct is understandable. It also creates problems if RouterOS ends up carrying billing logic it was never built to manage.
MikroTik modules and scripts are useful when the job is narrow. Receive a confirmed payment event, map it to a user, change access state, and write an audit trail somewhere central. For hotspots, prepaid vouchers, and smaller PPPoE deployments, that can remove a lot of repetitive support work.
The best use of RouterOS in an M-Pesa stack is at the enforcement layer, not the finance layer. In a clean ISP design, the payment gateway confirms the transaction, the billing system decides what that payment clears, and MikroTik only applies the resulting policy. That full path matters. It is the difference between a payment integration and an actual billing architecture.
What these modules do well
Most RouterOS payment modules are good at one thing. They shorten the time between confirmed payment and restored service.
Common actions include:
updating a hotspot user or voucher after payment
re-enabling a suspended PPP secret
changing a subscriber profile based on package paid
triggering disconnect or re-auth so the new policy applies immediately
For a small operator, that is often enough to improve collections and reduce support calls. I have seen simple deployments run well for quite a while with this model, especially where products are prepaid and account history is straightforward.
Where operators get into trouble
Problems start when RouterOS scripts become the place where payment truth lives. Comments, scheduler jobs, address lists, and local text files are poor substitutes for invoice records, transaction ledgers, and reconciliation reports.
Three failures show up repeatedly:
payments are matched by phone number only, which breaks when one number pays for multiple accounts
duplicate callbacks or delayed confirmations credit the same customer twice
finance teams cannot trace which payment cleared which invoice without checking the router and the gateway separately
Those are not edge cases. They appear as soon as the network grows, resellers come in, or postpaid billing enters the picture.
A better pattern is simple:
the gateway or webhook handler validates and stores the payment event
the billing core maps that event to the right customer, invoice, or package
MikroTik receives a single access instruction through API or RADIUS
reporting and dispute handling stay in the billing database
If you are building around MikroTik and want the control plane structured properly, this MikroTik RADIUS billing system setup guide is the right reference point. It shows how the network access layer should connect to billing decisions instead of carrying them.
RouterOS should enforce service state. Your billing system should decide why that state changes.
That trade-off is worth being honest about. RouterOS-side modules can get a small ISP operational quickly. They are fast to deploy and cheap to test. But once you need clean reconciliation, package changes, credit control, reseller separation, or audited payment history, keeping M-Pesa logic close to the router stops saving time and starts creating rework.
5. Safaricom M-Pesa webhook and callback handler samples
Most failed integrations don't fail at payment initiation. They fail at the callback layer. The STK Push goes out, the customer pays, then your endpoint mishandles the response, times out, or credits the same transaction twice.
That's why callback handler code matters more than flashy payment screens. In production, the hard part is receiving asynchronous events safely and making sure they update invoices only once.
The core handling pattern
A solid callback handler should do four things in order. Authenticate the inbound request as much as your integration model allows. Persist the raw payload for audit. Check whether the transaction already exists. Then push business logic into a queue or worker.
The Safaricom ecosystem also has operational rules you can't ignore. One verified integration summary notes that webhook security is commonly handled through IP whitelisting to Safaricom IPs and HMAC-SHA256 signatures, with sandbox-to-production transition mandates tightening setups after 2020, as described in Hello Duty's overview of M-Pesa integration and Daraja implementation.
What good handlers do
When I review billing integrations, I look for boring discipline, not cleverness.
Unique database constraints: Use the transaction identifier and receipt number to block double crediting.
Fast HTTP responses: Acknowledge receipt quickly, then do heavier processing asynchronously.
Masked logs: Keep enough payload detail for audits, but don't spray sensitive customer details across logs.
Failure isolation: If invoice posting fails, don't lose the payment event. Park it for retry and investigation.
If your callback path updates the ledger, triggers reconnection, sends SMS, and writes analytics in one synchronous request, you're building a timeout machine.
Code samples are helpful, but only if they show state management, retries, and duplicate protection. A “hello world” webhook isn't enough for an ISP collecting daily subscription payments.
6. Payment gateway adapter pattern
This isn't a vendor. It's the design pattern that keeps your billing system from becoming a hard-coded mess. If you're serious about how to integrate mpesa with a billing system, you need a layer that abstracts payment providers behind one internal contract.
The internal contract can be small. Create payment request. Receive callback. Query status. Record reconciliation data. Trigger refund or disbursement where supported. That's enough for most ISP workflows.
Why this pattern matters
Without adapters, every gateway leaks its naming, payload shapes, and error behaviour into your invoice engine. Then one future change becomes painful. You want your billing core to care about “invoice paid” or “payment pending”, not whether that came from Daraja, Pesapal, or another rail.
This matters even more if your ISP serves different customer segments. A retail hotspot operation may rely on M-Pesa. A corporate account may prefer bank transfer. The billing logic should remain consistent while the adapter changes per payment method.
A useful design rule is to normalise these elements:
Customer reference
Invoice reference
Provider transaction ID
Provider receipt number
Internal payment status
Reconciliation status
For the security side of gateway design, this broader write-up on securely processing credit card and crypto transactions is useful as an architecture reference, even if your immediate focus is M-Pesa.
Trade-offs in practice
The adapter pattern does add development overhead. Small operators often skip it because direct integration feels faster. That's true in the short term. Later, though, every additional gateway becomes a custom project.
I've seen this pattern save teams from rewriting invoice logic when payment needs changed. It also makes staged migration possible. You can start with an aggregator, add direct Daraja later, and keep the rest of the billing application stable.
7. M-Pesa payment reconciliation and reporting scripts
If collection is automated but reconciliation is weak, you still have a finance problem. Payment acceptance and accounting accuracy aren't the same thing. ISPs usually discover this when a customer insists they paid, the service is still off, and support can't quickly prove what happened.
Daily reconciliation scripts solve that. They compare M-Pesa transaction records against invoices, account numbers, subscriber IDs, and posted ledger entries. Then they flag unmatched or duplicate events for review.
Where reconciliation pays off
Mature operations distinguish themselves from improvised ones at this stage. You don't wait for complaints to discover mismatches. You run reconciliation on schedule and review exceptions as part of routine operations.
A verified implementation summary from CRM Africa reports that integrated M-PESA setups for subscription billing have driven a 20% reduction in customer churn linked to billing errors, while daily collection reports via API can yield match rates above 95%, according to CRM Africa's M-Pesa integration discussion for billing systems. Those outcomes make sense because customers rarely complain about the payment rail itself. They complain when the payment and service state don't match.
Scripts worth building
Good reconciliation scripts don't need to be complicated. They need to be predictable.
Normalise phone formats: One customer may appear with different number formats across systems.
Match on account references first: Phone numbers help, but account numbers and invoice IDs are stronger keys.
Keep an exception queue: Unmatched payments shouldn't vanish into email threads.
Export clean finance views: Your accountant and your network admin don't need the same report.
For operators comparing platforms, the Centipid overview of what to look for in an ISP billing system in Kenya is relevant because reconciliation features matter just as much as invoice generation or payment collection.
8. Centipid plus M-Pesa integration blueprint
A common ISP failure looks like this. A customer pays on time, the payment is visible in M-Pesa, but the line stays disconnected because the billing system, callback handler, and MikroTik policy change were never wired into one reliable flow. That is not a payment problem. It is a systems design problem.
For many Kenyan ISPs, the right answer is a reference architecture with clear boundaries between layers. The billing core manages invoices, balances, reminders, service status, and audit history. The payment layer handles collection and callback events. MikroTik enforces access policy after the account state changes in billing. That separation reduces support noise and makes failures easier to trace.
Based on Centipid documentation, Centipid Billing covers the pieces an ISP usually has to stitch together manually: recurring invoicing, automated collection workflows, dunning, subscriber self-service, reporting, and MikroTik integration for PPPoE and hotspot environments. The practical value is not just feature count. It is having one operational system decide when money has been received, which account should be credited, and whether service should stay active, be restored, or remain suspended.
A practical full-stack flow
The clean pattern is straightforward. Centipid creates or tracks the invoice and account reference. The customer pays through the configured M-Pesa route. The callback lands in the billing layer first. Centipid validates the event, posts the payment to the right subscriber account, updates the ledger, and only then sends the access change to MikroTik.
That order protects you in two places. Finance gets a reliable source of truth inside the billing system. Network operations avoid granting service based on an SMS, a partial callback, or an unmatched transaction.
It also helps the people who have to run the operation. Support sees the invoice, payment event, account status, and service action in one record instead of checking a phone, a gateway dashboard, and a router log separately.
The strongest local implementations also use disciplined account mapping. The Lipa na M-Pesa portal setup for ISP account references and payment flows shows the right model. Use Paybill references that point to a subscriber or invoice. Let callbacks update the billing record automatically. Let the billing system trigger restoration after the payment is confirmed and matched.
One design choice matters more than it gets credit for. Do not post payment callbacks directly into MikroTik scripts unless you are running a very small hotspot and accept the operational risk. For a growing ISP, billing has to sit in the middle because it owns customer state, debt logic, partial payments, package changes, and reporting. MikroTik should enforce the decision, not make it.
Start with the subscriber journey and test it end to end. Bill issued. Payment made. Callback received. Account credited. Service state updated. If staff still need to read M-Pesa messages and reconnect users by hand, the integration is incomplete.
M-Pesa Integration: 8-Resource Comparison
Solution | Core features / Capabilities | UX / Reliability (★) | Value & Pricing (💰) | Target audience (👥) | Unique selling points (✨ / 🏆) |
|---|---|---|---|---|---|
Safaricom M-Pesa Daraja API | STK Push, C2B/B2C, webhooks, OAuth, sandbox | ★★★★★ Official SLA, realtime webhooks | 💰 Low tx fees vs aggregators, merchant acct req'd | 👥 Kenyan ISPs, large merchants | ✨ Direct M-Pesa access, 🏆 highest reliability |
Pesapal M-Pesa Integration SDK | Unified API (M-Pesa, cards, bank), checkout UI, auto-reconcile, PCI | ★★★★ Fast onboarding, good dashboard | 💰 Higher fees than direct, saves onboarding time | 👥 Multi-country ISPs, startups | ✨ Multi-gateway, quick merchant activation |
Flutterwave Billing API & M‑Pesa (partners) | Recurring billing, dunning, invoices, tokenization, analytics | ★★★★ Strong billing features & dashboards | 💰 Mid–high fees, reduces bespoke dev cost | 👥 Subscription-focused & multi-country ISPs | 🏆 Subscription automation, multi-currency support |
MikroTik RouterOS M-Pesa Module (3rd‑party) | Real-time activation, voucher/credit apply, PPPoE/hotspot sync, policy control | ★★★ Direct network control, community support | 💰 Low initial cost, higher maintenance risk | 👥 Small ISPs, hotspot operators | ✨ Direct RouterOS service activation, tight access control |
Safaricom M-Pesa Webhook & Callback Samples | HMAC verification, idempotency, retries, multi-lang examples | ★★★★ Battle-tested patterns for reliability | 💰 Free/low cost, speeds dev & sec best practices | 👥 Developers, Centipid integrators | ✨ Secure idempotent handlers, reduces common pitfalls |
Payment Gateway Adapter Pattern (Architecture) | Abstract gateway interface, adapters, routing, unified webhooks | ★★★★ Improves maintainability & testability | 💰 Upfront design cost, long-term save on vendor lock | 👥 ISPs scaling regionally, engineering teams | 🏆 Decouples gateways, simplifies switch/A‑B testing |
M-Pesa Payment Reconciliation & Reporting Scripts | Bulk tx pulls, auto-matching, discrepancy flags, scheduled reports | ★★★★ Critical for financial controls | 💰 High ROI (reduces disputes & leakage) | 👥 Finance teams, multi-location ISPs | ✨ Automates reconciliation, audit-ready trails |
Centipid + M-Pesa Integration Blueprint | End‑to‑end Centipid core + M-Pesa + MikroTik sync, webhooks, reconciliation | ★★★★★ Tailored, production-ready guidance | 💰 High value, speeds integration (2–4 weeks) | 👥 Small–midsize ISPs, WISPs, hotspot operators | 🏆 Complete reference architecture, tested runbooks |
The Final Verdict Your Path to Automated ISP Billing
At this point, the decision is less about who can send an STK Push and more about who owns the full operating flow after the payment lands. For an ISP, that flow starts at the payment rail, passes through billing and reconciliation, and ends at network access control in MikroTik. If any layer is weak, staff step in manually, and the savings from automation disappear fast.
The trade-off is straightforward. Direct Daraja integration gives you control and lower dependency on third parties, but your team must build callbacks, retries, reconciliation, customer balance updates, and service-state logic correctly. Aggregators and billing APIs reduce build time and can widen your payment options, but they add another vendor layer and another place where transaction states can drift. RouterOS-focused modules can work for small deployments, especially where prepaid access is the main model, but they rarely give finance and support a clean system of record on their own.
The architecture that holds up in production keeps responsibilities clear. M-Pesa collects the payment. The billing platform posts the transaction, updates invoice status, applies dunning rules, and records the audit trail. MikroTik enforces the final service decision based on that billing state. Support teams get one place to check account history. Finance gets cleaner reconciliation. Network operations avoid ad hoc reconnect scripts that are hard to test and harder to trust.
Centipid is relevant because it follows that model. As noted earlier, it is built for ISP billing workflows that combine recurring invoicing, payment handling, subscriber management, and MikroTik-linked service control. That matters if the actual job is not just collecting money, but turning payment confirmation into an accurate account update and the correct network action without creating exceptions for staff to clean up later.
Use a simple test when comparing options. Can the setup handle invoice creation, payment collection, callback processing, reconciliation, suspension rules, reactivation, and reporting as one connected process? If the answer is no, you are still assembling tools, not fixing revenue operations.
If you want a billing platform built around that workflow, evaluate Centipid Technologies Ltd. against your current process. Check how it handles billing, M-Pesa events, reconciliation, and MikroTik enforcement before you commit to custom code that may solve one layer and leave the rest for your team to patch by hand.
