Payment Collection Flow
Overview
The payment collection flow describes the sequence of API calls, queue messages, and webhook notifications involved when a merchant initiates a charge against a customer's Mobile Money wallet, bank account, card, or USSD session. All four channels share the same /payment/collection entry point. The gateway routes to the correct operator based on the provider field in the request.
Sequence diagram
sequenceDiagram
autonumber
participant M as Merchant App
participant API as Central API
participant Q as Payment Queue
participant GW as Gateway Service
participant MNO as MNO / Bank Operator
participant C as Customer
M->>API: POST /payment/collection<br/>apiToken, amount, phone, provider
API->>API: validate apiToken &<br/>project quota
API-->>M: 201 Created<br/>{ reference, status: PROCESSING }
API->>Q: enqueue collection job
Q->>GW: dispatch to operator module
GW->>MNO: initiate USSD push /<br/>bank BillPay / card 3DS
MNO->>C: prompt (USSD / OTP / PIN)
C-->>MNO: enter PIN / approve
MNO-->>GW: callback with status
GW->>API: update payment + emit event
alt Payment successful
API->>M: webhook POST to merchant URL<br/>{ reference, status: SUCCESSFUL }
else Payment failed / timed out
API->>M: webhook POST to merchant URL<br/>{ reference, status: FAILED, reason }
end
Key endpoints
| Step | Endpoint | Notes |
|---|---|---|
| 1 | POST /payment/collection | Merchant initiates the charge. Returns immediately with status: PROCESSING. |
| 10 | POST <merchant webhook> | Final status push from MALIPOPAY to the merchant's configured webhook URL. |
GET /payment/reference/{reference} | Poll-based status check (fallback if webhook is unavailable). |
Webhook payload
The final webhook POST body follows this shape:
{
"reference": "ML008985",
"status": "SUCCESSFUL",
"amount": 1000,
"currency": "TZS",
"phoneNumber": "255742200105",
"provider": "airtel",
"operatorReference": "AT2026041008152300XJ",
"timestamp": "2026-04-10T08:15:32.000Z"
}
See Webhooks for signature verification and retry semantics.
Timeouts and retries
- USSD push timeout: 90 seconds (customer must complete PIN entry). After that, the operator returns
FAILEDwith reasonTIMEOUT. - Webhook retry: MALIPOPAY retries the webhook up to 5 times with exponential backoff (1s, 5s, 30s, 2m, 10m) until the merchant returns HTTP 2xx.
- Idempotency: repeated
POST /payment/collectioncalls with the samereferencefield return the existing payment without re-charging.