Bulk Transfers

Transfer funds to multiple recipients using bulk transfers.

📘

Getting Started

We recommend checking out the introductory section to understand the basics of making transfers first.

You can send money to multiple recipients in a single request using the bulk transfer endpoint.

Making a Bulk Transfer

Provide an array of objects called bulk_data. Each object contains the details for an individual transfer, similar to the details you provide when making a single transfer. Bulk transfers can be sent to either bank accounts, or mobile money accounts.

You can also specify a titleto identify the batch of transfers. This helps you easily identify what a set of payments was for.

const details = {
    title:  "Staff salary for April",
    bulk_data: [
        {
            bank_code: "044",
            account_number: "0690000031",
            amount: 690000,
            currency: "NGN",
            narration: "Salary payment for April",
        },
        {
            bank_code: "044",
            account_number: "0690000032",
            amount: 500000,
            currency: "NGN",
            narration: "Salary payment for April",
        }
    ]
};
const response = await flw.Transfer.bulk(details);
$details = [
    "title" =>  "Staff salary for April",
    "bulk_data" => [
        [
            "bank_code" => "044",
            "account_number" => "0690000031",
            "amount" => 690000,
            "currency" => "NGN",
            "narration" => "Salary payment for April",
        ],
        [
            "bank_code" => "044",
            "account_number" => "0690000032",
            "amount" => 500000,
            "currency" => "NGN",
            "narration" => "Salary payment for April",
        ]
    ]
];
$response = $transferService->bulkTransfer($details);
details = {
    title:  "Staff salary for April",
    bulk_data: [
        {
            bank_code: "044",
            account_number: "0690000031",
            amount: 690000,
            currency: "NGN",
            narration: "Salary payment for April",
        },
        {
            bank_code: "044",
            account_number: "0690000032",
            amount: 500000,
            currency: "NGN",
            narration: "Salary payment for April",
        }
    ]
}
response = transfer.initiate_bulk_transfer(details)
details = {
    "title":  "Staff salary for April",
    "bulk_data": [
        {
            "bank_code": "044",
            "account_number": "0690000031",
            "amount": 690000,
            "currency": "NGN",
            "narration": "Salary payment for April",
        },
        {
            "bank_code": "044",
            "account_number": "0690000032",
            "amount": 500000,
            "currency": "NGN",
            "narration": "Salary payment for April",
        }
    ]
}
res = rave.Transfer.bulk(details)
details := rave.BulkPaymentData {
    Title:       "Staff salary for April",
    AccountBank: "044",
    BulkData:    []map[string]string{
                    {
                        "Bank":           "044",
                        "Account Number": "0690000031",
                        "Amount":         690000,
                        "Currency":       "NGN",
                        "Narration":      "Salary payment for April",
                    },
                    {
                        "Bank":           "044",
                        "Account Number": "0690000032",
                        "Amount":         500000,
                        "Currency":       "NGN",
                        "Narration":      "Salary payment for April",
                    },
                },
}
err, response := transfer.InitiateBulkTransfer(details)
curl --location --request POST 'https://api.flutterwave.com/v3/bulk-transfers/' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_SECRET_KEY' \
--data-raw '{
    "title":  "Staff salary for April",
    "bulk_data": [
        {
            "bank_code": "044",
            "account_number": "0690000031",
            "amount": 690000,
            "currency": "NGN",
            "narration": "Salary payment for April"
        },
        {
            "bank_code": "044",
            "account_number": "0690000032",
            "amount": 500000,
            "currency": "NGN",
            "narration": "Salary payment for April"
        }
    ]
}'

You'll get a response like this:

{
    "status": "success",
    "message": "Bulk transfer queued",
    "data": {
        "id": 26805,
        "created_at": "2026-10-08T16:20:02.000Z",
        "approver": "N/A"
    }
}

The transfers are queued for processing, which usually takes between a few seconds and a few minutes.

Checking the Status

Each transfer in the batch is processed individually. If you have webhooks enabled, you'll receive a notification for each transfer when it succeeds or fails.

{
  "event": "transfer.completed",
  "event.type": "Transfer",
  "data": {
    "id": 2245702,
    "account_number": "0690000031",
    "bank_name": "ACCESS BANK NIGERIA",
    "bank_code": "044",
    "fullname": "Forrest Green",
    "created_at": "2026-10-09T14:47:10.000Z",
    "currency": "NGN",
    "debit_currency": null,
    "amount": 690000,
    "fee": 53.75,
    "status": "SUCCESSFUL",
    "reference": "ac24db195edf7529_PMCKDU_5",
    "meta": null,
    "narration": "Salary payment for April",
    "approver": null,
    "complete_message": "Successful",
    "requires_approval": 0,
    "is_approved": 1
  }
}

You can also retrieve the individual transfers in a batch using the get bulk transfer endpoint with the batch_id query parameter.

curl --request GET \
  --location 'https://api.flutterwave.com/v3/transfers?batch_id=26805' \
  --header 'Authorization: Bearer {{YOUR_SECRET_KEY}}'

The batch_id is the data.id returned in the initiate bulk transfer response:

{
    "status": "success",
    "message": "Transfers fetched",
    "meta": {
        "page_info": {
            "total": 2,
            "current_page": 1,
            "total_pages": 1
        }
    },
    "data": [
        {
            "id": 2245703,
            "account_number": "0690000032",
            "bank_code": "044",
            "full_name": "BLAKE LIVELY",
            "created_at": "2026-10-09T14:47:11.000Z",
            "currency": "NGN",
            "debit_currency": null,
            "amount": 500000,
            "fee": 53.75,
            "status": "SUCCESSFUL",
            "reference": "f942fb4bebd09cd9_PMCKDU_5",
            "meta": [
                {
                    "first_name": "Blake",
                    "last_name": "Lively",
                    "account_number": "0690000032",
                    "routing_number": "044",
                    "bank_name": "Access Bank",
                    "mobile_number": "23480000000002",
                    "email": "[email protected]",
                    "beneficiary_country": "NG",
                    "sender": "Dotuns Fashion Limited"
                }
            ],
            "narration": "Salary payment for April",
            "approver": null,
            "complete_message": "Successful",
            "requires_approval": 0,
            "is_approved": 1,
            "bank_name": "FA-BANK"
        },
        {
            "id": 2245702,
            "account_number": "0690000031",
            "bank_code": "044",
            "full_name": "Forrest Green",
            "created_at": "2026-10-09T14:47:10.000Z",
            "currency": "NGN",
            "debit_currency": null,
            "amount": 690000,
            "fee": 53.75,
            "status": "SUCCESSFUL",
            "reference": "ac24db195edf7529_PMCKDU_5",
            "meta": null,
            "narration": "Salary payment for April",
            "approver": null,
            "complete_message": "Successful",
            "requires_approval": 0,
            "is_approved": 1,
            "bank_name": "ACCESS BANK NIGERIA"
        }
    ]
}

The status field indicates the current status of each transfer ( for example,"NEW", "PENDING", "FAILED", "SUCCESSFUL"), while complete_message gives a more descriptive message about the transfer outcome, such as"Transaction is currently being processed", "Account resolve failed", or"Successful".

🚧

Approval Process

When making bulk transfers from your dashboard, you'll need to specify an approver. When making them via API, no approver is needed.

You can retrieve errors for individual transfers in a batch by setting the error_reporting flag to true in the initial bulk request.

When you retrieve the batch using its batch_id, any reported errors are returned in the meta.errors array. Each error includes the affected transfer's reference, its item number, and a description of the error.`

{
    "status": "success",
    "message": "Transfers fetched",
    "meta": {
        "page_info": {
            "total": 0,
            "current_page": 0,
            "total_pages": 0
        },
        "errors": [
            {
                "reference": "bulk_Transfers_0019_PMCK",
                "item": 1,
                "message": "Payout with this ref already exists"
            },
            {
                "reference": "bulk_Transfers_0020_PMCK",
                "item": 2,
                "message": "Payout with this ref already exists"
            },
            {
                "reference": "bulk_Transfers_0021_PMCK",
                "item": 3,
                "message": "Payout with this ref already exists"
            },
            {
                "reference": "bulk_Transfers_0022_PMCK",
                "item": 4,
                "message": "Payout with this ref already exists"
            }
        ]
    },
    "data": []
}

Testing Transfers

Check the testing guide for mocking transfers in the test environment.


Did this page help you?