🇪🇺 Live-mode-ready egress for RazorpayX

Static IP for Razorpay

RazorpayX refuses payout API calls in Live Mode from IPs outside your allowlist. Route contacts, fund accounts, and payouts through two fixed static EU IPs, allowlist them once under Share IP Addresses, and every request arrives trusted.

payout-worker · shell

# both IPs saved once, every call trusted

HTTPS_PROXY=https://user:pass@eu-01.outboundgateway.com:8443

# -u carries Key ID and Key Secret (Basic auth)

curl -u "$RZP_KEY_ID:$RZP_KEY_SECRET" \

  "https://api.razorpay.com/v1/payouts" \

  -H "X-Payout-Idempotency: $KEY"

Live Mode checks every single call

RazorpayX treats the IP allowlist as a security control, not a suggestion. Once you are on live keys, payout-related API requests from addresses you never saved simply fail, and the platform assumes your infrastructure can name an egress IP that never moves.

Mandatory, and enforced at the door

The allowlist doc says it without hedging: "If an API request is received from an IP outside the allowlist, the request will fail." The rule reaches every payout, contact, fund account, validation, and payout link request. No warning header arrives first; the call is refused because of where it came from.

The edit is a ceremony

Only the Owner or Admin of the account can touch the list, and every save is confirmed by an OTP sent to the registered phone and email. When your egress address rotates, the fix is not a config push; it is a dashboard session, two approval factors, and someone who can reach that phone right now.

Twenty slots, spent one rollout at a time

Share IP Addresses accepts up to 20 entries, which sounds generous until an autoscaling fleet, a second cloud region, and a staging cluster each contribute their rotating addresses. Fixed egress collapses the whole estate to two entries that never need replacing.

Test mode forgives, live mode does not

IP Allowlisting is applicable only in Live Mode, so an integration built on rzp_test_ keys passes every check and ships on time. The first live payout batch is the moment the gate arms, which is the worst possible moment to discover what your egress IP actually is.

The Solution

Two fixed EU IPs, saved once under Share IP Addresses

Your Platform

payouts · contacts · fund accounts

HTTPS Proxy

(Static EU IP)

RazorpayX

api.razorpay.com

Both of your fixed addresses live in the allowlist from the very first save. Either one can answer a request, so a proxy node failing over never sends the Owner or Admin back into the dashboard for another OTP.

Set HTTPS_PROXY once wherever the payout jobs run; contact, fund account, and payout requests then all leave from the same saved pair.
Both EU addresses are trusted at the same time, so failover is a detail RazorpayX never notices and your payout batch never feels.
TLS runs end to end to api.razorpay.com. Your Key ID and Key Secret travel as Basic auth inside encryption the proxy never unwraps.

Why payout teams route RazorpayX through OutboundGateway

Go live with the gate already satisfied

The allowlist is mandatory, so the only open question is whether your addresses are in it before the first live key fires. Saving a fixed pair turns go-live day into a key switch, not an incident bridge.

Scale without spending the list

Pods, nodes, regions, and environments all share two entries out of the twenty available. The eighteen that remain stay free for the partners, branch offices, and vendor machines that will ask for them later.

One pair across every payout surface

Test to live, staging to production: the same two addresses keep answering, so promotions change nothing about origin. Running several PSPs side by side? Our Paystack static IP guide and Payfast guide stretch the pattern across the stack.

Designed for

Teams whose RazorpayX integrations move real money in Live Mode and cannot afford a request refused over geography.

Marketplace and SaaS payout automation

Refund sweeps, seller settlements, and disbursements that fire through the Payouts API on a schedule and must succeed the first time, every time, on whatever node the scheduler picked.

Finance-ops batch jobs

Nightly runs that create contacts, refresh fund accounts, and reconcile transactions, where a refused batch is not an error message but a payroll date starting to slip.

Fintechs and agencies building for merchants

The same pair pasted into every client account's Share IP Addresses list, so one egress story covers every RazorpayX dashboard you maintain without per-client plumbing.

Platforms promoting from test to live

The switch from rzp_test_ to rzp_live_ keys is the moment the mandatory check arms. Arriving with both IPs already saved makes the promotion uneventful, which is the goal.

Implementation

One environment variable routes every authenticated request out of your fixed EU pair.

Shell / environment

Set the variable wherever the payout workload runs. RazorpayX authenticates with Basic auth, the Key ID and Key Secret pair that curl -u sends for you.

# .env, task definition, Kubernetes secret, wherever env config lives
HTTPS_PROXY=https://user:pass@eu-01.outboundgateway.com:8443

# create a payout, egressing from your static EU IP
curl -u "$RZP_KEY_ID:$RZP_KEY_SECRET" -X POST "https://api.razorpay.com/v1/payouts" \
  -H "Content-Type: application/json" \
  -H "X-Payout-Idempotency: $IDEMPOTENCY_KEY" \
  -d "{ \"account_number\": \"$ACCOUNT_NUMBER\", \
        \"fund_account_id\": \"$FUND_ACCOUNT_ID\", \
        \"amount\": 1000000, \"currency\": \"INR\", \
        \"mode\": \"IMPS\", \"purpose\": \"payout\" }"

# amount is in paise: 1000000 transfers Rs 10,000

Python (requests)

Basic auth is native to requests as the auth tuple, and the library reads HTTPS_PROXY from the environment on its own, so there is no proxy code to write.

import os
import requests

# curl -u key:secret becomes the auth tuple
auth = (os.environ["RZP_KEY_ID"], os.environ["RZP_KEY_SECRET"])

contact = requests.post(
    "https://api.razorpay.com/v1/contacts",
    auth=auth,
    json={
        "name": "Priya Sharma",
        "email": "priya@example.com",
        "contact": "9000090000",
        "type": "vendor",
        "reference_id": "vendor-0042",
    },
    # no proxy argument: HTTPS_PROXY from the env is honored
).json()

Node.js (undici ProxyAgent)

Node's global fetch skips proxy environment variables, so hand it undici's ProxyAgent and build the Basic header yourself.

import { ProxyAgent } from 'undici';

const auth = 'Basic ' + Buffer.from(
  `${process.env.RZP_KEY_ID}:${process.env.RZP_KEY_SECRET}`
).toString('base64');

const res = await fetch('https://api.razorpay.com/v1/payouts', {
  method: 'POST',
  dispatcher: new ProxyAgent(process.env.HTTPS_PROXY),
  headers: {
    'Authorization': auth,
    'Content-Type': 'application/json',
    'X-Payout-Idempotency': idempotencyKey,
  },
  body: JSON.stringify({
    fund_account_id: fundAccountId,
    amount: 1000000,   // paise: Rs 10,000
    currency: 'INR',
    mode: 'IMPS',
    purpose: 'payout',
  }),
});

Save the pair in Share IP Addresses

The allowlist sits behind two gates by design, so plan the ceremony once and never repeat it.

# saving the pair (Owner or Admin only):
#   RazorpayX Dashboard -> profile icon
#   My Account & Settings -> Developer Controls
#   Share IP Addresses
#   enter BOTH fixed IPv4 addresses, Enter after each
#   Save -> OTP arrives on the registered phone and email
#   Submit; the list stays editable in the same section

# the allowlist governs Live Mode payout APIs,
#   incl. contacts, fund accounts, payout links,
#   and fund account validation requests

# both addresses being present is what makes a proxy
#   failover a non-event: the survivor is already saved

Paste the pair once, then leave the dashboard alone

Every OutboundGateway account ships with its own two static EU IPv4 addresses. Save both under Share IP Addresses and live payout traffic is compliant from the first request; the next environment or key rotation reuses the same two lines without another OTP.

Which traffic is covered? Everything the proxy forwards is outbound and authenticated: your REST calls to api.razorpay.com for contacts, fund accounts, payouts, payout links, and fund account validation, the exact set the Live Mode allowlist governs. Per the docs, the allowlist does not apply to Vendor payments, Payroll, or payouts made from the dashboard. Webhooks run the other direction, from Razorpay to your endpoint, so nothing inbound flows through the proxy.

📖 Complete Documentation: For deeper examples, error handling, and advanced configurations, see the Python guide, the Node.js guide, or all guides.

Payout data, leaving from Europe

RazorpayX is an India-first payouts platform, and your account, contacts, and fund accounts live on its infrastructure wherever that runs. What you control is the origin your requests leave from, and an EU pair keeps that side of the story European.

GDPR on your side of the wire

Contact and fund account payloads carry names, phone numbers, and bank details of real people. When those requests exit from EU data centres, the origin chapter of your data-processing story stays in the EU instead of scattering across whichever cloud region happened to serve the job.

Card-rails hygiene, sealed credentials

Payouts sit in a payment chain where PCI DSS is the working frame, and RazorpayX holds the regulated money movement. On your side, the Key Secret travels as Basic auth inside TLS that passes through the proxy untouched, and the mandatory allowlist means an address you never saved cannot spend your keys.

What you get

The gate, satisfied for good

Mandatory allowlisting stops being a go-live checklist item the moment both addresses are saved. The requirement holds, and your traffic holds with it.

One paste, no repeat ceremony

Two entries in Share IP Addresses cover every pod and region you will ever scale to, and the account Owner keeps their phone in their pocket.

Failover without a ticket

Both addresses sit in the list from day one, so a proxy node stepping out is invisible to RazorpayX and to the payout batch that was running at the time.

Slots to spare

Two of twenty used, forever. Partners, branch offices, and one-off vendor machines keep the other eighteen for the day they ask.

Secrets stay sealed

The Key ID and Key Secret ride TLS through the proxy as ciphertext. We relay packets, never credentials.

Simple pricing

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

Make the mandatory allowlist trivial

A single environment variable points every RazorpayX call at two fixed EU addresses already saved under Share IP Addresses, from the first test request to the ten-thousandth payout.

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

Frequently asked questions

Does RazorpayX require IP whitelisting?

Yes, in Live Mode it is mandatory. The documentation states that all payout related API requests must come from allowlisted IPs and that "a request from an IP outside the allowlist will fail." The rule covers Payouts APIs including contacts and fund accounts, plus Payout Link APIs and fund account validation. Two fixed EU IPs satisfy the requirement permanently.

How do I add my proxy IPs in Share IP Addresses?

In the RazorpayX Dashboard, open the profile icon, then My Account & Settings, then Developer Controls, and open Share IP Addresses. Enter both fixed IPv4 addresses, pressing Enter after each, and save; an OTP arrives on the registered phone and email to confirm the change. Only the account Owner or Admin can complete this, and the saved list stays editable in the same place.

Do RazorpayX webhooks also go through the proxy?

No. Webhooks are inbound: Razorpay calls your endpoint and signs each payload with the webhook secret you configured. The proxy and the allowlist concern the outbound direction, your API calls to api.razorpay.com, so webhooks need nothing from the proxy pair.

Two addresses RazorpayX will always recognise

Tell us what your payout stack runs on, and we will map exactly where the pair plugs in.

Contact Our Founders →