Direct Send Money
Disburse funds directly to a customer's Mobile Money wallet instantly via API.
Direct Send Money
The Direct Send Money API allows merchants to programmatically disburse funds directly from their Xtopay Disbursement Account to any customer's Mobile Money wallet. This is ideal for payouts, customer refunds, withdrawals, affiliate commission payouts, cashbacks, and any other automated disbursement flow.
Supported Channels
Xtopay supports direct disbursements across the following networks:
| Mobile Money Provider | Channel Identifier | Country |
|---|---|---|
| MTN Mobile Money | mtn-gh | Ghana |
| Telecel Cash | vodafone-gh | Ghana |
| AT Money (AirtelTigo) | tigo-gh | Ghana |
Disbursement Account Funding
To disburse payments via the Direct Send Money API, your business must maintain an active balance in your Disbursement Account.
You can fund your Disbursement Account via one of two methods:
- Online Funding: Fund it using bank transfer or card payment from your merchant dashboard.
- Balance Transfer: Instantly transfer settled funds from your Xtopay Collection Account to your Disbursement Account.
For detailed custom limits or support, please contact your Xtopay Account / Relationship Manager.
Business IP Whitelisting
[!WARNING] Whitelisting Required Direct Send Money endpoints are live and require strict IP whitelisting. Requests from non-whitelisted IP addresses will return a
403 Forbiddenerror or timeout.Please submit your production server public IP addresses to your Xtopay Retail Systems Engineer for whitelisting. We permit a maximum of four (4) IP addresses per service key.
Understanding the Service Flow
The Direct Send Money process is asynchronous. When you send money, Xtopay processes and forwards the request to the mobile money networks. The final delivery status is usually resolved within 30 seconds.
Service Steps
| Step | Description |
|---|---|
| 1 | Your server makes a Send Money request to POST /v1/payments/send. |
| 2 | Xtopay validates the credentials and disbursement balance, debits the account, and returns a pending status PROCESSING (ResponseCode 0001). |
| 3 | Xtopay dispatches the funds to the mobile wallet. |
| 4 | Once confirmed by the carrier, Xtopay dispatches an HTTP POST webhook callback containing the final state. |
| 5 | If no callback is received within five (5) minutes of initiation, query the Transaction Status Check API (GET /v1/payments/:reference) to verify. |
Direct Send Request Flow
sequenceDiagram
autonumber
actor Customer
participant AppServer as Merchant Server
participant Xtopay as Xtopay API
participant Telco as Telco Gateway
AppServer->>Xtopay: POST /v1/payments/send (Auth: Bearer secret_key)
Xtopay-->>AppServer: Return processing response (ResponseCode 0001)
Xtopay->>Telco: Forward payout request
Telco-->>Customer: Funds deposited in recipient wallet
Telco-->>Xtopay: Payout settlement confirmation
Xtopay->>AppServer: Send Webhook Callback (POST payment.succeeded)
Note over AppServer, Xtopay: Fallback: Check status via GET /v1/payments/:reference if callback failsAPI Reference
To initiate a payout transaction, send an HTTP POST request to the endpoint below.
| Detail | Description |
|---|---|
| API Endpoint | https://api.xtopay.co/v1/payments/send |
| Request Type | POST |
| Content Type | application/json |
| Authentication | Basic Base64(clientId:clientSecret) |
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
amount | Integer | Yes | Specifies the total amount to disburse in minor units (e.g. 20000 = GHS 200.00). Decimals are not allowed. |
currency | String | No | Three-letter ISO 4217 currency code (e.g. GHS, NGN, USD). Defaults to GHS. |
phone | String | Yes | The recipient's mobile wallet number in international format (e.g. 233200000000 or +233200000000). |
provider | String | Yes | The provider code channel identifier. Available channels: MTN, TELECEL, AIRTELTIGO. |
name | String | Yes | The recipient name matching their mobile wallet profile. The phone number can be passed as a placeholder if name is unknown. |
description | String | Yes | Transaction details displayed to the recipient on wallet logs. |
customerId | String | No | Optional Xtopay customer ID to associate the payout with. |
metadata | Object | No | Flat JSON key-value store to attach merchant references (e.g. { "clientReference": "3jL2KlUy3vt21" }). |
Response Parameters
| Parameter | Type | Description |
|---|---|---|
success | Boolean | Indicates if the payout request was accepted successfully. |
data | Object | Payload containing disbursement details. |
data.id | String | Unique transaction ID generated by Xtopay. |
data.reference | String | Unique transaction reference string. |
data.amount | Integer | Payout amount in minor units. |
data.fee | Integer | Platform processing fee in minor units. |
data.status | String | Status of the disbursement (always PROCESSING). |
data.phone | String | Ingested recipient phone number. |
data.name | String | Recipient wallet name. |
data.createdAt | String | ISO 8601 creation timestamp. |
Code Examples
curl https://api.xtopay.co/v1/payments/send \
-u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"amount": 80,
"currency": "GHS",
"phone": "233200000000",
"provider": "TELECEL",
"name": "Joe Doe",
"description": "Union Dues Payout",
"metadata": {
"clientReference": "3jL2KlUy3vt21"
}
}'Sample Response
200 OK
{
"success": true,
"responseCode": "0001",
"data": {
"id": "pay_09f84e20a283942e807128e8c21d0303",
"reference": "3jL2KlUy3vt21",
"status": "PROCESSING",
"amount": 80,
"fee": 0,
"currency": "GHS",
"phone": "233200000000",
"name": "Joe Doe",
"createdAt": "2026-06-06T12:00:00Z"
}
}Webhook Callback
Xtopay dispatches callback webhook alerts to your registered URL once the payout is finalized by the telco gateway.
Sample Callback (Successful)
{
"ResponseCode": "0000",
"Data": {
"AmountDebited": 80,
"TransactionId": "09f84e20a283942e807128e8c21d0303",
"ExternalTransactionId": "142116938399",
"Description": "Telecel Cash payment has been made successfully",
"ClientReference": "3jL2KlUy3vt21",
"Amount": 80,
"Charges": 1,
"Meta": null,
"RecipientName": "Joe Doe"
}
}Sample Callback (Failed)
{
"ResponseCode": "4075",
"Data": {
"AmountDebited": 80,
"TransactionId": "08f84e20a283942e807128e8c21d0302",
"ExternalTransactionId": null,
"Description": "Insufficient prepaid balance.",
"ClientReference": "3jL2KlUy3vt21",
"Amount": 80,
"Charges": 0,
"Meta": null,
"RecipientName": null
}
}Transaction Status Check
Checks the status of a send transaction. It is mandatory to implement this check to verify the final transaction state if no webhook callback is received within 5 minutes of initiation.
To poll the status, send an HTTP GET request appending the unique client reference.
| Detail | Description |
|---|---|
| API Endpoint | https://api.xtopay.co/v1/payments/:reference |
| Request Type | GET |
| Content Type | application/json |
| Authentication | Basic Base64(clientId:clientSecret) |
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
:reference | String | Yes | The client reference of the transaction (3jL2KlUy3vt21). |
Sample GET Request
curl https://api.xtopay.co/v1/payments/3jL2KlUy3vt21 \
-u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET"Sample Response (Succeeded)
200 OK
{
"ResponseCode": "success",
"data": {
"TransactionId": "09f84e20a283942e807128e8c21d0303",
"networkTransactionId": "142116938399",
"Amount": 80,
"Fees": 1,
"ClientReference": "3jL2KlUy3vt21",
"Channel": "vodafone-gh",
"CustomerNumber": "233200000000",
"transactionStatus": "success",
"CreatedAt": "2026-06-06 12:00:00"
}
}Response Codes & Actions
| Response Code | Description | Required Action |
|---|---|---|
0000 | Payout has been completed successfully. | None. Update the transaction as successful in your local logs. |
0001 | Payout request accepted. Webhook will be sent once processed. | Mark the payout as pending. Wait for the webhook callback. |
2001 | payment failed (e.g. invalid recipient wallet number, duplicate client reference). | Verify the recipient number or review if the reference was previously used. |
3050 | mobile number is not registered for Mobile Money payouts. | Verify the number with the customer and ensure the correct network provider. |
4000 | Validation errors. Request payload contains incorrect parameters. | Inspect the request parameter schemas and try again. |
4075 | Insufficient prepaid balance. | Top up your Disbursement Account balance from your Xtopay dashboard. |
5000 | Internal error. Xtopay or carrier gateway is undergoing maintenance. | Retry in a few minutes or contact Xtopay support. |
How is this guide?