Paystack can block every secret key request that leaves from an address you did not whitelist. Give it two fixed static EU IPs with one HTTPS_PROXY variable, and switch that whitelist on for good, in production and in test.
# one variable, fixed egress for every call
HTTPS_PROXY=https://user:pass@eu-01.outboundgateway.com:8443
# initialize a checkout with your secret key
curl -s -X POST https://api.paystack.co/transaction/initialize \
-H "Authorization: Bearer $PAYSTACK_SECRET_KEY" \
-d '{"email":"customer@email.com","amount":"20000"}'
# verify it, from the same two EU IPs
curl -s https://api.paystack.co/transaction/verify/$REFERENCE \
-H "Authorization: Bearer $PAYSTACK_SECRET_KEY"
Paystack's IP whitelisting is a genuinely good control: once a list is set, secret key calls from anywhere else are blocked. It only works if the addresses on it never change.
Containers, Kubernetes pods, and serverless functions restart with fresh egress IPs. Add one address and the next deploy is locked out; add none and a leaked live secret key still works from any machine on earth. Plenty of teams run with whitelisting off for exactly this reason.
Whitelists are tied to your secret keys, with separate lists for live and test. CI runners and staging platforms egress from whatever address their host assigned today, and a drift between the two lists quietly locks a Friday deploy out of api.paystack.co.
Paystack accepts valid public IPv4 addresses: no CIDR ranges, no IPv6, no private addresses, and at most ten per list. You cannot paste in a cloud provider's rotating egress range even if you knew it. The form wants concrete addresses that are actually yours.
Initializing a transaction, verifying a reference, charging a saved authorization: these run mid-checkout and in unattended recurring jobs at night. A request from the wrong origin is not retried gracefully. It is refused in front of a paying customer.
Your Platform
initialize + verify + charge calls
HTTPS Proxy
(Static EU IP)
Paystack API
api.paystack.co
Both addresses go on the whitelist under "+Add IP address", on the live key's list and on the test key's. Paystack then sees every request from your platform arriving at one of two EU addresses, whichever runtime issued it, and either address can carry the whole load.
HTTPS_PROXY once in your platform's environment; every initialize, verify, charge and export call then leaves from your fixed pair.IP whitelisting only protects you if it stays enabled. A pair of addresses you actually own is what makes leaving it on compatible with serverless deploys, autoscaling, and everything else that reshuffles your egress.
Wired for the real endpoints: a Bearer secret key header, POST /transaction/initialize, GET /transaction/verify/{reference}, charge_authorization for saved authorizations. No SDK surgery required.
Paystack publishes the source IPs its webhooks come from, so you can pin inbound traffic. Your outbound secret key calls deserve the same treatment. Paystack has been part of Stripe since 2020; see our Stripe static IP guide for the same pattern on the parent platform.
Teams collecting payments through Paystack who want the whitelist on, and their egress to finally cooperate with it.
Checkouts over NGN, GHS and KES with channels like USSD, mobile money and bank transfer. If you also collect through CinetPay, the same address pair covers both integrations.
Scheduled charge_authorization calls run unattended against saved authorizations overnight. A locked-out origin fails quietly until the morning dunning report notices.
Live and test secret keys carry separate whitelists. Putting the same pair on both lists means identical proxy configuration ships to every environment, and the test list never drifts.
PCI-DSS-scoped reviews ask how a leaked secret key would be contained. A whitelist of two IPv4 addresses is not a hope; it is a rule Paystack actively enforces on every request.
One environment variable, and your Paystack calls leave from a fixed EU address.
Set the variable wherever your platform runs. curl picks it up with no other change.
# .env, Heroku config vars, Vercel env settings, Lambda env
HTTPS_PROXY=https://user:pass@eu-01.outboundgateway.com:8443
# initialize a checkout, from your static EU IP
curl -s -X POST https://api.paystack.co/transaction/initialize \
-H "Authorization: Bearer $PAYSTACK_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"customer@email.com","amount":"20000"}' \
| jq -r .data.authorization_url
# amounts are passed in subunits (kobo, pesewas, cents)
requests reads HTTPS_PROXY from the environment automatically; keep your secret key in os.environ.
import os, requests
headers = {"Authorization": f"Bearer {os.environ['PAYSTACK_SECRET_KEY']}"}
# initialize a transaction, egressing from your static EU IP
txn = requests.post(
"https://api.paystack.co/transaction/initialize",
headers=headers,
json={"email": "customer@email.com", "amount": 20000},
).json()
# verify it lands on the same two EU IPs
verified = requests.get(
f"https://api.paystack.co/transaction/verify/{txn['data']['reference']}",
headers=headers,
).json()
Node's native fetch ignores proxy env vars; hand it undici's ProxyAgent instead.
import { ProxyAgent } from 'undici';
const dispatcher = new ProxyAgent(process.env.HTTPS_PROXY);
const res = await fetch('https://api.paystack.co/transaction/initialize', {
method: 'POST',
dispatcher,
headers: {
Authorization: `Bearer ${process.env.PAYSTACK_SECRET_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ email: 'customer@email.com', amount: 20000 }),
});
Whitelists are per key type. Add the same two addresses to the test key's list and identical configuration works in CI, staging and production.
# same HTTPS_PROXY, test-mode secret key
curl -s https://api.paystack.co/transaction \
-H "Authorization: Bearer $PAYSTACK_TEST_SECRET_KEY"
Register both addresses in Paystack
Your account ships with a pair of static EU IPv4 addresses. In the Paystack dashboard, open the API Keys and Webhook Settings tab and add both under "+Add IP address", once for the live key and once for the test key. That is two of ten slots used. Paystack emails the integration owner when the live list changes, so you always have an audit trail.
Which traffic is covered? Your platform's outbound secret-key calls: initialize, verify, charge_authorization, list and export. Paystack webhooks arrive inbound at your endpoints from published source addresses (52.31.139.75, 52.49.173.169, 52.214.14.220); allowlist those on your own firewall and verify the x-paystack-signature header (HMAC-SHA512) rather than routing webhooks through the proxy.
📖 Complete Documentation: For detailed examples, error handling, and advanced configurations, see the Python guide, the Node.js guide, or all guides.
Paystack connects you to cards, bank transfers, USSD and mobile money across Nigeria, Ghana, Kenya, South Africa and beyond. Where those requests leave from is still your decision.
Paystack was founded in Lagos and has been part of Stripe since 2020. Your outbound hop stays in EU data centres, keeping one simple residency story for the customer data riding in your API calls.
The connection to Paystack is never terminated at the proxy. Your secret key, authorization codes and payment payloads stay encrypted the whole way.
Two single public IPv4 addresses, exactly what the "+Add IP address" form accepts. No ranges needed, and none are allowed.
Pod reschedules and function cold stops stop mattering; the address pair stays put while everything behind it churns.
TLS passthrough keeps your secret key, authorization codes and payloads sealed past the proxy hop.
The same pair fits both per-key whitelists, with room to spare: two of ten slots on each list.
Initialize, verify, charge_authorization, export: the exact calls your checkout and reconciliation jobs already make.
Starting from €19/month. Flexible plans for every scale. Cancel anytime.
Set one environment variable and every initialize, verify and charge call leaves from two fixed EU addresses that fit the whitelist.
Starting from €19/month. Flexible plans for every scale. Cancel anytime.
Yes. In the dashboard's API Keys and Webhook Settings you add allowed addresses with "+Add IP address". Once a list is set, secret key requests from any other address are blocked. Each list holds up to ten valid public IPv4 addresses, and live and test keys keep separate lists. Dashboard logins are not affected, and Paystack emails the integration owner whenever the live list changes.
Yes. You get two single public IPv4 addresses, and each list holds up to ten. Add both: either address can carry your entire traffic, so a proxy node failing over never changes the origin your whitelist records, and the list itself never needs touching.
They arrive inbound, from Paystack's published source addresses (52.31.139.75, 52.49.173.169, 52.214.14.220). Allowlist those on your firewall and verify each payload's x-paystack-signature header, an HMAC-SHA512 of the body keyed with your secret key. The proxy covers your outbound API calls, not Paystack's deliveries to you.
Happy to talk through how a managed EU proxy pair fits your payment platform.
Contact Our Founders →