The Monnify Single Transfer API allows you to send money directly to a bank account or mobile wallet in real time. This guide walks you through the prerequisites and the full integration flow.
Before integrating the Single Transfer API, make sure you have completed the following steps:
Though Disbursements is enabled by default on Sandbox environment, it is disabled on live environment. You must request activation on Live environment by contacting [email protected] to get this enabled before you can make any transfer requests.
For security on Live environment, Monnify only processes disbursement requests from whitelisted IP addresses. You must provide the static IP address(es) of your server(s) to Monnify before going live. If your IP is not whitelisted, all disbursement requests will be rejected with a D06 error. Send your IP address(es) to [email protected] to get them added.
Multi-Factor Authentication (MFA) via OTP is enabled by default for all disbursement accounts in both Sandbox and Live instances. When MFA is active, each transfer request will return a PENDING_AUTHORIZATION status and require you to submit an OTP before the transfer is processed. The OTP is sent to the registered email address on your Monnify account.
If your integration handles transfers programmatically and you do not need OTP authorization, you can request for MFA to be disabled by contacting [email protected].
You can send merge and send the three requests above as a single email. As part of the email, you will be expected to idemnify Monnify for potential use and misuse of the feature on your platfrom.
Once your account is set up, here is the typical flow for a single transfer:
Make a POST request to the Initiate Transfer (Single) API with your transfer details. The response will differ depending on whether MFA is enabled on your account.
Before initiating a transfer, use the Name Enquiry API to look up and verify the recipient's account. The name returned should be passed as the destinationAccountName in your request — submitting a mismatched name will cause the transfer to fail. To get the correct destinationBankCode, use the Get Banks API to retrieve the full list of supported banks and their codes.
1curl --request POST \
2--url https://sandbox.monnify.com/api/v2/disbursements/single \
3--header 'Authorization: Bearer {access_token}' \
4--header 'Content-Type: application/json' \
5--data '{
6 "amount": 500.00,
7 "reference": "unique-ref-001",
8 "narration": "Payment for services rendered",
9 "destinationBankCode": "058",
10 "destinationAccountNumber": "0123456789",
11 "destinationAccountName": "John Doe",
12 "currency": "NGN",
13 "sourceAccountNumber": "9999999999"
14}'Response — MFA enabled (OTP required):
1{
2"requestSuccessful": true,
3"responseMessage": "success",
4"responseCode": "0",
5"responseBody": {
6 "amount": 500.00,
7 "reference": "unique-ref-001",
8 "status": "PENDING_AUTHORIZATION",
9 "dateCreated": "2024-01-15T10:30:00.000+0000",
10 "totalFee": 10.75,
11 "destinationAccountName": "John Doe",
12 "destinationAccountNumber": "0123456789",
13 "destinationBankCode": "058",
14 "destinationBankName": "GTBank"
15}
16}Response — MFA disabled (transfer proceeds immediately):
1{
2"requestSuccessful": true,
3"responseMessage": "success",
4"responseCode": "0",
5"responseBody": {
6 "amount": 500.00,
7 "reference": "unique-ref-001",
8 "status": "SUCCESS",
9 "dateCreated": "2024-01-15T10:30:00.000+0000",
10 "totalFee": 10.75,
11 "destinationAccountName": "John Doe",
12 "destinationAccountNumber": "0123456789",
13 "destinationBankCode": "058",
14 "destinationBankName": "GTBank"
15}
16}If your account has MFA enabled and you received a PENDING_AUTHORIZATION status, you must authorize the transfer by submitting the OTP sent to your registered email. Make a POST request to the Authorize Transfer (Single) API.
1curl --request POST \
2--url https://sandbox.monnify.com/api/v2/disbursements/single/validate-otp \
3--header 'Authorization: Bearer {access_token}' \
4--header 'Content-Type: application/json' \
5--data '{
6 "reference": "unique-ref-001",
7 "authorizationCode": "123456"
8}'1{
2"requestSuccessful": true,
3"responseMessage": "success",
4"responseCode": "0",
5"responseBody": {
6 "amount": 500.00,
7 "reference": "unique-ref-001",
8 "status": "SUCCESS",
9 "dateCreated": "2024-01-15T10:30:00.000+0000",
10 "totalFee": 10.75,
11 "destinationAccountName": "John Doe",
12 "destinationAccountNumber": "0123456789",
13 "destinationBankCode": "058",
14 "destinationBankName": "GTBank"
15}
16}If the OTP was not received or has expired, you can request a new one via the Resend OTP API.
1curl --request POST \
2--url https://sandbox.monnify.com/api/v2/disbursements/single/resend-otp \
3--header 'Authorization: Bearer {access_token}' \
4--header 'Content-Type: application/json' \
5--data '{
6 "reference": "unique-ref-001"
7}'By default, Monnify processes transfers synchronously and your server waits for a final status. If you prefer not to block your server, you can process transfers asynchronously by setting async to true in your request. Monnify will send the final status to your webhook URL once the transfer is processed.
1curl --request POST \
2--url https://sandbox.monnify.com/api/v2/disbursements/single \
3--header 'Authorization: Bearer {access_token}' \
4--header 'Content-Type: application/json' \
5--data '{
6 "amount": 500.00,
7 "reference": "unique-ref-async-001",
8 "narration": "Async payment for services",
9 "destinationBankCode": "058",
10 "destinationAccountNumber": "0123456789",
11 "destinationAccountName": "John Doe",
12 "currency": "NGN",
13 "sourceAccountNumber": "9999999999",
14 "async": true
15}'You can specify the actual sender's details on a transfer so that the recipient's bank statement shows the real sender rather than your business name. This is particularly useful for platforms that process transfers on behalf of other parties. Include a senderInfo object in your request payload.
1curl --request POST \
2--url https://sandbox.monnify.com/api/v2/disbursements/single \
3--header 'Authorization: Bearer {access_token}' \
4--header 'Content-Type: application/json' \
5--data '{
6 "amount": 500.00,
7 "reference": "unique-ref-002",
8 "narration": "Payment from Acme Ltd",
9 "destinationBankCode": "058",
10 "destinationAccountNumber": "0123456789",
11 "destinationAccountName": "John Doe",
12 "currency": "NGN",
13 "sourceAccountNumber": "9999999999",
14 "senderInfo": {
15 "senderName": "Acme Ltd",
16 "senderAccountNumber": "1234567890",
17 "senderBankCode": "057"
18 }
19}'To check the status of a transfer, make a GET request to the Single Transfer Status API with the transaction reference.
1curl --request GET \
2--url 'https://sandbox.monnify.com/api/v2/disbursements/single/summary?reference=unique-ref-001' \
3--header 'Authorization: Bearer {access_token}'1{
2"requestSuccessful": true,
3"responseMessage": "success",
4"responseCode": "0",
5"responseBody": {
6 "amount": 500.00,
7 "reference": "unique-ref-001",
8 "narration": "Payment for services rendered",
9 "currency": "NGN",
10 "fee": 10.75,
11 "twoFaEnabled": false,
12 "status": "SUCCESS",
13 "transactionDescription": "Transfer Successful",
14 "transactionReference": "MONNIFY_TRX_REF_001",
15 "createdOn": "2024-01-15T10:30:00.000+0000",
16 "destinationAccountNumber": "0123456789",
17 "destinationAccountName": "John Doe",
18 "destinationBankCode": "058",
19 "destinationBankName": "GTBank"
20}
21}You can retrieve a paginated list of all single transfers from your account by making a GET request to the Get All Single Transactions API. Provide pageNo (starts at 0) and pageSize as query parameters.
1curl --request GET \
2--url 'https://sandbox.monnify.com/api/v2/disbursements/single/list?pageNo=0&pageSize=20' \
3--header 'Authorization: Bearer {access_token}'To search across all your disbursement transactions, make a GET request to the Search Disbursement Transactions API. You can filter by reference, status, date range, and more.
You can check the available balance in your Monnify disbursement wallet at any time by making a GET request to the Wallet Balance API.
1curl --request GET \
2--url 'https://sandbox.monnify.com/api/v2/disbursements/wallet-balance?accountNumber=9999999999' \
3--header 'Authorization: Bearer {access_token}'1{
2"requestSuccessful": true,
3"responseMessage": "success",
4"responseCode": "0",
5"responseBody": {
6 "availableBalance": 24500.00,
7 "ledgerBalance": 25000.00,
8 "accountNumber": "9999999999",
9 "currency": "NGN"
10}
11}| Status | Description |
|---|---|
PENDING, AWAITING_PROCESSING and IN_PROGRESS | The transaction is still being processed. Re-query to get the final status. |
| PENDING_AUTHORIZATION | MFA is enabled and the transfer is waiting for OTP authorization before it can be processed. |
| OTP_EMAIL_DISPATCH_FAILED | Monnify could not send the OTP email. Use the Resend OTP API to request a new one. |
| SUCCESS and COMPLETED | The disbursement was processed successfully and the recipient has been credited. |
| REVERSED | The disbursement was reversed. The funds have been returned to your wallet. |
| FAILED | The disbursement was not successful. Check the error message for the reason. |
| EXPIRED | The transaction was not authorized within its validity period. Initiate a new transfer. |
| Error Code | Meaning | Recommended Action |
|---|---|---|
| 99 | An unexpected error occurred while processing the transaction. | Re-query to confirm the transaction status before retrying. |
| D01 | Something went wrong and the transaction could not be processed. The actual error will be in the | Treat as Failed. |
| D02 | Transaction does not exist. | Treat as Failed. |
| D03 | Invalid account details supplied. | Treat as Failed. |
| D04 | Insufficient wallet balance. | Top up your Monnify wallet and retry. |
| D05 | The reference supplied has already been used for a previous transaction. | Retry with a new unique reference. |
| D06 | Unauthorized request. The request originated from an IP address that is not whitelisted. | Send your server IP address to [email protected] for whitelisting. |
| D07 | Duplicate request. A transfer to the same account for the same amount was made within a 2-minute window. | Retry after 2 minutes, or contact [email protected] to disable duplicate detection. |
| Invalid destination account number | The account number did not pass name enquiry validation. | Ask the customer to provide a valid account number. |
| Dormant beneficiary account | The recipient's account is dormant. | The customer should contact their bank. |
| Beneficiary account name mismatch | The account name does not match the account number. | Ask the customer to reconfirm their account details. |
| Unknown destination bank code | The bank code supplied is not recognized on Monnify. | Confirm the correct |
Transaction timed out while waiting for destination bank | The recipient's bank did not respond in time. | Re-query the transaction status. |
| Invalid amount | The transaction amount is invalid. | Confirm the transaction amount and retry. |
| Delayed processing from NIP | Delay from the NIP (interbank network). | Re-query the transaction status. |
Post No Credit restriction on beneficiary account | The recipient's account has a Post No Debit (PND) restriction and cannot be credited. | The customer should contact their bank. |
| Beneficiary bank not available | The recipient's bank is currently unavailable. | Re-query the transaction status. |
| Invalid session ID | The session ID for the transaction is invalid. | Re-query the transaction status. |
Rejected by destination institution | The credit was rejected by the recipient's bank. | The customer should contact their bank to find out the reason. |
| Suspected fraud | The recipient's account is under investigation for fraud. | The customer should contact their bank. |
Invalid response code from beneficiary institution | An unrecognized response code was received from the recipient's bank. | Re-query the transaction status. |
System malfunction by destination institution | The recipient's bank is experiencing a system issue. | Re-query the transaction status. |
| Beneficiary account limit exceeded | The recipient's account is a low-KYC account and cannot receive the transfer amount. | The customer should contact their bank to upgrade their account tier. |
Sender not permitted to credit beneficiary | The recipient's account has a restriction that prevents it from being credited. | The customer should contact their bank to identify and resolve the restriction. |
Unable to complete the transaction at this time | The recipient's bank or payment provider is currently unavailable. | Re-query the transaction status. |
Transaction could not be processed at this time. Please try again | The payment provider is currently unavailable. | Re-query the transaction status. |
| Transaction processing in progress | The transaction is still being processed. | Re-query the transaction status. |
Account number could not be validated | Name enquiry failed — the account number may be invalid or the destination bank is unavailable. | Reconfirm the destination account details and check bank availability. |
| Transaction Failed | The transaction failed due to a system or provider error. | Contact Monnify support. |
System Malfunction - Internal service failure | The transaction failed due to an internal Monnify error. | Contact Monnify support. |
System Malfunction - Transaction transmission unsuccessful | The transaction failed due to a system malfunction during transmission. | Contact Monnify support. |
Processor Malfunction - Transaction transmission failed | An error occurred during transaction processing with NIBBS. | Re-query the transaction status. |
How would you rate your experience?