Gateway Policy & Security
Each API has a gateway policy that controls how the API Gateway treats its calls. Set it in the Gateway policy card on the API's edit page (while the API is in Draft or Rejected), or as gateway_policy in the API.
The defaults are deliberately safe for existing APIs: limits are generous, and the strict checks are opt-in per API.
| Setting | Default | What it does |
|---|---|---|
| Calls per minute (API) | 600 | Total calls to this API per minute, across all users |
| Calls per minute (per user) | 120 | Calls per signed-in user per minute (needs a caller identity) |
| Max request size | 5 MB | Larger request bodies are refused with 413 |
| Max response size | 10 MB | Larger upstream responses are refused with 502 |
| Validate requests against the spec | Off | Refuse calls that don't match the OpenAPI spec (400) |
| Require a signed caller identity | Off | Refuse calls that don't carry a caller token (401) |
| Mask sensitive data | None | Mask PAN, Aadhaar, card numbers, emails, mobile numbers or custom patterns in responses |
Leave a limit empty to use the instance default. Instance defaults come from environment variables (see Configuration).
Rate limits
Two rolling one-minute limits apply to every call: one for the whole API and one per user. A call over either limit gets:
HTTP/1.1 429 Too Many Requests
Retry-After: 6
{"error": "rate_limited", "message": "Rate limit exceeded for this API (600 calls per minute). Retry shortly.", "reference": "..."}
Limits are counted in Redis when it's configured (so they hold across multiple Hrida.ai replicas) and in memory otherwise. Refused calls count toward the limit, so a looping agent can't hammer the upstream by retrying instantly.
Size caps
- Requests — checked from
Content-Lengthbefore the body is read, and again while it's read. - Responses — read in chunks; the read stops as soon as the cap is passed, so a single huge upstream response can't exhaust server memory.
Request validation
With Validate requests against the OpenAPI spec on, the gateway checks each call before it reaches any mapper or the upstream:
- Path and query parameters — required parameters present, values match their schema type (integers, numbers, booleans) and constraints.
- JSON request body — validated against the operation's
requestBodyschema, including$refs intocomponents(OpenAPI 3) ordefinitions(Swagger 2), and OpenAPI 3.0nullable.
{
"error": "request_invalid",
"message": "Request does not match the API specification: body.amount: 0 is less than the minimum of 1; body: 'currency' is a required property",
"reference": "..."
}The message lists up to 20 problems so the calling agent can correct its request. Turn it on once your spec accurately describes the upstream — a loose or incomplete spec will refuse valid calls.
Caller identity
With Require a signed caller identity on, the API only accepts calls made by Hrida.ai agents on behalf of a signed-in user. Every call is then attributed to a user in the call log, counted against the per-user limit, and re-checked against the API's access grants.
Leave it off for APIs that automations or scheduled jobs call without a user context. When it's off, a caller token is still verified and enforced if one is sent. See Caller identity for how the token works.
Response masking
Masking replaces sensitive values in responses before they reach the agent (and therefore the model). It applies to every string in a JSON response, including nested values, and to text responses such as XML or CSV.
| Preset | Example input | Masked |
|---|---|---|
| PAN (India) | ABCDE1234F | AB******4F |
| Aadhaar | 2345 6789 0123 | XXXX XXXX 0123 |
| Card numbers | 4111 1111 1111 1111 | **** **** **** 1111 |
| Email addresses | asha.rao@bank.in | a***@bank.in |
| Mobile numbers (India) | +91 98765 43210 | ******3210 |
- Card numbers are only masked when they pass the Luhn checksum, so other long numbers (order ids, references) are left alone.
- Aadhaar ignores 12-digit runs that are part of a longer number.
- Custom rules take a regular expression (up to 200 characters, checked when you save) and a replacement, for example
ACC-\d+→ACC-****.
Masking runs after the response mappers, so it also covers fields a mapper adds. Individual strings over 100 KB are not masked.
Upstream host allow-list
Admins can restrict which hosts any API's upstream may point at. Open API Builder → Gateway settings (admins only) and list one host per line:
api.partner.com
*.bank.internal
*.bank.internalmatches any subdomain ofbank.internal, but notbank.internalitself.- An empty list allows any host (subject to the network protections below).
- The list is checked when an API is saved, when it's published, and on every gateway call — tightening the list immediately blocks published APIs on hosts that are no longer allowed (
502 upstream_blocked).
The initial value can come from API_BUILDER_UPSTREAM_ALLOWED_HOSTS (comma-separated); after that it's managed in the UI.
Network protections
These apply to every API regardless of policy:
- Upstream URLs must be absolute
http/httpsURLs with no credentials embedded (put credentials in the auth settings). - Internal addresses are blocked — loopback (
localhost,127.0.0.1,::1), link-local and cloud-metadata addresses (169.254.0.0/16, including169.254.169.254), unspecified and multicast addresses. Private networks such as10.xand192.168.xstay allowed, since internal enterprise APIs are a primary use case. - DNS is re-checked on every call, so a hostname that later starts resolving to a blocked address (DNS rebinding) is still refused.
- Path tricks —
.and..segments are refused, and only operations in the spec are reachable. - XML from upstreams and samples is parsed with protections against entity-expansion and external-entity attacks.
API_BUILDER_ALLOW_LOCAL_UPSTREAMS=true allows loopback upstreams for local development. Link-local and metadata addresses stay blocked even then.
Configuration
| Environment variable | Default | Purpose |
|---|---|---|
API_GATEWAY_RATE_LIMIT_PER_MINUTE | 600 | Default calls per minute per API |
API_GATEWAY_USER_RATE_LIMIT_PER_MINUTE | 120 | Default calls per minute per user |
API_GATEWAY_MAX_REQUEST_BYTES | 5242880 | Default max request body (bytes) |
API_GATEWAY_MAX_RESPONSE_BYTES | 10485760 | Default max upstream response (bytes) |
API_GATEWAY_CALLER_TOKEN_TTL_SECONDS | 900 | Lifetime of caller identity tokens |
API_GATEWAY_CALL_LOG_RETENTION_DAYS | 30 | How long call log rows are kept |
API_BUILDER_UPSTREAM_ALLOWED_HOSTS | (empty) | Initial host allow-list, comma-separated |
API_BUILDER_ALLOW_LOCAL_UPSTREAMS | false | Allow loopback upstreams (local development only) |
ENABLE_API_BUILDER | true | Turn API Builder on or off for the whole instance |
The features.api_builder user permission controls which non-admin users can use API Builder. Both it and ENABLE_API_BUILDER are enforced by the server, not just by hiding the menu.
Related
- API Gateway — the full request pipeline and error codes
- Upstream Authentication & TLS — how the gateway authenticates to the upstream
- Gateway Call Log — see what the policy refused and why