The first support response should not be “pay again”
When a customer says they completed an M-PESA payment but the merchant cannot see it, the safest first action is to gather evidence and check the existing transaction before creating another payment request.
Step 1: identify the invoice or account
Confirm what the customer was trying to pay: invoice number, member/account number, amount and approximate time.
Do not start by searching only the payer phone number. Someone else may have paid on the customer's behalf.
Step 2: check your own payment-attempt record
- Was an STK request created?
- What is its CheckoutRequestID?
- Did a callback arrive?
- Is the attempt Pending, Unknown, Failed or Succeeded?
If the attempt is already marked successful but the invoice is still due, the problem is probably internal matching/state propagation rather than customer non-payment.
Step 3: query an unresolved STK request
If the customer used M-PESA Express and the callback is missing, query the STK request using M-PESA Express Query and its CheckoutRequestID.
Do not use Transaction Status as the first lookup when you only have the CheckoutRequestID and no M-PESA receipt number.
Step 4: check for a manual PayBill payment
If the customer may have paid manually, search the C2B/provider records using the available M-PESA transaction reference, BillRefNumber, amount and time.
A wrong account reference can cause the money to exist while the invoice remains unmatched.
Step 5: ask for the minimum customer evidence needed
If the structured records are still insufficient, ask for the M-PESA transaction reference and time. Avoid making screenshots the default proof method when the provider record can resolve the case.
Never ask the customer for their M-PESA PIN or OTP.
Step 6: classify the case
- Payment succeeded but invoice was not updated — fix the internal match/state.
- Payment exists with wrong reference — resolve through the exception queue.
- STK request is still unresolved — keep the customer from paying again while you check.
- Provider confirms failure — offer a valid new payment path.
- No evidence of payment — explain the next payment action clearly.
Step 7: close the loop with the customer
Once payment is confirmed, stop reminders and update service or membership state according to the merchant policy. Finance reconciliation can continue separately.
When to escalate
- Provider query and merchant records disagree.
- A customer presents a receipt reference that cannot be found.
- Two successful payments appear against one invoice.
- The issue affects many customers at once.
- The payment is old enough that normal status-query paths no longer resolve it.
The developer-facing article on asynchronous payment state covers the underlying state machine. This article is the support/front-desk procedure.
Sources
- Safaricom M-PESA Express Query API: https://developer.safaricom.co.ke/apis/MpesaExpressQuery
- Safaricom Customer to Business API: https://developer.safaricom.co.ke/apis/CustomerToBusiness
- Safaricom Transaction Status API: https://developer.safaricom.co.ke/apis/TransactionStatus



