The Monnify Bulk Transfer API allows you to send money to multiple recipients in a single request. Each entry in the batch is processed individually, and you receive a consolidated status for the entire batch. This guide walks you through the prerequisites and the full integration flow.
Before integrating the Bulk 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. As part of the email, you will be expected to idemnify Monnify for potential use and misuse of the feature on your platfrom.
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 merge and send the three requests above as a single email. As part of the email, you will be expected to indemnify Monnify for potential use and misuse of the feature as it pertains to your wallet balance with us.
Once your account is set up, here is the typical flow for a bulk transfer:
Make a POST request to the Initiate Transfer (Bulk) API with your batch details. The response will differ depending on whether MFA is enabled on your account.
Before initiating a bulk transfer, use the Name Enquiry API to look up and verify each recipient's account. The name returned should be passed as the destinationAccountName for each entry — submitting a mismatched name will cause that transaction 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/batch \
3--header 'Authorization: Bearer {access_token}' \
4--header 'Content-Type: application/json' \
5--data '{
6 "title": "October Salary Payment",
7 "batchReference": "unique-batch-ref-001",
8 "narration": "October salary disbursement",
9 "sourceAccountNumber": "9999999999",
10 "onValidationFailure": "CONTINUE", //or BREAK.
11 "notificationInterval": 25,
12 "transactionList": [
13 {
14 "amount": 50000.00,
15 "reference": "unique-ref-001",
16 "narration": "Salary - John Doe",
17 "destinationBankCode": "058",
18 "destinationAccountNumber": "0123456789",
19 "destinationAccountName": "John Doe",
20 "currency": "NGN"
21 },
22 {
23 "amount": 75000.00,
24 "reference": "unique-ref-002",
25 "narration": "Salary - Jane Smith",
26 "destinationBankCode": "044",
27 "destinationAccountNumber": "9876543210",
28 "destinationAccountName": "Jane Smith",
29 "currency": "NGN"
30 }
31 ]
32}'The onValidationFailure field expects either BREAK or CONTINUE. BREAK means the request should stop the moment an account validation fails, CONTINUE means to skip the specific account number that failed validation and continue the execution of the request.
Response — MFA enabled (OTP required):
1{
2"requestSuccessful": true,
3"responseMessage": "success",
4"responseCode": "0",
5"responseBody": {
6 "totalAmount": 125000.00,
7 "totalFee": 100.00,
8 "batchReference": "unique-batch-ref-001",
9 "batchStatus": "PENDING_AUTHORIZATION",
10 "dateCreated": "2024-01-15T10:30:00.000+0000",
11 "totalTransactions": 2,
12 "sourceAccountNumber": "9999999999"
13}
14}Response — MFA disabled (batch proceeds immediately):
1{
2"requestSuccessful": true,
3"responseMessage": "success",
4"responseCode": "0",
5"responseBody": {
6 "totalAmount": 125000.00,
7 "totalFee": 100.00,
8 "batchReference": "unique-batch-ref-001",
9 "batchStatus": "AWAITING_PROCESSING",
10 "dateCreated": "2024-01-15T10:30:00.000+0000",
11 "totalTransactions": 2,
12 "sourceAccountNumber": "9999999999"
13}
14}If your account has MFA enabled and you received a PENDING_AUTHORIZATION batch status, you must authorize the batch by submitting the OTP sent to your registered email. Make a POST request to the Authorize Transfer (Bulk) API.
1curl --request POST \
2--url https://sandbox.monnify.com/api/v2/disbursements/batch/validate-otp \
3--header 'Authorization: Bearer {access_token}' \
4--header 'Content-Type: application/json' \
5--data '{
6 "reference": "unique-batch-ref-001",
7 "authorizationCode": "123456"
8}'1{
2"requestSuccessful": true,
3"responseMessage": "success",
4"responseCode": "0",
5"responseBody": {
6 "totalAmount": 125000.00,
7 "totalFee": 100.00,
8 "batchReference": "unique-batch-ref-001",
9 "batchStatus": "AWAITING_PROCESSING",
10 "dateCreated": "2024-01-15T10:30:00.000+0000",
11 "totalTransactions": 2,
12 "sourceAccountNumber": "9999999999"
13}
14}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-batch-ref-001"
7}'To check the status of a batch, make a GET request to the Bulk Transfer Status API with the batch reference.
1curl --request GET \
2--url 'https://sandbox.monnify.com/api/v2/disbursements/batch/summary?batchReference=unique-batch-ref-001' \
3--header 'Authorization: Bearer {access_token}'1{
2"requestSuccessful": true,
3"responseMessage": "success",
4"responseCode": "0",
5"responseBody": {
6 "batchReference": "unique-batch-ref-001",
7 "batchStatus": "COMPLETED",
8 "totalTransactions": 2,
9 "totalAmount": 125000.00,
10 "totalFee": 100.00,
11 "successfulCount": 2,
12 "failedCount": 0,
13 "pendingCount": 0,
14 "dateCreated": "2024-01-15T10:30:00.000+0000",
15 "sourceAccountNumber": "9999999999"
16}
17}To retrieve a paginated list of all individual transactions within a batch and their statuses, make a GET request to the Get Bulk Transfer Transactions API. Provide pageNo (starts at 0) and pageSize as query parameters.
1curl --request GET \
2--url 'https://sandbox.monnify.com/api/v2/disbursements/batch/transactions?batchReference=unique-batch-ref-001&pageNo=0&pageSize=20' \
3--header 'Authorization: Bearer {access_token}'You can retrieve a paginated list of all bulk transfer batches from your account by making a GET request to the Get All Bulk Transactions API. Provide pageNo (starts at 0) and pageSize as query parameters.
1curl --request GET \
2--url 'https://sandbox.monnify.com/api/v2/disbursements/batch/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_AUTHORIZATION | MFA is enabled and the batch 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. |
| AWAITING_PROCESSING | The batch has been authorized and is queued for processing. |
| IN_PROGRESS | The batch is currently being processed. Individual transactions may complete at different times. |
| COMPLETED | All transactions in the batch have been processed. Check individual transaction statuses for results. |
| FAILED_ON_ACCOUNTS_VALIDATION | One or more transactions failed account validation. If |
| FAILED | The batch could not be processed. Check the error message for the reason. |
| Status | Description |
|---|---|
PENDING, AWAITING_PROCESSING and IN_PROGRESS | The transaction is still being processed. Re-query to get the final status. |
| 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?