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.
# 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"
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.
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.
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.
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.
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.
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.
HTTPS_PROXY once wherever the payout jobs run; contact, fund account, and payout requests then all leave from the same saved pair.api.razorpay.com. Your Key ID and Key Secret travel as Basic auth inside encryption the proxy never unwraps.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.
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.
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.
Teams whose RazorpayX integrations move real money in Live Mode and cannot afford a request refused over geography.
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.
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.
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.
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.
One environment variable routes every authenticated request out of your fixed EU pair.
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
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'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',
}),
});
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.
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.
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.
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.
Mandatory allowlisting stops being a go-live checklist item the moment both addresses are saved. The requirement holds, and your traffic holds with it.
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.
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.
Two of twenty used, forever. Partners, branch offices, and one-off vendor machines keep the other eighteen for the day they ask.
The Key ID and Key Secret ride TLS through the proxy as ciphertext. We relay packets, never credentials.
Starting from €19/month. Flexible plans for every scale. Cancel anytime.
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.
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.
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.
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.
Tell us what your payout stack runs on, and we will map exactly where the pair plugs in.
Contact Our Founders →