Flutterwave's payouts checklist tells you to whitelist the servers that make Transfer API calls. Route those calls through two fixed static EU IPs, add them once under Whitelisted IP addresses, and every transfer leaves from an address the dashboard already trusts.
# one variable pins egress on every surface
export HTTPS_PROXY=https://user:pass@eu-01.outboundgateway.com:8443
# every call now leaves from the trusted pair
curl -s -X POST "https://api.flutterwave.com/v3/transfers" \
-H "Authorization: Bearer $FLW_SECRET_KEY" \
-H "Content-Type: application/json"
# Bearer, one space, then the FLWSECK key
Flutterwave frames whitelisting as extra security and control for your payouts, and its integration docs make the assignment explicit. The only input the dashboard asks for is the one thing cloud infrastructure refuses to give you: addresses that hold still.
Before your first transfer, the docs list two prerequisites: enable Transfer via API in your dashboard settings, then "whitelist the IP addresses of the servers that will be making Transfer API calls." There is no shortcut through step two. The dashboard expects named addresses, and it is your infrastructure that has to produce them.
Each add or remove under Whitelisted IP addresses finishes with a one-time passcode delivered by email or WhatsApp. That is fine twice a year and unbearable per deploy: an egress address that rotates drags a two-channel confirmation ritual into the middle of your payout pipeline, with a WhatsApp dependency nobody asked for.
Autoscaled pods, serverless functions, and platform-hosted jobs leave from pooled or per-instance addresses that reshuffle on every schedule. The dashboard's format dropdown wants explicit IPv4 or IPv6 entries, and a fleet that changes shape hourly has no honest answer to that question.
Flutterwave is explicit that its own webhook source IPs are dynamic and recommends signature verification over IP rules for inbound traffic. So address discipline belongs on exactly one side of the integration: the outbound Transfer API calls that carry your money out. That is the side with no publisher ranges, no signatures, just the list you maintain.
Your Platform
transfers · payouts · bulk
HTTPS Proxy
(Static EU IP)
Flutterwave
api.flutterwave.com/v3
Enter both fixed addresses once under Whitelisted IP addresses, confirm a single OTP, and the checklist item is closed for good: transfers initiate from an address the dashboard was told to trust, and failover between the pair never reopens the question.
HTTPS_PROXY once in your platform's environment; single transfers, bulk runs, and beneficiary calls then leave from your fixed pair.FLWSECK secret travels as a Bearer token inside encryption the proxy never unwraps.Flip Transfer via API on, paste two addresses, confirm one OTP, and both items on the payouts checklist are done before the first test transfer. No phased rollout, no per-environment negotiations with the dashboard.
Two addresses cover every pod, region, function, and cron job you will ever deploy. The whitelist stays two entries long whether you run three servers or three hundred, and no scaling event ever ends in an email-and-WhatsApp confirmation.
Flutterwave is one rail among many, and the same two EU addresses answer every PSP's whitelist question. Our Paystack static IP guide and Razorpay guide walk the identical pattern on the neighboring rails.
Anyone pushing money out through Flutterwave's Transfer API who wants the whitelist step finished once instead of tended forever.
Seller settlements, refunds as transfers, and bulk payout runs to bank accounts, mobile money, or other Flutterwave wallets across Nigeria, Ghana, Kenya, the UK, SEPA, and 30-plus countries, all initiated from one trusted pair.
Cron-driven bulk transfers and status polling run when nobody is watching. An origin the dashboard does not recognize is a payroll run that stalls overnight, discovered by an angry beneficiary rather than a dashboard alert.
Every client dashboard gets the same two addresses in its whitelist, so the integration you built once works identically across every account you operate, and client onboarding never restarts the address conversation.
Test keys carry the _TEST prefix and forgive a lot. The day you switch to live FLWSECK credentials and flip Transfer via API on is the day the whitelist earns its keep, so the pair should already be in place.
One environment variable routes every transfer request out of your fixed EU address.
Set the variable wherever your payout jobs run. Flutterwave authenticates with your secret key as a Bearer token, and the header is unfussy in exactly one way: Bearer, a single space, then the key.
# .env, task definition, Kubernetes secret, wherever env config lives
HTTPS_PROXY=https://user:pass@eu-01.outboundgateway.com:8443
FLW_SECRET_KEY=FLWSECK-xxxxxxxxxxxxxxxxxxxxxxxx-x
# create a transfer, egressing from your static EU IP
curl -s -X POST "https://api.flutterwave.com/v3/transfers" \
-H "Authorization: Bearer $FLW_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"account_bank":"044","account_number":"0690000040",
"amount":5500,"currency":"NGN",
"reference":"payout-2026-10-31-001"}'
# reference is your unique id; you query transfer status with it
requests reads HTTPS_PROXY from the environment on its own, so there is no proxy argument to wire and nothing to hardcode: credentials come from os.environ, the way Flutterwave's own docs recommend storing them.
import os
import requests
transfer = {
"account_bank": "044",
"account_number": "0690000040",
"amount": 5500,
"currency": "NGN",
"reference": "payout-2026-10-31-001",
}
res = requests.post(
"https://api.flutterwave.com/v3/transfers",
headers={"Authorization": f"Bearer {os.environ['FLW_SECRET_KEY']}"},
json=transfer,
)
print(res.json()["status"]) # env proxy rides along, egress is your fixed pair
Node's built-in fetch ignores proxy env vars, so hand it undici's ProxyAgent explicitly. If you use the official flutterwave-node-v3 SDK, keys are provided when the client is initialized and Transfer.initiate() fires the same POST underneath.
import { ProxyAgent } from 'undici';
const res = await fetch('https://api.flutterwave.com/v3/transfers', {
method: 'POST',
dispatcher: new ProxyAgent(process.env.HTTPS_PROXY),
headers: {
Authorization: `Bearer ${process.env.FLW_SECRET_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
account_bank: '044',
account_number: '0690000040',
amount: 5500,
currency: 'NGN',
reference: 'payout-2026-10-31-001',
}),
});
The ceremony is short and, with a fixed pair, rare: both addresses go in once, the OTP confirms the change, and the list never needs a third visit.
# dashboard -> Settings -> Whitelisted IP addresses
# -> Add IP Address
# enter BOTH fixed IPv4 addresses, one entry each
# pick IPv4 in the format dropdown (IPv6 also supported)
# OTP arrives via email or WhatsApp to confirm the change
# control stays yours: removing an address from the
# same list revokes it anytime
# done once; the pair does not move under you, so the
# OTP only happens when YOU change the list
Both IPs belong in the list from day one
Every account gets its own pair of static EU IPv4 addresses. Add both, confirm one OTP, and a proxy failover between them is a non-event: the other address was already trusted, so transfers continue while you read about it later. The next environment you wire up is the same two-line paste.
Which traffic is covered? Everything here is your outbound, Bearer-authenticated REST traffic to api.flutterwave.com/v3: creating transfers, queuing bulk runs, polling transfer statuses, and managing beneficiaries. The whitelist item sits in the payouts checklist, so it is this money-moving traffic it protects. Webhooks run the other direction, Flutterwave POSTing events to your endpoint, and their docs recommend verifying webhook signatures rather than filtering IPs, so nothing inbound flows through the proxy.
📖 Complete Documentation: For detailed examples, error handling, and advanced configurations, see the Python guide, the Node.js guide, or all guides.
Flutterwave's transfer rails reach more than 30 countries, EUR transfers included across the SEPA area. Wherever the money lands, the server it departs from can be European, and that part of the journey is yours to choose.
Transfer payloads carry beneficiary names, account numbers, narrations, and references, personal and financial data in one request body. Egress from EU data centres gives that data a European origin for its entire trip to the API, which keeps the residency story simple when compliance asks where payout calls physically start.
Payout integrations live in a card-and-bank rails world where PCI DSS frames how the chain is secured, and Flutterwave is blunt that the secret key can do anything on the account. Yours travels as a Bearer token inside TLS the proxy passes through untouched, stored as an env var, never in a repo or a frontend.
Whitelisting your servers is a prerequisite, not a subscription. A fixed pair turns it into something you finish in the first hour and never revisit, no matter how the fleet behind it evolves.
Both addresses enter the list once with a single confirmation. Deploys, scale events, and node recycling stop generating email-and-WhatsApp rituals, because the egress simply never changes.
Both IPs sit in the whitelist from the first day, so the proxy switching between them is invisible to Flutterwave. Transfers keep flowing while the failover happens, and the OTP stays unhunted.
The dashboard lets you remove an address anytime, and that control is worth keeping. The pair works for as long as you list it and stops the moment you take it out, with no lock-in in either direction.
You attach the Bearer token on your side, and TLS passthrough carries it to Flutterwave encrypted. The proxy relays ciphertext and nothing else, so the key that can do anything on the account is seen by no one in between.
Starting from €19/month. Flexible plans for every scale. Cancel anytime.
A single environment variable points every Transfer API call at two fixed EU addresses your dashboard already trusts, from the first test payout to the thousandth bulk run.
Starting from €19/month. Flexible plans for every scale. Cancel anytime.
Yes. Under Settings on your dashboard, the Whitelisted IP addresses page lets you add addresses one at a time, choosing IPv4 or IPv6 from a format dropdown, with each change confirmed by an OTP sent via email or WhatsApp. Flutterwave presents it as added security and control for your payouts, and the Transfer API integration checklist asks you to whitelist the servers that will be making Transfer API calls before you start. You keep full control and can revoke an address by removing it anytime.
Open Settings, then Whitelisted IP addresses, and click Add IP Address. Enter both fixed EU IPv4 addresses from your OutboundGateway account, one entry each, pick IPv4 in the format dropdown, and confirm the OTP that arrives by email or WhatsApp. That single session finishes the setup: both addresses answer for your traffic, so a failover between them needs no dashboard visit, and the list only changes again if you decide to change it.
No. Webhooks are inbound: Flutterwave POSTs event notifications to an endpoint you expose, and your outbound proxy plays no role in that direction. Flutterwave's own docs note that their source IPs are dynamic and recommend verifying webhook signatures rather than filtering by IP, so the address discipline applies to your outbound Transfer API calls, which is exactly the traffic the proxy and the whitelist cover.
Tell us what your Flutterwave integration runs on, and we will map exactly where the pair plugs in.
Contact Our Founders →