Ghana
The 54Pay Collections API enables merchants to accept mobile money payments in Ghana. For the Ghanaian market, the payment completion workflow is determined by your transaction risk category.
Supported Operators
| Operator | Code |
|---|---|
| MTN | GHMTN |
| AirtelTigo | GHATL |
| Vodafone | GHVOD |
Payment Completion Methods
Understanding your risk category flow is critical for successful integration.
-
High Risk (Gaming) - STK Push
For high-risk traffic, such as those in Gaming, the collection process is a single-step flow. An STK push notification is triggered and sent directly to the customer's mobile device. Once the customer enters their PIN to authorize the payment on their device, the transaction is completed.
Flow: API Request → STK Push to Customer's Device → Customer Authorizes
-
Low Risk (Forex and Remittance) - OTP Verification
For low-risk traffic, such as those in Forex and Remittance, the collection process is a two-step flow. The mobile operator sends an OTP to the customer's mobile number. The merchant must collect this OTP from the customer and include it in a secondary
/complete-payinrequest to finalize the transaction.Flow: API Request → OTP Sent to Customer → Collect OTP from Customer → Call
/collection/v1/complete-payinwith OTP
Authentication
Headers
| Header | Type | Description |
|---|---|---|
| X-module | string | Base64(amount+transactionReference+customerNumber) |
| X-business | string | Base64-encoded Merchant Public Key: {Base64(Merchant Public Key)} |
| Content-Type | string | Must be application/json |
| X-app | string | Must be api |
1. Initiate Collection (High Risk (1) - Gaming)
Creates a payment collection request that triggers an STK push directly to the user's phone.
Endpoint: POST /collection/v1/payin
Request
BASH
curl --location 'https://subsidiary.dev.mypaygate.co/collection/v1/payin' --header 'Accept: application/json' --header 'X-module: {Base64(amount+transactionReference+customerNumber)}' --header 'X-business: {Base64(Merchant Public Key)}' --header 'Content-Type: application/json' --header 'X-app: api' --data-raw '{
"requestHeader": {
"clientId": "",
"requestType": "Collections"
},
"customerName": "Kwame Mensah",
"customerEmail": "kwame@example.com",
"customerNumber": "233550000000",
"transactionReference": "TXN10273646",
"transactionDescription": "Wallet Funding",
"transactionAmount": 200,
"transactionCurrency": "GHS",
"transactionCountry": "GH",
"transactionType": "1", //Gaming
"successUrl": "",
"errorUrl": "",
"cancelUrl": "",
"operatorCode": "GHMTN",
"webhookUrl": ""
}'
Sample Response
JSON
{
"responseDetails": {
"responseCode": "09",
"responseMessage": "PENDING"
},
"transactionReference": "TXN61043784",
"otpIsRequired": false,
"lengthOfOtp": 0,
"paymentCompletionRequired": false,
"redirectionRequired": false
}
2. Initiate Collection (Low Risk (2) - Forex/Remittance)
Initiates the first step of the two-step flow. This request triggers an OTP to be sent to the customer's device.
Endpoint: POST /collection/v1/payin
Request
BASH
curl --location 'https://subsidiary.dev.mypaygate.co/collection/v1/payin' --header 'Accept: application/json' --header 'X-module: {Base64(amount+transactionReference+customerNumber)}' --header 'X-business: {Base64(Merchant Public Key)}' --header 'Content-Type: application/json' --header 'X-app: api' --data-raw '{
"requestHeader": {
"clientId": "",
"requestType": "Collections"
},
"customerName": "Ama Osei",
"customerEmail": "ama@example.com",
"customerNumber": "233550000000",
"transactionReference": "TXN10273646",
"transactionDescription": "Wallet Funding",
"transactionAmount": 200,
"transactionCurrency": "GHS",
"transactionCountry": "GH",
"transactionType": "2", //Forex or Remittance
"successUrl": "",
"errorUrl": "",
"cancelUrl": "",
"operatorCode": "GHVOD",
"webhookUrl": ""
}'
Sample Response
JSON
{
"responseDetails": {
"responseCode": "09",
"responseMessage": "PENDING"
},
"transactionReference": "TXN10273646",
"otpIsRequired": true,
"lengthOfOtp": 6,
"paymentCompletionRequired": true,
"redirectionRequired": false,
"paymentCompletionUrl": "/collection/v1/complete-payin"
}
2.1. Complete Payment (Low Risk (2) - Forex/Remittance)
The mobile operator sends a 6-digit OTP to the customer's mobile number. Collect this OTP and include it in the complete-payin request to finalize the transaction.
Endpoint: POST /collection/v1/complete-payin
Request
Additional Parameter: otpCode (The OTP provided by the customer)
Bash
curl --location 'https://subsidiary.dev.mypaygate.co/collection/v1/complete-payin' --header 'Accept: application/json' --header 'X-module: {Base64(amount+transactionReference+customerNumber)}' --header 'X-business: {Base64(Merchant Public Key)}' --header 'Content-Type: application/json' --header 'X-app: api' --data-raw '{
"requestHeader": {
"clientId": "",
"requestType": "Collections"
},
"customerName": "Ama Osei",
"customerEmail": "ama@example.com",
"customerNumber": "233550000000",
"transactionReference": "TXN10273646",
"transactionDescription": "Remittance Funding",
"transactionAmount": 200,
"transactionType": "2", //Forex or Remittance
"otpCode": "123456",
"transactionCurrency": "GHS",
"transactionCountry": "GH",
"successUrl": "",
"errorUrl": "",
"cancelUrl": "",
"operatorCode": "GHVOD",
"webhookUrl": ""
}'
Webhooks
Payment Status Webhook
The API sends POST requests to your webhookUrl when payment status changes.
Sample Webhook
{
"transaction_reference": "176414160871313",
"transaction_status": "Funds Received",
"transaction_fee": 0,
"amount_received": 50,
"initiated_date": "2025-11-26 08:20:08",
"current_status_date": "2025-11-26 08:29:21",
"received_from": {},
"merchant_reference": "TXN10273646",
"status": "COMPLETED",
"channel": "MOBILE_MONEY",
"currency_code": "GHS"
}
Webhook Status Values
| Status | Description |
|---|---|
| COMPLETED | Payment successfully received |
| FAILED | Payment failed or expired |
Webhook Implementation
Your webhook endpoint must:
- Accept POST requests: Listen for incoming webhook notifications
- Validate payload: Verify merchant_reference matches your records
- Return 200 OK
- Process asynchronously: Handle business logic after responding
- Handle duplicates: Implement idempotency using transaction_reference
Webhook Security
- Verify requests originate from 54Pay IP addresses
- Validate the merchant_reference exists in your system
- Store webhook payloads for audit trail