M-Pesa Disbursements to Business Central: How to Reconcile Without Re-keying

How Kenyan finance teams can link M-Pesa B2C and B2B disbursements to Microsoft Dynamics 365 Business Central: result callbacks, payment references, OData posting, failed and reversed payments, and month-end reconciliation.

CS
Creodata Solutions Team
September 24, 2026
M-Pesa Disbursements to Business Central: How to Reconcile Without Re-keying

Short answer: To reconcile M-Pesa disbursements with Microsoft Dynamics 365 Business Central without re-keying, make the approved request the single source of both the payment and the ledger entry. Put your own unique reference on every M-Pesa instruction, treat the asynchronous result callback (not the initial response) as the truth, write the M-Pesa transaction ID back to the request, and post to Business Central from that same record over OData. Month-end then becomes a check of exceptions rather than a line-by-line match.

This article is for finance managers, Business Central owners and IT teams at Kenyan organisations that pay staff, field teams or suppliers on M-Pesa and post to Business Central. It is technical enough to brief a developer and plain enough for the finance lead who signs off the reconciliation. Creodata builds expense management software that pays over M-Pesa and posts to Business Central, so we describe our approach near the end.

Why M-Pesa and Business Central drift apart

In most organisations the payment and the posting are two acts by two people:

  1. A request is approved by email or on paper.
  2. Someone sends the money through a gateway or M-Pesa portal and saves the confirmation.
  3. Days or weeks later, someone else keys a journal in Business Central from the voucher.
  4. At month-end, a third person matches the M-Pesa statement to the ledger.

Each hand-off loses information. The M-Pesa statement has a transaction ID, a phone number or till, and an amount. The ledger has an account, a cost centre and a description someone typed. Nothing links them except memory and file names. The fix is structural: the payment and the posting must come from the same record.

M-Pesa B2C vs B2B: which one for which payment?

Safaricom exposes both through its Daraja API and business products, usually reached through a licensed payment gateway.

M-Pesa B2CM-Pesa B2B
PaysAn individual's M-Pesa walletAnother business's paybill or till
Typical useStaff reimbursements, petty cash, field allowances, per-activity paymentsSupplier and vendor payments
Recipient identifierPhone numberPaybill or till number, plus an account reference for paybills
What to captureRecipient name returned by M-Pesa, transaction ID, completion timeTransaction ID, the account reference you sent, completion time
Common failuresUnregistered or wrong number, recipient wallet limits, insufficient float in the paying accountWrong paybill or account reference, insufficient float

Whichever you use, the paying organisation's own business account is the source of funds, never a staff member's phone. That alone fixes most segregation-of-duties findings.

How M-Pesa result callbacks work

The single most common integration mistake is treating the first response as the payment outcome.

When a system sends a B2C or B2B request through Daraja, the immediate reply only says the request was accepted for processing. The actual outcome arrives later, as a callback to a result URL you supplied, with a result code, a description and, on success, the M-Pesa transaction ID. Daraja also asks for a queue time-out URL, which is called if the request expires in the queue. If you use a gateway, it may wrap these callbacks in its own format, but the principle is the same.

That gives three states a request can be in after approval:

  • Sent, awaiting result. Money may or may not have moved. Do not post and do not re-send.
  • Completed. The callback reports success with a transaction ID. Now it is safe to post.
  • Failed or timed out. The callback reports failure, or no result arrives. Investigate before any retry.

Callbacks can be delayed or, occasionally, never arrive. A good integration does not just wait: it runs a status query on requests that have been "sent, awaiting result" for too long, and only then decides whether the payment happened.

Put your own payment reference on every request

Reconciliation is only as good as the key you match on. The M-Pesa transaction ID is created by M-Pesa, so you do not know it until the result arrives. You need your own reference, generated when the request is approved and sent with the payment instruction.

Good practice:

  • One request, one reference. Use the expense request number, or a payment ID derived from it, as the originator reference on the M-Pesa instruction.
  • Never reuse a reference for a retry without first confirming the original failed. Reusing it, or checking it before sending, is how you avoid paying twice.
  • Carry the reference into Business Central as the document number or external document number on the posted entry, alongside the M-Pesa transaction ID.

With both identifiers on the ledger entry, anyone can go from a line on the M-Pesa statement to the approved request and its receipts in one step.

Posting to Business Central over OData

Business Central exposes its data through web services and APIs based on OData. An integration can create journal lines or purchase documents directly, instead of producing a file for someone to import. For M-Pesa disbursements, the questions to settle with your Business Central partner are:

  • Where does the entry land? A general journal batch for M-Pesa payments, a payment journal against a vendor, or a posted purchase document for supplier invoices. Keep M-Pesa payments in their own batch so they are easy to review.
  • Which bank account represents M-Pesa? Most organisations set up the M-Pesa business account as a bank account in Business Central, so payments reduce it and the statement can be reconciled against it.
  • What dimensions travel with the entry? Department, programme, project or cost centre should come from the request, not be typed again.
  • When does posting happen? After the payment result says completed, not at approval. Posting on approval creates entries for money that never left.
  • Where do documents go? Link the receipts or invoice to the entry, so an auditor looking at the ledger can open the evidence.

Handling failed and reversed M-Pesa payments

Failures are where manual processes break, because the obvious fix, sending again by hand, is also how duplicate payments happen.

SituationWhat the system should doWhat finance should see
Result callback reports failureMark the request "payment failed" with the M-Pesa reason; do not postA queue of failed payments to correct and resubmit
No callback within the expected timeRun a status query before anything elseRequests flagged "unconfirmed" until the query answers
Payment succeeded but posting to Business Central failedKeep the payment as completed and hold a posting exceptionA list of paid-but-unposted items, cleared before close
Payment reversed after completionRecord the reversal against the original request and post a reversing entryReversals visible on the request, not only on the statement
Duplicate submission of the same requestRefuse a second payment for a reference already completedNothing, because it never happened

Ask any vendor or developer to demonstrate each row in a test environment. Most integrations handle the happy path well; the difference shows up here.

Month-end reconciliation, step by step

When payment and posting come from the same record, month-end looks like this:

  1. Export the M-Pesa statement for the business account for the period.
  2. Match on transaction ID to the completed requests. This should match almost everything automatically.
  3. Review the exceptions: statement lines with no request (payments made outside the system), requests completed with no statement line, and reversals.
  4. Clear paid-but-unposted items so the Business Central M-Pesa bank account agrees to the statement.
  5. Check charges. M-Pesa transaction charges need their own posting rule so they do not become unexplained differences.
  6. Sign off, with the exception list and its resolution kept as audit evidence.

The goal is that step 3 is short. If it is long, look for payments being made outside the workflow.

Where Creodata fits

Our expense management system is built around this model. Supplier invoices, petty cash and cashbook payments are raised with attachments, approved through a configurable multi-stage chain (for example Head of Department, Finance Reviewer, CFO) with automatic SLA escalation, and paid on final approval:

  • M-Pesa B2C for petty cash and reimbursements, and M-Pesa B2B for supplier payments, through the KentaPay / Eclectics Swivel gateway.
  • Callback and status reconciliation, with the payment reference written back to the request.
  • Posting to Microsoft Dynamics 365 Business Central over OData, with SharePoint document links attached, so nobody re-keys the entry.
  • Every attachment stored in SharePoint Online and linked to the request; sign-in through Microsoft Entra ID; role dashboards and CSV exports for finance and audit.

What we do not do: we post only to Business Central, not to Sage, SAP or other ERPs, and we do not make bank or PesaLink payments. If you need those, ask whether a different tool fits better. For petty cash specifically, see our petty cash management software and the guide to petty cash management in Kenya. For a worked example, read the composite scenario of an NGO that closed the gap between M-Pesa and Business Central.

To see an approved request paid on M-Pesa and posted to Business Central, book a demo.

Frequently asked questions

Can M-Pesa integrate directly with Business Central?

Business Central does not pay over M-Pesa on its own. An integration, either custom or through an expense or payments system, calls M-Pesa through Daraja or a gateway, receives the result callback, and posts to Business Central through its OData web services. The design choice that matters is making one record drive both the payment and the posting.

How do I reconcile M-Pesa B2C payments?

Match the M-Pesa statement to your approved requests on the M-Pesa transaction ID, with your own payment reference as a second key. Then review the exceptions: payments with no request, requests with no payment, reversals and charges. If every payment is triggered from an approved request, almost everything matches automatically.

Why does an M-Pesa payment show as accepted but never complete?

The first response only confirms the request was accepted for processing. The outcome comes later on the result callback. If the callback is delayed or lost, run a transaction status query before retrying, otherwise you risk paying twice.

When should a payment be posted to Business Central?

After M-Pesa confirms the payment completed, not at approval. Posting on approval creates ledger entries for payments that may fail. Keep approved-but-unpaid items in the workflow system until the result arrives.

What is the difference between M-Pesa B2C and B2B for businesses?

B2C sends money from a business account to an individual's M-Pesa wallet, which suits staff reimbursements and petty cash. B2B sends money to another business's paybill or till, which suits supplier payments. Both return a result callback with a transaction ID that should be recorded against the request.

See Expense Management in action.