Back to Blog

Mobile Money Integration: What Changes in Your Product, Not the API

The provider API is about a week of work. The months go into pending payments, reconciliation, retries and the support screens nobody scopes. Here is what belongs in your build plan.

MoyoLab Admin
MoyoLab team
7 min read
Mobile Money Integration: What Changes in Your Product, Not the API

You have decided your app needs to take mobile money. You ask what it costs, and the answer sounds reassuring: the provider has a REST API, a sandbox, maybe an SDK, so the integration is about a week. That estimate is usually right and almost always misleading. Mobile money integration is not mainly an API job. It changes your product, your admin tools and your support work, and that is where the months go.

Here is what actually changes, so you can put it in the brief instead of discovering it in week nine.

The API really is the easy week

What a provider hands you is small: an endpoint that asks a phone number for money, a status endpoint, and a callback URL you expose so they can tell you the result. Your developer wires it up, the sandbox returns success, the demo works.

Then real money meets real networks. The PIN prompt reaches the customer forty seconds late. They are on a bus with one bar of 2G and close the app. Your callback never arrives, or arrives twice. The provider has a bad hour. The customer fat-fingers the PIN, waits, and tries again. None of that is an API problem. All of it is a product problem: what the screen says, what your database believes, and what your support agent can do about it.

A payment is not a function call. It is a conversation between your app, a telco and a person on a bus, and any of the three can stop replying.

Pending is a state, not an error

The most common design mistake is treating a payment as success or failure. There are at least three outcomes, and the third is the frequent one: confirmed, failed, and unknown. Design for unknown first.

  • Create your own payment record, with your own reference, before you call the provider. If that call times out you still know you asked.

  • Never let the phone decide the outcome. The device that started the payment may never come back. Confirmation is settled server-side, by callback or by polling the status endpoint.

  • Poll for a bounded window with backoff, then stop and tell the truth on screen: we are waiting for the network to confirm, you will get a notification, do not pay again.

  • Make the pending screen a real screen, with the order reference and a check again button. Orders stuck silently in pending are where customers either call you or pay twice.

Retry needs a strict definition: retry means ask again about the same payment, never start a new one. One reference per attempt, and the status is checked before any new debit is sent. The most expensive bug in this whole area is a retry that charges a customer twice. The second most expensive is a retry that credits an order twice.

Reconciliation is a feature, not a spreadsheet

Your provider keeps a transaction history. Your app keeps its own records. Every day they disagree a little, and the disagreements are not random. There are four kinds, and each one costs you something different:

  • Paid at the provider, not credited in your app. A lost callback. Costs you an angry customer and a refund conversation.

  • Credited in your app, no money at the provider. A bug, a test payment in production, or a manual credit nobody recorded. Costs you cash.

  • Duplicates. The same order paid twice, usually by a customer who was not told what was happening.

  • Amount mismatches. A fee taken off the top, a partial payment where the provider allows one, or a currency rounded in the wrong direction.

So the product needs a payments record that can be compared, and an admin screen that does the comparing for a date range. Ask to see the field list. Something close to this is a good sign:

payment
  id             your own reference, created before the request
  order_id
  provider       mtn | orange | wave | ...
  payer_number   who actually paid
  amount_minor   integer in the smallest unit, never a float
  currency
  fee_minor      and who absorbed it
  provider_ref   filled in when known
  provider_status  the raw string they sent you
  status         requested | pending | confirmed | failed | reversed
  requested_at / confirmed_at / settled_at

Then name a person and a time of day. Fifteen minutes of reconciliation every morning is cheap. A month-end investigation across thousands of transactions is not, and it always lands in the week you are trying to ship something else.

Confirmed is not the same as settled

A confirmed payment means the customer's money left their wallet. It does not mean it is in your bank account. Settlement happens on the provider's schedule and your contract: same day, next day, or weekly. That gap decides real things. If you pay riders daily, or restock from today's revenue, or promise fast refunds, you need to know the number before you promise anything.

Fees deserve the same attention. They are usually a percentage, sometimes capped, often banded by amount, and sometimes different per provider. Decide early whether you absorb the fee or pass it to the customer, because that decision is visible at checkout and it changes your prices. Changing your mind later means changing your pricing page, your invoices and your margins at once.

If you are building a marketplace or a delivery platform, add one more rule: money that arrives for someone else's sale is a liability, not revenue. Keep seller and rider balances in your own ledger from the first week. Retrofitting that after a few thousand transactions is one of the least pleasant pieces of work we do.

Support is the part nobody scopes

I paid and it is not showing will be your single most common support message, in every market, with every provider. The question is only whether answering it takes two minutes or a developer. Put these in the brief:

  1. Search payments by phone number, by provider reference, by amount, and by time window. Customers will give you any one of the four.

  2. A timeline view of one payment, including the raw responses from the provider.

  3. A re-check with provider button, so an agent can resolve a lost callback without opening a ticket.

  4. A manual credit action that requires a reason and writes an audit record naming the person who used it.

  5. A duplicates view for one order, so a double charge is visible before the customer finds it.

Two details that save a lot of tickets. Send your own confirmation with a short reference by SMS or WhatsApp, because many customers trust a message more than a screen they have already closed. And do not key a customer account to the paying number: the person who pays is often a cousin, a spouse or a shop owner with the only phone with money on it. Store the payer as data on the payment, not as the identity of the account.

What this adds to the quote

When you ask for a price, insist that payments are itemised rather than hidden in one line called payment integration. The line items that matter:

  • the payment record and its state machine

  • the callback endpoint and the polling job

  • the pending and failure screens in the app

  • the admin payments screen, with search and re-check

  • the reconciliation view and manual credit with audit

  • fees, settlement timing and, for marketplaces, balances

  • a live pilot: real SIMs, real small amounts, one run per provider

Budget for that pilot honestly. Sandboxes are polite and fast in a way the live network never is, and every provider has at least one behaviour that only appears with real money. Expect the work around the API to be the larger half of the payments scope. A quote that does not mention reconciliation or support tooling is not cheaper than one that does. It has simply moved those costs to you, after launch, when they are more expensive.

What to do next

  1. Ask your developer for the list of payment states and the field list above. Compare it with what you got.

  2. Decide today who reconciles payments and at what time. Write the name down.

  3. Add the five support actions to the brief before the build starts, not after the first double charge.

  4. Get your provider's settlement window and fee bands in writing, then check your prices still work.

  5. Plan a pilot week with real SIMs on every provider you intend to support.

If you are scoping a product that takes mobile money and want a second opinion on the plan before you commit, talk to us. You can also see how we work on web platforms and mobile apps where payments are the core of the product.

TagsStartupReliabilityMobile AppsPayments
Written by
MoyoLab Admin

Part of the MoyoLab team building AI-powered products and platforms for founders and growing teams.

Share this article