NGN Bank Transfer

Learn how to collect payment directly from your Nigerian customer’s via bank transfer.

📘

Getting Started

We recommend checking out the introductory section to understand the basics of direct charge first. This guide assumes you’ve read that.

The Process

Collecting payments via bank transfer charge is straightforward:

  • You call the bank transfer charge endpoint to create a charge and generate account details for the customer to pay into.
  • The customer transfers to the generated account.
  • We send you a webhook notifying you that we've received the payment.
  • You verify the payment and complete the customer's order.

Initiating the Charge

To initiate the charge, you'll call the bank transfer charge endpoint, which is supported in some of our backend SDKs. You'll need to specify:

  • tx_ref: A unique reference code that you'll generate for each transaction.
  • amount: The amount to be charged for the transaction.
  • currency: The currency to be used for the charge (currently always "NGN").
  • email: The customer's email address.
// Install with: npm i flutterwave-node-v3

const Flutterwave = require('flutterwave-node-v3');
const flw = new Flutterwave(
	process.env.FLW_PUBLIC_KEY,
	process.env.FLW_SECRET_KEY
);

const details = {
	tx_ref: 'UNIQUE_TRANSACTION_REFERENCE',
	amount: '1500',
	currency: 'NGN',
	email: '[email protected]',
	fullname: 'Flutterwave Developers',
	phone_number: '+2349012345678',
};
const response = await flw.Charge.bank_transfer(details);
# Install with: gem install flutterwave_sdk

require './flutterwave_sdk'

flw = Flutterwave.new(ENV["FLW_PUBLIC_KEY"], ENV["FLW_SECRET_KEY"], ENV["FLW_ENCRYPTION_KEY"])
charge_transfer = BankTransfer.new(flw)

payload = {
    "tx_ref" => "UNIQUE_TRANSACTION_REFERENCE",
    "amount" => "1500",
    "currency" => "NGN",
    "email" => "[email protected]",
    "fullname": "Flutterwave Developers",
    "phone_number" => "+2349012345678"
}
response = charge_transfer.initiate_charge(payload)
curl --request POST \
   --url https://api.flutterwave.com/v3/charges?type=bank_transfer \
   --header 'Authorization: Bearer FLW_SECRET_KEY' \
   --header 'content-type: application/json' \
   --data '{
      "tx_ref": "UNIQUE_TRANSACTION_REFERENCE",
      "amount": "1500",
      "currency": "NGN",
      "email": "[email protected]",
      "fullname": "Flutterwave Developers",
      "phone_number": "+2349012345678"
    }'

📘

Integration Tip

You can also specify a list of subaccounts to split the payment into. See split payments for details.

There are more options available when initiating a bank transfer charge, such as the payment expiry, customer's phone_number and additional meta. See the endpoint docs for details.

{
  "tx_ref": "UNIQUE_TRANSACTION_REFERENCE",
  "amount": "1500",
  "currency": "NGN",
  "email": "[email protected]",
  "fullname": "Flutterwave Developers",
  "phone_number": "+2349012345678",
  "subaccounts": [
    {
      "id": "RS_D87A9EE339AE28BFA2AE86041C6DE70E"
    }
  ]
}
{
	"tx_ref": "UNIQUE_TRANSACTION_REFERENCE",
	"amount": "1500",
	"currency": "NGN",
	"email": "[email protected]",
	"fullname": "Flutterwave Developers",
	"phone_number": "+2349012345678",
	"bank_transfer_options": {
		"expires": 3600
	}
}

If the charge is created successfully, you'll get a successful response containing the generated account details.

{
	"status": "success",
	"message": "Charge initiated",
	"meta": {
		"authorization": {
			"transfer_reference": "N/A",
			"transfer_account": "7825397990",
			"transfer_bank": "WEMA BANK",
			"account_expiration": "N/A",
			"transfer_note": "N/A",
			"transfer_amount": 1500,
			"mode": "banktransfer"
		}
	}
}

Generating specific bank accounts

You can choose which bank issues the virtual account for your PWBT payments. Simply provide the bank_code when creating the virtual account, and the account details will be generated by the selected bank.

{
   "tx_ref":"YOUR_TRANSACTION_REFERENCE",
   "amount":"1500",
   "email":"[email protected]",
   "phone_number":"054709929220",
   "currency":"NGN",
   "client_ip":"154.123.220.1",
   "device_fingerprint":"62wd23423rq324323qew1",
   "narration":"All star college salary for May",
   "is_permanent":false,
	 "bank_code": "232"
}

Supported values for bank_code include:

Bank nameCodeSupported Region
9PSB12001Nigeria
Access Bank044Nigeria
Cashconnect090360Nigeria
Fidelity Bank070Nigeria
Indulge090772Nigeria
Sterling Bank232Nigeria
Wema Bank035Nigeria
Zenith Bank057Nigeria

Completing the Payment

The meta.authorization object contains the account details for the transfer: the bank name (transfer_bank), account number (transfer_account), and amount (transfer_amount). Pass the details on to your customer, and they can make a transfer into the account (for instance, from their bank app).

🧪

Testing Tip

In Test Mode, all bank transfers will automatically be paid after a few seconds.

Webhooks

When payment is made, we'll send you a webhook with a payload like this:

{
  "event": "charge.completed",
  "data": {
    "id": 2028146660,
    "tx_ref": "UNIQUE_TRANChgTdlIfONff_REFERENCE",
    "flw_ref": "100004260420103413157701995493",
    "device_fingerprint": "N/A",
    "amount": 100,
    "currency": "NGN",
    "charged_amount": 102,
    "app_fee": 2,
    "merchant_fee": 0,
    "processor_response": "success",
    "auth_model": "AUTH",
    "ip": "54.154.184.168",
    "narration": "FOR TESTING PURPOSE",
    "status": "successful",
    "payment_type": "bank_transfer",
    "created_at": "2026-04-20T10:34:22.000Z",
    "account_id": 96753,
    "customer": {
      "id": 1334422040,
      "name": "Flutterwave Developers",
      "phone_number": "08012345678",
      "email": "[email protected]",
      "created_at": "2026-04-16T21:31:36.000Z"
    }
  },
  "meta_data": {
    "originatorname": "ADEDOTUN OBATOMI",
    "bankname": "OPAY",
    "bankcode": "100004",
    "originatoramount": "N/A",
    "originatoraccountnumber": "813*******00"
  },
  "event.type": "BANK_TRANSFER_TRANSACTION"
}

📘

How to Retrieve the Session ID.

The Session ID is used to reconcile and track PWBT transactions. It is returned in the Webhook response as the flw_ref. You should store this value in your database alongside your internal transaction record.

Now, your webhook endpoint can handle the event and complete the customer's order. For help setting up webhooks, see our guide to webhooks.

In your webhook handler, you can then verify the payment and credit your customers with whatever they paid for. See our guide to transaction verification for details.