API Key Security and IP Allowlisting for Payment APIs
How to hold, scope and restrict API keys that can move money — hashing, least privilege, IP allowlists, rotation, and what a good provider does on their side.
In short
An API key that can issue cards can move money. Treat it as a credential rather than configuration: scope it narrowly, restrict where it may be used from, store it properly and be able to rotate it without downtime.
A key that can create cards can spend your balance. That makes it a credential of the same class as a database password, and it deserves the same handling — which it very often does not get, because it arrives as a string in a dashboard and ends up pasted into a config file.
What a provider should be doing
Before your own practices, check theirs. These are table stakes:
- The secret is shown once and stored hashed. If a provider can show you an existing key's full value, they are storing it recoverably, and their breach is your breach.
- Keys carry scopes. A key for reading balances should not be able to issue cards.
- Revocation is immediate. Not "within an hour", not "on next deploy".
- An invalid key and a disallowed one look identical. If a key blocked by an IP rule returns a different error from an unknown key, the response can be used to discover which keys exist.
- There is a request log. You need to see what a key did, from where, and when.
ON5 stores only a SHA-256 hash of each secret, shows it once at creation, and returns the same 401 for unknown, revoked and IP-blocked keys — deliberately, so the response cannot be used to probe which keys are real.
Scope to least privilege
The temptation is one key with everything. The cost of that shows up on the day it leaks.
| Scope | Permits | Give it to |
|---|---|---|
account:read | Balance, activation state, brand | Dashboards, monitoring, alerting |
cards:read | List cards, products, designs | Support tooling, reporting |
cards:write | Create, top up, freeze, unfreeze | Only the service that issues cards |
A monitoring job that reads your balance every minute needs account:read and nothing else. If that key leaks, an attacker learns your balance — irritating, not expensive. The same job holding cards:write turns the same leak into a financial loss.
IP allowlisting
This is the highest-value control available and the least used. Restricting a key to the addresses your servers actually use means a leaked key is worthless from anywhere else — a laptop, a CI log, a paste site.
- Individual addresses for fixed servers:
203.0.113.5. - CIDR ranges for a block you control:
198.51.100.0/24. - Both IPv4 and IPv6, because a host with both may egress on either.
The usual objection is dynamic egress addresses. The usual answer is a NAT gateway or a static egress address, which most cloud platforms offer and which is worth configuring for this alone. If you truly cannot pin an address, compensate with narrower scopes and shorter rotation.
Storing keys
- Environment variables or a secrets manager. Never in the repository, including in a
.envthat is only usually gitignored. - Never in client code. A key in a browser bundle or a mobile app is public. Every call that uses one must originate from your server.
- Never in logs. Redact
authorizationheaders globally, at the logger, not at each call site — the leak always comes from the one place someone forgot. - Never in error reports. Exception trackers capture request context by default, and that context frequently includes headers.
Rotation without downtime
Rotation only happens if it is painless. The pattern that makes it painless is supporting two keys at once:
- Create the new key with the same scopes and allowlist.
- Deploy it alongside the old one — your code should accept a primary and a secondary from configuration.
- Verify the new key is being used, from the request log.
- Revoke the old key.
- Remove the secondary configuration at leisure.
Rotate on a schedule, and immediately on any suspicion: someone leaving, a key appearing in a log, a machine being decommissioned, or anything unexplained in the request log.
Watch the request log
ON5 keeps a rolling record of recent API requests per account — method, path, status, latency, IP, request id and error code — visible to you and to ON5 support. It is the fastest way to answer the questions that matter during an incident.
- Requests from an IP you do not recognise.
- A spike in 401s, which usually means a key was revoked somewhere and something is still using it.
- Card creation at a time or rate nobody scheduled.
- Latency changes that indicate something upstream is struggling.
A minimum standard
- Separate keys per environment. Never share one between staging and production.
- One key per service, scoped to what that service does.
- IP allowlists on everything in production.
- Keys in a secrets manager, redacted in logs, absent from client code.
- A rotation procedure that has actually been rehearsed once.
Frequently asked questions
How should payment API keys be stored?
In environment variables or a secrets manager, never in a repository, never in client-side code, and redacted globally at the logger so they cannot reach logs or error reports.
What is API key IP allowlisting?
Restricting a key so it only works from specified IP addresses or CIDR ranges. A leaked key then has no value from anywhere else, which makes it the highest-value control available.
Why do invalid and IP-blocked API keys return the same error?
So the response cannot be used to discover which keys exist. If a blocked key returned a distinguishable error, an attacker could confirm a key is valid simply by trying it from a disallowed address.
How do I rotate an API key without downtime?
Support a primary and secondary key in configuration. Create the new key, deploy it alongside the old, confirm from the request log that it is in use, then revoke the old one.
Issue your first card on ON5
Fund an account with USDT or USDC and issue a branded Visa or Mastercard virtual card. The minimum is $5.
Open the dashboard