Date: Nov 12, 2026

Subject: Building Recurring Billing on M-Pesa Without a Card Network

$ ssh dev@recurring-billing-ke

Connecting to payments stack...

[WARN] No card network detected.

[INFO] M-Pesa STK Push session active.

[INFO] Customer-initiated auth required per transaction.

[TODO] Build recurring billing anyway.

_

Building Recurring Billing on M-Pesa Without a Card Network

Mobile phone with payment app in Nairobi setting

If you've built or sold subscription software in markets where Visa and Mastercard dominate, you already know the pattern: capture a card once, store a token with the processor, and charge it automatically every billing cycle until the customer cancels. It's invisible to the customer after the first transaction. In Kenya, where M-Pesa is the default rail for the overwhelming majority of retail payments, that pattern simply doesn't exist in the same form. There is no "card on file" equivalent that lets you silently pull money from a customer's mobile wallet on a schedule. This single fact shapes almost every architectural decision for SACCOs, clinics, schools, SaaS products, and subscription-based SMEs trying to bill recurring amounts in Kenya.

This article walks through why that gap exists, what tools Safaricom's M-Pesa ecosystem actually gives you to approximate recurring billing, and how to design a system around those constraints rather than pretending they don't exist. It's written for the person who has to actually ship this — a developer at a fintech, an operations manager at a school, or a founder running a SACCO management system — not for someone comparing payment theory in the abstract.

Why Card-Style Recurring Billing Doesn't Translate to M-Pesa

Card networks solve recurring billing through tokenization and merchant-initiated transactions. When a customer enters their card details once, the payment processor exchanges that card number for a token, and critically, grants the merchant permission to initiate future charges against that token without the cardholder re-authenticating each time. The cardholder's bank effectively trusts the merchant (via the network's rules) to charge only what was agreed.

M-Pesa was built around a different trust model: the customer authorizes each transaction individually, typically by entering their PIN on their own device in response to a prompt. This is a deliberate security design, not an oversight. It is part of why mobile money has scaled so widely with relatively low fraud compared to systems built on stored, reusable credentials. But it means that, as a merchant, you cannot simply "charge" a customer's M-Pesa account the way you'd charge a stored card. Every STK Push (the prompt that appears on a customer's phone asking them to enter their M-Pesa PIN) still requires the customer's live participation.

What Safaricom's Daraja Platform Actually Gives You

Safaricom exposes M-Pesa functionality to businesses through the Daraja API platform. If you're building a billing system, you'll typically be working with some combination of Lipa Na M-Pesa Online (commonly called STK Push), C2B (Customer to Business) Paybill or Till integrations, and B2C (Business to Customer) for any refunds or disbursements. There's also M-Pesa Ratiba, Safaricom's standing-order style feature that lets a customer set up a recurring instruction from their own phone to pay a biller on a schedule they define.

The practical distinction that matters for your architecture is this: STK Push is merchant-initiated in the sense that your system triggers the prompt, but the customer must still act on it — enter their PIN, confirm, and have sufficient balance — every single time. M-Pesa Ratiba shifts initiation to the customer's side entirely; they set it up once on their phone, and it fires automatically afterward. Each approach has very different implications for how reliable, visible, and controllable your billing cycle is. Because these features and their exact mechanics change over time, always confirm current capability, limits, and integration requirements directly on the Safaricom Developer Portal before you design around them.

The Core Design Problem You're Actually Solving

Strip away the technical detail and the problem is this: you need predictable, recurring revenue collection, but your payment rail requires a human to approve each transaction in real time. That means your system isn't really "billing" in the card-network sense — it's closer to a disciplined, automated reminder-and-collection workflow with payment confirmation built in. Accepting this early saves you from designing a system that assumes guarantees M-Pesa was never built to give you.

Architectural Patterns That Actually Work

Pattern One: Scheduled STK Push Prompts

The most common approach for subscription businesses — SaaS tools, SACCOs collecting monthly contributions, schools collecting fees in installments — is to schedule an STK Push prompt to fire on the customer's billing date. Your backend holds the subscription schedule, triggers the push at the right time, and listens for the callback confirming success or failure.

What this requires operationally

This sounds simple until you account for real-world conditions: the customer's phone might be off, they might be out of airtime-adjacent network coverage, their M-Pesa balance might be insufficient at that exact moment, or they might simply ignore the prompt because they don't recognize it. You need a retry strategy (sensible spacing, not aggressive re-pushing that annoys customers), a grace period before you consider an account delinquent, and clear customer communication — an SMS or WhatsApp message explaining why the prompt appeared, since unexplained STK prompts are often mistaken for fraud attempts.

Reconciliation is non-negotiable

Every STK Push integration needs a robust callback handler that records the transaction reference, amount, and status from Safaricom's response — and a reconciliation job that cross-checks what you expected to collect against what actually landed in your Paybill or Till account. Power interruptions, timeouts, and delayed callbacks are routine in real deployments, so your system should never assume a callback will arrive promptly or even at all; build a polling or query-based fallback to check transaction status independently.

Pattern Two: Customer-Initiated Standing Orders

Where it fits the use case, pushing customers toward setting up their own standing instruction (such as through M-Pesa Ratiba) shifts both the initiation burden and some of the reliability risk onto a feature Safaricom manages directly on the customer's phone. This tends to work well for fixed, predictable amounts — a SACCO monthly contribution, a fixed school fee installment, a gym membership — where the customer is comfortable setting it up once. It's less suitable where billing amounts vary month to month, since standing orders are typically built around fixed, scheduled amounts rather than dynamic invoicing. Confirm current setup flows, limits, and whether your business category is supported directly with Safaricom, as these details are the kind that change and shouldn't be assumed from general knowledge.

Pattern Three: Paybill-Based Self-Service Payment

The simplest and most battle-tested pattern, especially for smaller businesses without development capacity for push integrations, is a Paybill number paired with an account reference convention — the customer pays whenever reminded, using their own M-Pesa menu, and your system reconciles payments against outstanding invoices using the account number they enter. This isn't glamorous, but it's resilient: it doesn't depend on API uptime, STK Push success rates, or app logic firing correctly. Many clinics, schools, and SACCOs run entirely on this model with a reminder layer (SMS, WhatsApp, phone calls) built on top.

Designing the Billing Logic Around Human-Approved Payments

Decoupling "Invoice Due" from "Invoice Paid"

Because no payment is guaranteed to clear automatically, your data model needs a clear separation between when an amount becomes due and when it's actually confirmed paid. Resist the temptation to treat "billing cycle fired" as equivalent to "payment received." Build explicit states — pending, prompted, confirmed, failed, overdue — and drive your dunning and access-control logic off the confirmed state only, not off the attempt.

Handling Failures Without Frustrating Customers

A failed STK Push isn't necessarily customer intransigence — it's often a timeout, a momentary balance shortfall, or a missed notification. Your retry cadence should be generous enough to avoid looking like harassment, but your communication should be clear about consequences (service suspension, late fees if applicable) so customers aren't caught off guard. For regulated or sensitive sectors — clinics, schools, financial cooperatives — be deliberate about how aggressively you suspend access over a payment delay; reputational and compliance risk from clumsy collections can outweigh the revenue at stake.

Data Protection and Record-Keeping

Any system storing phone numbers, payment histories, and personal identifiers tied to billing falls within the scope of Kenya's data protection framework, overseen by the Office of the Data Protection Commissioner. Keep your data collection proportional to what billing actually requires, secure your transaction logs, and have a clear retention and access policy. If you're a registered business issuing invoices or receipts, also think through how your billing records align with KRA's eTIMS requirements — particularly around what constitutes a valid receipt for a recurring service charge. This is a compliance area worth confirming directly with KRA guidance rather than assuming your invoicing tool handles it correctly out of the box.

Practical Considerations for Small Teams

Build Versus Buy

Several Kenyan fintech and payment-aggregator platforms already offer M-Pesa collection tooling with reconciliation dashboards, which can be far more cost-effective than a small team maintaining their own Daraja integration, retry logic, and reconciliation jobs from scratch. If your core business isn't payments infrastructure, evaluate whether an existing aggregator meets your needs before committing engineering time to building this in-house. Where you do build custom, budget for ongoing maintenance — Safaricom's API behavior, authentication tokens, and callback formats can change, and someone on your team needs to own that relationship.

Forex Exposure on Tooling

If you're layering third-party billing or subscription-management software priced in US dollars on top of your M-Pesa collection, be deliberate about currency exposure. Shilling depreciation against the dollar directly erodes margins on dollar-denominated software costs, so where a comparable KES-priced or locally hosted alternative exists, factor that into your total cost of ownership, not just feature comparisons.

Designing for Connectivity Reality

Power interruptions and inconsistent connectivity are routine, not edge cases, in much of East Africa. Your billing scheduler, callback handlers, and reconciliation jobs should be built to survive restarts and delayed processing gracefully — queue jobs rather than relying on everything executing in a single synchronous pass, and make sure nothing critical depends on a callback arriving within a tight window.

The Honest Takeaway

Recurring billing on M-Pesa isn't a solved problem the way it is on card rails — and treating it as if it were will produce a system that quietly fails customers and revenue targets alike. The more durable approach is to design for what M-Pesa actually offers: customer-approved, prompt-based payments, with reconciliation, retries, and clear communication doing the work that tokenized auto-charging does elsewhere. Build your data model around confirmed payment states, keep your compliance posture current with ODPC and KRA guidance, and choose the collection pattern — scheduled push, standing order, or plain Paybill — that matches your customers' habits rather than the one that looks most elegant on a whiteboard. For anything involving current API behavior, regulatory specifics, or Safaricom product features, verify directly with Safaricom's developer documentation and the relevant regulator before you commit it to production.

Want this handled for you?

We build AI agents and automation for Kenyan businesses — and the infrastructure underneath them. Run the automation scan and find out what's worth building first.

Run the Automation Scan < Back to Blog
SYSTEM INITIALIZATION...

We Engineer Certainty.

GeekforGigs isn't just a consultancy. We are a specialized unit of Cloud Architects and DevOps Engineers based in Nairobi.

We don't believe in "patching" problems. We believe in building self-healing infrastructure that scales automatically.

The Partnership Protocol

We work best with forward-thinking companies tired of manual deployments and surprise AWS bills.

We embed ourselves into your team to automate the boring stuff so you can focus on innovation.

Identify Target Objective

Current System Status?

Where's the manual work happening?

What are you using to manage it today?

> SCAN COMPLETE
AUTOMATION OPPORTUNITY: —

Establish Uplink

Mission parameters received. Enter your details to initialize the request.