Getting Started
We recommend checking out the introductory section to understand the basics of making transfers first.
Introduction
Mobile money transfers work the same as regular bank account transfers. The key difference is that the account_number is the mobile number on the account (including the country code, like "233"), while the account_bank is a code representing the mobile money operator (for example, "MPS" for M-Pesa). A beneficiary_name is also required so we can identify this account in your list of beneficiaries.
Kenya (M-PESA)
Mobile Money Kenya (M-Pesa) requires you to include the sender's full name as sender, the sender's country as sender_country and the sender's mobile number as mobile_number in the meta object. See Initiate a Transfer for specification
Supported Networks
Here's a list of the currently supported countries and available networks for mobile money:
| Countries/Currencies | Mobile Money options |
|---|---|
| Cameroon (XAF) | MTN, ORANGEMONEY |
| Cote d'Ivoire (XOF) | MOOV, MTN, ORANGE, WAVE |
| Ghana (GHS) | AIRTELTIGO, MTN, Telecel (Vodafone) |
| Kenya (KES) | M-Pesa (MPS) |
| Rwanda (RWF) | MPS, MTN |
| Senegal (XOF) | ORANGEMONEY, WAVE |
| Uganda (UGX) | AIRTEL, MTN |
| Zambia (ZMW) | MPS |
Here's an example of a mobile money transfer:
Javascript
const details = {
account_bank: "MPS",
account_number: "2540782773934",
amount: 1200,
currency: "KES",
beneficiary_name: "Akinyi Kimwei",
meta: {
"sender": "Flutterwave Developers",
"sender_country": "ZA",
"mobile_number": "23457558595"
}
};
await flw.Transfer.initiate(details)
Here's an example of the response you'll get:
Javascript
{
"status": "success",
"message": "Transfer Queued Successfully",
"data": {
"id": 127886,
"account_number": "2540782773934",
"bank_code": "MPS",
"full_name": "Flutterwave Developers",
"created_at": "2020-06-25T14:03:51.000Z",
"currency": "KES",
"amount": 50,
"fee": 45,
"status": "NEW",
"reference": "mk-902837-jk",
"meta": null,
"narration": "New transfer",
"complete_message": "",
"requires_approval": 0,
"is_approved": 1,
"bank_name": "FA-BANK"
}
}
Supported Format
To make a successful M-Pesa(KES), XAF, or XOF transfer request, Pass amount and account_number in the following formats:
- We only support integers for amount.
- account_number is expected to take these forms: 254700000000 or 0700000000.
You'll notice that the data.status for the transfer is "NEW". Remember to set up a webhook or call the get transfer endpoint to find out when the transfer is completed. See Transfers: Overview for more details.
Bulk Transfers
You can also transfer to multiple mobile money accounts at once. See the bulk transfers guide for details.
Country-Specific Guides
For details on how to transfer to each supported country, select your country below:
Egypt
Transfers to Mobile Money wallets in Egypt are not available by default. To enable this feature, submit a request.
Prerequisites
- Complete your KYC verification and confirm that your account is approved for transactions.
- Whitelist your server IP address to prevent security errors.
- Fund your EGP balance. You can do this by:
- Directly funding via collections, this method allows funding up to the equivalent of $1,000.
- Indirect funding via FX conversion from a different currency balance (i.e., wallet-to-wallet transfers).
We currently support two types of Inbound transfers into Egyptian mobile money wallets:
- Class A: global enterprises, not categorised as Money transfer operators.
- Class B: International Money Transfer Operators.
Transfer Settlement Schedule
Transfers are processed Sunday to Thursday, 9 AM to 3 PM (GMT+2). Requests made outside these hours are handled the next working period. Funds settle 24-48 hours after processing.
Payout Flow
Follow these steps to initiate a transfer to an Egyptian Mobile Money Wallet
1. Collect the customer's (payout initiator) and beneficiary's information
Collect the customer's (payout initiator) and beneficiary's information.
Step 1: Collect Customer and Beneficiary information
You'll need the correct information to initiate the transfer. Collect the sender and beneficiary's information, see the list of mandatory and optional parameters below:
| Parameter | Description | Format | isRequired | Payment Rail | Example |
|---|---|---|---|---|---|
| account_number | The beneficiary's bank account number. | String | Yes | Class A / Class B | EGPWALLETS |
| account_bank | The beneficiary's bank code. Query the bank endpoint for a comprehensive list of supported banks | String | Yes | Class A / Class B | “0690000032” |
| amount | The transfer amount. | String | Yes | Class A / Class B | "2000" |
| beneficiary_name | The full name of the transfer beneficiary. | String | Yes | Class A / Class B | “Example User” |
| narration | The transfer's description. | String | No | Class A / Class B | "Test Payment" |
| currency | The transfer currency. This must be EGP. | String | Yes | Class A / Class B | EGP |
| meta | Additional information needed to process the transfer. | Object | Yes | Class A / Class B | N/A |
| meta.beneficiary_address | The Beneficiary's Address. | String | Yes | Class A / Class B | “24 King William Street London” |
| meta.beneficiary_country | The Beneficiary's country. This should be EG. | String | No | Class A / Class B | EG |
| meta.sender | The Sender's full name. | String | No | Class A / Class B | Example User |
| meta.email | The Sender's email address. | String | No | Class B | '[email protected]' |
| meta.sender_email_address | The Sender's email address | String | No | Class A | [email protected] |
| meta.sender_city | The Sender's city | String | Yes | Class A / Class B | "Lagos" |
| meta.sender_mobile_number | The Sender's mobile number. | String | No | Class A / Class B | “01993003333” |
| meta.sender_date_of_birth | The Sender's date of birth. | String | Yes | Class A / Class B | “1990-09-23” |
| meta.sender_id_number | The Sender's ID number. | String | Yes | Class A / Class B | "2231aaa" |
| meta.sender_id_type | The Sender's ID type. | String | Yes | Class A / Class B | "01" |
| meta.sender_id_expiry | The Sender's ID expiration date. | String | Yes | Class A / Class B | “2026-09-23” |
| meta.is_cash_pickup | Specifies if this is a cash pickup transfer. This should be false. | String | No | Class B | false |
| debit_currency | The source currency for the transfer. | String | Yes | Class A | "NGN" |
| meta.transfer_purpose | A brief description of the purpose for the transfer. See full list of supported purposes here . | String | Yes | Class A / Class B | "Medical Bills" |
| meta.beneficiary_id_number | The Beneficiary's ID number | String | Yes | Class A | "28503122500311" |
| meta.beneficiary_mobile_number | The Beneficiary's Mobile number. | String | Yes | Class A / Class B | "01000410066" |
Step 2: Payout to the Customer
Send your payment request with all the needed transfer information to the transfers endpoint to initiate the payout.
Javascript
{
"account_bank": "EGPWALLETS",
"account_number": "1234567",
"amount": 1000,
"narration": "Retest",
"beneficiary_name": "Mohamed Saad Hussein Saad Makarem",
"currency": "EGP",
"debit_currency": "NGN",
"reference": "ST-10001002420",
"meta": [
{
"beneficiary_address": "3057 El-Harameen St, El-Basatin Sharkeya, El Basatin, Cairo Governorate 4236025, Egypt",
"sender_city": "Brighton",
"beneficiary_country": "EG",
"sender_id_number": "B01123075",
"sender_id_type": "01",
"sender_id_expiry": "2027-08-23T00:00:00",
"sender_mobile_number": "441228587691",
"sender_date_of_birth": "1993-12-28T00:00:00",
"sender": "Tubonemi Oruitemeka",
"email": "[email protected]",
"transfer_purpose": "EPFAMT",
"beneficiary_id_number": "28503122500311"
}
]
}
You'll get a response like this:
Javascript
{
"status": "success",
"message": "Transfer Queued Successfully",
"data": {
"id": 326,
"account_number": "1234567",
"bank_code": "EGPWALLETS",
"full_name": "Mohamed Saad Hussein Saad Makarem",
"created_at": "2025-02-24T15:35:35.000Z",
"currency": "EGP",
"amount": 2000,
"fee": 45,
"status": "NEW",
"reference": "ST-10001002420",
"meta": [
{
"BeneficiaryAddress": "24 King William Street London",
"SenderCity": "kakakwa",
"IsCashPickup": false,
"SenderIdNumber": "2231aaa",
"SenderIdType": "PASSPORT",
"Sender": "test",
"SenderIdExpiry": "23/09/2026",
"SenderDateOfBirth": "23/09/2002",
"SenderAddress": "TESt 40",
"SenderMobileNumber": "08110745134",
"SenderNationality": "NG",
"SenderCountry": "NG",
"SenderEmailAddress": null,
"MerchantName": "Daniel ltd",
"BeneficiaryName": "Mohamed Saad Hussein Saad Makarem",
"TransferType": "MOBILE",
"TransferPurpose": "EPFAMT",
"AgentCode": "1",
"AgentLocationCode": "1",
"RouteCode": "BDC"
}
],
"narration": "Retest",
"complete_message": "",
"requires_approval": 0,
"is_approved": 1,
"bank_name": "FA-BANK"
}
}
Step 3: Verify the Payout status
You have different options to verify the transfer status. Here are some quick ways to verify your status:
- If you have webhooks enabled, we'll call your webhook URL with the transfer details when the transfer is completed or fails.
- If you specify a callback_urlwhen creating the transfer, we'll call that URL with the transfer details when the transfer is completed or fails.
- You can manually check the current status of the transfer by polling the get transfer endpoint with the transfer ID.
Sample Response (Webhook)
Javascript
{
"event.type": "Transfer",
"transfer": {
"id": 641173,
"account_number": "0690000040",
"bank_code": "97964560",
"fullname": "NWABALI S",
"date_created": "2024-07-29T13:00:30.000Z",
"currency": "EGP",
"debit_currency": "NGN",
"amount": 100000,
"fee": 45,
"status": "SUCCESSFUL",
"reference": "47b4b1f71065196a",
"meta": null,
"narration": "SAMPLE BDC TRANSFER",
"approver": null,
"complete_message": "Successful",
"requires_approval": 0,
"is_approved": 1,
"bank_name": "First Discount House Limited"
}
}
Testing Transfers
Check our testing guide for details on testing transfers.