Your platform drives Payrails all day: token exchanges, orchestration calls, analytics pulls on api.payrails.io. Give that traffic two fixed static EU IPs with one HTTPS_PROXY variable, so your side of the orchestration is as attributable as theirs.
# one variable, fixed egress for every call
HTTPS_PROXY=https://user:pass@eu-01.outboundgateway.com:8443
# exchange your secret key for a JWT
curl -s -X POST https://api.payrails.io/auth/token/$CLIENT_ID \
-H "x-api-key: $PAYRAILS_SECRET_KEY"
# then every call leaves from the same
# two EU IPs, on every deploy
curl -s "https://api.payrails.io/analytics/reports?page[size]=20" \
-H "Authorization: Bearer $JWT"
Payrails normalizes how you reach a hundred payment providers. The address those requests leave from is still whatever your platform assigned this morning.
Containers, Kubernetes pods, and serverless functions each restart with fresh egress IPs. Your calls to api.payrails.io authenticate fine, but they arrive from a different machine almost daily, and nothing on your side can state what your integration's address is.
Reconciliation pushes, SFTP drops to acquirers, and the occasional direct PSP or bank call still leave your own infrastructure. Those receiving ends want known addresses, and rotating egress gives them the opposite.
Security programs at Puma- and Vinted-class companies ask where payment traffic originates and how it is contained. A different answer per deploy is not an answer when the system in question moves money.
Your Platform
orchestration + vault + analytics calls
HTTPS Proxy
(Static EU IP)
Payrails API
api.payrails.io
Payrails sees every request from your platform arriving at the same two EU addresses, whichever runtime issued it. Either address can carry the whole load, so maintenance on a proxy node never changes the origin your logs record.
HTTPS_PROXY once in your platform's environment; every token exchange, orchestration call, and analytics pull then leaves from your fixed address.x-api-key secret and the JWTs it mints stay encrypted past the proxy hop.The address pair becomes your integration's identity. Your own firewalls, the dashboards of PSPs you connect directly, and audit questions about Payrails-bound traffic all get one stable answer.
Wired for the real sequence: your secret key in x-api-key, POST /auth/token/{clientId} for the JWT, then Bearer calls like GET /analytics/reports. No SDK surgery required.
Payrails was founded in Berlin with offices across Europe, and your egress stays in European data centres too. One clean residency story for traffic that carries payment instructions.
Teams running an orchestrator who still need their own payment traffic to look predictable, to their tooling and to anyone reviewing it.
Teams that integrated with Payrails once and now toggle routing across many PSPs, but cannot promise a stable egress address from serverless or containerized runtimes.
Jobs that pull reports from /analytics/reports and push settlement files over SFTP, and need that traffic identifiable in logs, firewalls, and partner allowlists.
Platforms chasing approval rates across regions who keep direct PSP and acquirer connections alongside the orchestrator and want every egress path equally recognizable.
Integrations that must answer where transaction and reporting traffic originates, and how it is contained to an address pair someone can actually verify.
One environment variable, and your Payrails 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
# mint a JWT with your secret key, from your static EU IP
JWT=$(curl -s -X POST https://api.payrails.io/auth/token/$PAYRAILS_CLIENT_ID \
-H "x-api-key: $PAYRAILS_SECRET_KEY" \
| jq -r .access_token)
# pull a report page, same fixed address
curl -s "https://api.payrails.io/analytics/reports?page[size]=20" \
-H "Authorization: Bearer $JWT"
requests reads HTTPS_PROXY from the environment automatically; keep your key and client id in os.environ.
import os, requests
# exchange the secret key for a JWT
token = requests.post(
f"https://api.payrails.io/auth/token/{os.environ['PAYRAILS_CLIENT_ID']}",
headers={"x-api-key": os.environ["PAYRAILS_SECRET_KEY"]},
).json()["access_token"]
# pull reports, egressing from your static EU IP
reports = requests.get(
"https://api.payrails.io/analytics/reports",
headers={"Authorization": f"Bearer {token}"},
params={"page[size]": 20},
).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.payrails.io/analytics/reports?page[size]=20', {
dispatcher,
headers: { Authorization: `Bearer ${token}` },
});
Keys are environment-specific, but the proxy variable is not. Point test traffic at the documented staging host and change nothing else.
# same HTTPS_PROXY, staging host and staging keys
curl -s -X POST https://api.staging.payrails.io/auth/token/$PAYRAILS_CLIENT_ID \
-H "x-api-key: $PAYRAILS_STAGING_SECRET_KEY" | jq -r .access_token
Register both addresses on your own side
Your account ships with a pair of static EU IPs. Add them to your own firewall allowlists, WAF rules, and monitoring, and to the dashboards of any PSP you still connect directly. When a Payrails onboarding call or security review asks which addresses to expect from you, the answer is already stable.
Which traffic is covered? Your platform's outbound calls to api.payrails.io and api.staging.payrails.io, plus the direct PSP, bank, and SFTP pushes that run alongside the orchestrator. Payrails webhooks arrive inbound at your endpoints; restrict those to Payrails' published source IPs instead of routing them through the proxy.
📖 Complete Documentation: For detailed examples, error handling, and advanced configurations, see the Python guide, the Node.js guide, or all guides.
When your platform forwards payment instructions and reporting queries, the path matters as much as the destination.
Payrails is a Berlin-founded company with European offices, and your egress stays in European data centres too. Payment traffic keeps a single, simple residency story.
The connection to Payrails is never terminated at the proxy. Your x-api-key secret, minted JWTs, and reporting payloads stay encrypted the whole way.
A pair of static EU IPs covering for each other, so your integration's origin survives a proxy node restart.
Pod reschedules and function cold stops stop mattering; the address pair stays put while everything behind it churns.
TLS passthrough keeps secrets, tokens, and payment payloads sealed past the proxy hop.
One env var covers curl, Python requests, Node with undici, and PHP backends alike.
Hand the same pair to PSP dashboards, auditors, or your own firewalls whenever the question comes up.
Starting from €19/month. Flexible plans for every scale. Cancel anytime.
Set one environment variable and every token exchange, orchestration call, and analytics pull leaves from two fixed EU addresses.
Starting from €19/month. Flexible plans for every scale. Cancel anytime.
Not for authenticating your standard API connections; those use token-based auth with environment-specific keys. Where IP allowlisting shows up in a Payrails deployment, it mostly concerns Payrails' own egress: their outbound addresses get allowlisted at strict downstream processors, and their SFTP source IPs get allowlisted on your servers for data integrations, with the current lists provided by your account team. A fixed pair on your side covers the part you control: attributable API egress and allow-list-ready direct PSP connections.
Your platform's outbound calls to api.payrails.io, plus any direct PSP, bank, or SFTP pushes that run alongside the orchestrator. Payrails webhooks arrive inbound at your endpoints; restrict those to Payrails' published source IPs rather than routing them through the proxy.
Yes. Keys are environment-specific, but the HTTPS_PROXY variable is identical everywhere. The documented staging host is api.staging.payrails.io; production traffic targets api.payrails.io. You switch keys, not configuration.
Happy to talk through how a managed EU proxy pair fits your payment platform.
Contact Our Founders →