IP allowlist
The IP allowlist restricts the calls your servers make with a secret rail_* key, and dashboard
sessions, to addresses you nominate, on the payment API (/payments, /refunds and related
routes) and the account API (/v1/...) alike. It is opt-in: with no active entries nothing is
restricted. The moment your first entry becomes active, such a call or session from an address
outside the list is refused. Calls your customers' browsers make with your publishable key
(rail_open_...), such as the hosted checkout's, are not restricted by this allowlist: they come
from wherever your customers are. A publishable-key confirm you run client-side from your own
page is checked separately, by the page's origin rather than by address; see
Browser flows and client_secret.
Dashboard sessions are checked against the address each person connects from. So while the list is active, everyone who uses the dashboard needs an entry that covers the address they connect from, and removing the entry that covers yours locks you out of the dashboard. See Before you add the first entry.
There is no staging mode, no dry run, and no grace period. Your first entry activates
enforcement on the next request, so your production servers' API calls, payments included, and
your colleagues' dashboard sessions, are refused from that instant until you add their addresses
too. If your first entry covers only your own address, those calls return ERR_1006.
Read Before you add the first entry and If you lock yourself out first. Recovery is not self-serve once no allowlisted address is reachable.
Manage the list in the dashboard under Security → IP allowlist. There is no API call for managing it; see Managing the list.
What is enforced, and against which address
| Scope | Your whole merchant account: every rail_* key and every dashboard user, not a single user, not a single key. |
| Applies to | Calls to the payment API (/payments, /refunds and related routes) and to the account API (/v1/...) made with a secret rail_* key, checked against the address your servers present. Dashboard sessions, checked against the address the person connects from. Not calls made with your publishable key. |
| No entries | Nothing is restricted. |
| One or more active entries | The caller's address must fall inside one of them, or the request is refused with 403 ERR_1006. |
| Takes effect | Immediately on add and on remove. |
For a call made with a secret rail_* key, the address checked is the one your connection presents
at our edge. Forwarding headers you set yourself (X-Forwarded-For, X-Real-IP) are ignored:
they can be appended to by anything between you and us, so trusting them would let a caller
nominate their own address and walk through the allowlist. If you call us through your own proxy
or NAT, the address to allowlist is that egress address, not the address of the machine behind it.
For a dashboard session, the address checked is the one your browser's connection presents at our edge: the dashboard calls the account API on your behalf and passes that address along with each call. Forwarding headers sent by the browser are ignored here too.
When your allowlist cannot be read at all (a storage failure on our side, with nothing cached),
secret-key API traffic is refused rather than admitted (an account that asked to be restricted is
not quietly unrestricted), while a dashboard session is allowed through, so an outage on our side
never locks a human out of the screen where they can fix things. If a payment API call cannot be
checked at all, it is refused with 503 ERR_5005; retry it.
Before you add the first entry
- Write down every address that calls the API with one of your secret keys, and every address your team uses the dashboard from, before you add anything: production servers, staging, your CI runner, any scheduled job, offices and VPN exits. Anything you miss is refused the moment the list goes live, payments included.
- Add them one at a time; there is no bulk action. Between the first entry and the last, the addresses you have not added yet are already being refused. Do it in a window where a few minutes of refused calls is acceptable, and add the server ranges immediately after the first entry.
- The first entry must contain the address you are adding it from. Entries are added from the dashboard, so that is the address your browser connects from (through a VPN or a corporate proxy, its exit address): a first entry that does not contain it is refused, and the dashboard names the address. If that address cannot be identified, the first entry is refused; contact support.
- Only public address ranges can be added. Private, loopback, link-local, shared (CGNAT) and
multicast ranges are refused, and so is a wider range that contains one (for example
0.0.0.0/0). None of your servers or people reaches us from such an address.
Beyond the public-range check, nothing checks the second and later entries, and nothing checks that your servers or your colleagues are covered. Only the first entry is guarded against locking you out, because only the first entry switches enforcement on.
Removing entries
Nothing blocks a removal, and nothing checks which entry you are removing:
- Removing the entry that covers your servers refuses their API calls as soon as it commits.
- Removing the entry that covers the address you use the dashboard from, while other entries stay active, refuses your dashboard calls as soon as it commits, including the Security page you would use to undo it. A colleague whose address is still covered can add yours back; otherwise recovery needs support.
- Removing the last active entry switches enforcement off entirely and leaves the account unrestricted.
Every removal is audited (ip_allowlist:remove in your audit log)
and sends a security email. Entries are deactivated rather than deleted, so the history of what was
allowed, and when, stays readable.
If you lock yourself out
If only your servers are refused, sign in to the dashboard. As long as an active entry covers the address you connect from, Security → IP allowlist lets you add the address your servers call from or remove the entry that is wrong (two-factor required).
If the dashboard refuses you too (ERR_1006), a colleague whose address is covered can add
yours. If nobody on your account can reach the dashboard, you cannot recover it yourself: contact
TensorRail support to have the entries cleared; expect to verify who you are.
This is why the pre-flight list matters more than it looks: for every server you missed, the failure is total until the list is fixed.
Managing the list
Everything here is a dashboard action, under Security → IP allowlist: there is no API call for listing, adding or removing an entry, under any credential.
The list shows every entry, including deactivated ones (an entry is deactivated rather than deleted when you remove it, so the history of what was allowed, and when, stays visible). Only an active entry is enforced.
Add an entry, with a fresh two-factor step-up: a CIDR block (203.0.113.0/24) or a bare
address (203.0.113.9, stored as /32; IPv6 as /128), stored network-aligned (so
203.0.113.5/24 is recorded as 203.0.113.0/24), and an optional label up to 64 characters for
your own reference (prod egress, london office). Up to 50 active entries; the dashboard
refuses a 51st until you deactivate one.
Remove an entry, with a fresh two-factor step-up: deactivates it. Removing one that is already inactive leaves it unchanged, so doing it twice is safe.
What you will see when it fires
A blocked request gets 403 with ERR_1006. Every add and every removal writes an audit entry
(ip_allowlist:add / ip_allowlist:remove) readable through
GET /v1/audit, and sends a security email (subject "Security
alert: IP allowlist entry added" or "…removed") to your security address, with the origin of
the change masked. Turn that email off, or point it at a different address, under
security notifications; the audit entry is
written either way.
Errors
These are what your secret-key API calls see once enforcement is active; adding, removing or listing entries is a dashboard action and shows plain messages rather than an API error code.
| Code | HTTP | Cause |
|---|---|---|
ERR_1006 | 403 | The calling address is not inside any active entry. |
ERR_5005 | 503 | A payment API call could not be checked against the allowlist; retry it. |
Related
- Account security: two-factor, sessions, recent logins, security email.
- Reporting API: reading the audit trail of allowlist changes.
- Error catalog: every code, in one table.
- Emergency key revoke: the other control for a credential you no longer trust.
TensorRail, Limassol, Cyprus.