M-Pesa API Integration in Kenya: A Pre-Production Checklist
An M-Pesa integration is not finished when the first payment succeeds in a sandbox. The application also needs a clear payment state, a callback that can be checked safely, a way to reconcile records, and a plan for what staff do when the customer and the system disagree.
Safaricom's Daraja developer portal is the source to use for the available APIs, onboarding steps, and current technical details. The exact flow depends on the product and the organisation's account setup, so treat the portal and the approved API contract as the authority.
1. Choose the payment flow first
Start with the business action, not the endpoint name. Is a customer paying for an order, a school fee, a service booking, a membership contribution, or an invoice? Then decide whether the system needs a customer-initiated request, a payment confirmation, a business disbursement, or a way to query a transaction.
Write down the expected journey in plain language:
- The customer starts the payment.
- The application records a pending transaction.
- The payment provider sends a response or callback.
- The application updates the transaction after checking the result.
- The business process is allowed to continue only when the payment state supports it.
This prevents the payment request, the callback, and the order from becoming three unrelated pieces of code.
2. Give every payment a traceable reference
Create an internal reference before calling the provider. Store the amount, currency, customer reference, account or order, request time, and current status. Do not use a phone number or a customer-entered note as the only identifier.
A useful status model might include pending, completed, failed, cancelled, and needs review. The names are up to the application, but the transitions should be explicit. A completed order should not be created merely because a request was sent.
3. Treat callbacks as untrusted input
The callback endpoint must be reachable by the provider, but that does not mean every request should change a business record. Validate the request according to the current provider contract, check that the reference belongs to a pending transaction, and record the event before applying the business action.
Design for duplicate delivery. A network retry or an application timeout can make the same notification arrive more than once. Processing the same successful callback twice must not create two orders, issue two receipts, or change the balance twice.
Keep credentials and configuration outside the repository. Use separate sandbox and production settings, and avoid placing access tokens, passwords, or raw payment data in logs.
4. Reconcile instead of trusting one screen
A payment dashboard and your database can disagree for ordinary operational reasons. A callback may be delayed, a request may time out after the provider receives it, or a staff member may retry an action without knowing the first request is still being processed.
Provide a reconciliation path for authorised staff. It can show the internal reference, provider reference, amount, status, timestamps, and the last callback received. Where the provider supports a transaction query, use the documented process to investigate a payment that remains in an uncertain state.
Do not silently mark an uncertain payment as successful. Give the team a clear review state and record who resolved it.
5. Test the cases people forget
Before production, test more than a successful payment:
- an invalid or incomplete phone number;
- a rejected or cancelled prompt;
- a timeout after the request is sent;
- a callback received twice;
- a callback for an unknown reference;
- an amount that does not match the order;
- a provider response that arrives after the order has expired;
- a temporary database or queue failure;
- a reconciliation that needs a human decision.
The test should prove both sides of the integration. The payment record must be correct, and the business workflow must respond correctly to each state.
6. Prepare the production handover
Document the credentials, callback URLs, environments, responsible people, alerting, reconciliation steps, and rollback plan. Review the current Daraja production requirements before requesting live access. Confirm the callback URL, certificates or network rules where applicable, and the account details with the people responsible for the payment account.
A small runbook is more useful than a promise that the integration is secure or instant. It gives the team a way to investigate a payment after launch.
Statum builds payment-ready systems and integrations for organisations in Kenya. See the M-Pesa and API integration service, read the Safaricom API documentation, or talk to Statum about an existing system.
A practical next step
Need help applying this to a real system?
Statum can help turn the idea into a scoped piece of work. See our software services, browse completed projects, read the developer documentation, or start a project conversation.
Bob Mwenda
Writers and software engineers at Statum sharing insights on cloud infrastructure, backend services, mobile apps, and developer productivity.