IP allowlist and rate limits
Two controls sit in front of every call you make, in this order: the IP allowlist decides whether the call is looked at, and the rate limiter decides whether it is served now. A call refused by the allowlist never spends your rate budget.
IP allowlist
Section titled “IP allowlist”Your client carries a list of addresses it may call from. The list is set by the bank when the client is created and changed through your relationship manager; you cannot edit it through the API.
- Entries are plain addresses (
203.0.113.10) or CIDR blocks (203.0.113.0/24,2001:db8::/32). IPv4 and IPv6 are both accepted. - An empty list means no restriction. The bank will normally insist on a non-empty list for production.
- The list is checked twice: once at the token endpoint, and again on every subsequent call. Issuing a token from an allowed address does not let the token be used from a disallowed one, and narrowing the list takes effect on the next request, not at token expiry.
- The address compared is the one the bank’s edge sees the connection coming from. Headers you add (
X-Forwarded-For,X-Real-IP) are never trusted. If you call through a NAT gateway or an egress proxy, the allowlist must contain that address. - An entry that cannot be parsed is ignored, and an allowlist that exists but matches nothing denies. Make sure every entry you give the bank is a valid address or block.
A refused call is answered with HTTP 403 and:
{ "code": "IP_NOT_ALLOWED", "message": "Access denied from this IP address"}At the token endpoint the same refusal comes back in the native error shape with errorCode IP_NOT_ALLOWED; see Authentication.
Per-minute limit
Section titled “Per-minute limit”Each client has a requests-per-minute budget, stored on the client record and shown on the portal’s API access page. The bank sets it when the client is created (600 per minute if nothing else is specified) and can change it on request; a change applies to your very next call.
How it is counted:
- A sliding 60-second window, not a calendar minute: at any instant, the number of calls you made in the preceding 60 seconds.
- One window per client, covering every endpoint together, across all of the bank’s API nodes. A cheap call is refused the moment an expensive polling loop has spent the budget.
- Only authenticated calls count. A call refused by the allowlist, or with a bad token, is not counted.
- A refused call is not counted either, so hammering a 429 does not push the reset further out.
Rate limit headers
Section titled “Rate limit headers”Every authenticated response carries three headers, whether or not you are close to the limit:
| Header | Meaning |
|---|---|
X-RateLimit-Limit |
Your per-minute budget |
X-RateLimit-Remaining |
Calls left in the current sliding window, before this call was counted |
X-RateLimit-Reset |
Unix time in seconds, 60 seconds from now. The window is fully clear by then if you make no further calls |
Because the window slides, Remaining recovers gradually as old calls age out rather than jumping back to Limit at Reset.
When you are refused
Section titled “When you are refused”Exhausting the budget returns HTTP 429 with:
HTTP/1.1 429 Too Many RequestsRetry-After: 60X-RateLimit-Limit: 600X-RateLimit-Remaining: 0X-RateLimit-Reset: 1775054460Content-Type: application/json
{"code":"RATE_LIMIT_EXCEEDED","message":"Too many requests. Retry after 60 seconds."}Retry-After is always 60. In practice capacity returns sooner as the window slides, but 60 seconds is the guarantee.
A 429 is produced before your request reaches any business logic. No money moves on a 429, so retrying with the same reference is always safe; see Idempotency.
The token endpoint
Section titled “The token endpoint”The token endpoint is unauthenticated, so the per-client window above does not apply to it. It is protected instead by a per-source-address limit at the bank’s edge that refuses short bursts. You should never meet it: fetch one token, cache it, and refresh shortly before expires_in elapses. A client that fetches a token per request will be refused at the edge long before it is refused by the per-minute window.
Backoff advice
Section titled “Backoff advice”- Read
X-RateLimit-Remainingon every response and throttle yourself when it gets low, rather than waiting for a 429. - On a 429, wait at least
Retry-Afterseconds, then retry with exponential backoff and jitter. Do not retry in a tight loop; refused calls are logged and a sustained burst looks like an incident to the bank. - Treat a 429 as a signal from your own code, not the user’s. Queue the work and drain it at a steady rate.
- Replace polling with webhooks wherever one exists. Balance polling and check-transaction loops are the usual way partners exhaust the window; an inflow or transaction webhook costs you nothing. See Events and payloads.
- Batch jobs (end-of-day statements, bulk funding) should run at a fixed rate below the limit, not as fast as the network allows.
- If you have a legitimate sustained need above your budget, ask your relationship manager for a higher limit before go-live rather than after the first 429 in production.
In the portal
Section titled “In the portal”The API access page shows the client’s IP allowlist, its per-minute and per-day limits, and the time and address of its last use.