🇪🇺 Allow-list-ready egress for payment orchestration

Static IP for Payrails

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.

payments-platform · shell

# 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"

The orchestrator centralizes payments, not your egress

Payrails normalizes how you reach a hundred payment providers. The address those requests leave from is still whatever your platform assigned this morning.

Every deploy reshuffles your address

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.

The orchestrator does not cover everything

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.

Strict processors allowlist by IP

In live Payrails environments, processors with strict egress rules expect known outbound addresses allowlisted ahead of time. The same discipline applies to the direct connections you keep with providers such as Stripe or Adyen.

Enterprise reviews want attributable egress

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.

The Solution

One fixed EU IP pair for everything you send to api.payrails.io

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.

Set HTTPS_PROXY once in your platform's environment; every token exchange, orchestration call, and analytics pull then leaves from your fixed address.
Two EU addresses stand in for each other. If either proxy node drops out, the other keeps answering, so the origin never shifts under a live payment flow.
TLS passes straight through to Payrails. Your x-api-key secret and the JWTs it mints stay encrypted past the proxy hop.

Why payment teams route Payrails traffic through OutboundGateway

Attributable on both sides

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.

Fits the documented auth flow

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.

European end to end

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.

Designed for

Teams running an orchestrator who still need their own payment traffic to look predictable, to their tooling and to anyone reviewing it.

Payments and platform engineers

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.

Finance-ops and reconciliation teams

Jobs that pull reports from /analytics/reports and push settlement files over SFTP, and need that traffic identifiable in logs, firewalls, and partner allowlists.

Marketplaces scaling multi-PSP

Platforms chasing approval rates across regions who keep direct PSP and acquirer connections alongside the orchestrator and want every egress path equally recognizable.

Security-reviewed enterprise payment teams

Integrations that must answer where transaction and reporting traffic originates, and how it is contained to an address pair someone can actually verify.

Implementation

One environment variable, and your Payrails calls leave from a fixed EU address.

Shell / environment

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"

Python (requests)

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.js (undici ProxyAgent)

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}` },
});

Staging works the same

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.

EU egress for orchestrated payment traffic

When your platform forwards payment instructions and reporting queries, the path matters as much as the destination.

GDPR-conscious routing

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.

TLS straight through

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.

What you get

Two addresses, one identity

A pair of static EU IPs covering for each other, so your integration's origin survives a proxy node restart.

Survives redeploys

Pod reschedules and function cold stops stop mattering; the address pair stays put while everything behind it churns.

End-to-end encryption

TLS passthrough keeps secrets, tokens, and payment payloads sealed past the proxy hop.

Runtime-agnostic

One env var covers curl, Python requests, Node with undici, and PHP backends alike.

Ready for any allowlist

Hand the same pair to PSP dashboards, auditors, or your own firewalls whenever the question comes up.

Honest pricing

Starting from €19/month. Flexible plans for every scale. Cancel anytime.

Give your Payrails integration one stable origin

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.

Frequently asked questions

Does Payrails support IP whitelisting?

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.

Which connections should go through the proxy?

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.

Does it work for staging and production?

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.

Running Payrails on a platform that rotates egress?

Happy to talk through how a managed EU proxy pair fits your payment platform.

Contact Our Founders →