Guardrails
Control models, providers, budgets and request content.
A guardrail is a set of rules for requests. You assign it to the organization, a workspace, a member or a key. Every guardrail that covers a request applies. When two guardrails disagree, the stricter rule wins.
Guardrails apply to POST /v1/chat/completions, /v1/messages, /v1/responses, /v1/images/generations, /v1/videos and /v1/decisions. You manage them with the management API.
In the console, open Governance > Guardrails for the rules. Open Governance > Budgets for the spending limits.
Create and assign a guardrail
- 01
Create the guardrail with a management key:
curl https://dev2-api.routerplus.com/v1/guardrails \ -H "Authorization: Bearer $TM_MANAGEMENT_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "support-bot", "blocked_models": ["openai/gpt-oss-20b"], "content_rules": [{"kind": "pii", "preset": "email", "action": "redact"}]}'The response is
201.dataholds the guardrail and itsguardrail_id. - 02
Assign the guardrail. It has no effect until you do.
target_kindis the organization, a workspace, a member or a key:curl https://dev2-api.routerplus.com/v1/guardrails/$GUARDRAIL_ID/assignments \ -H "Authorization: Bearer $TM_MANAGEMENT_KEY" \ -H "Content-Type: application/json" \ -d '{"target_kind": "org", "target_id": "'$ORG_ID'"}'
A change applies within 5 seconds. With the guardrail above:
- A call to
openai/gpt-oss-20breturns403witherror.codeguardrail_blocked. - A call that contains an email address goes to the provider with
[REDACTED:email]in its place. The response carriesx-tm-guardrail-actions: redacted.
Rules
Unknown fields are refused.
| Field | Type | Effect |
|---|---|---|
allowed_models | string[] | Only these models. * matches any run of characters, ? one character. Empty means every model. |
blocked_models | string[] | Never these models. |
allowed_providers | string[] | Only these providers. Empty means every provider. |
blocked_providers | string[] | Never these providers. |
zdr | boolean | Only providers that keep no prompts or completions. |
data_collection | "deny" | Only providers that do not train on or keep request data. |
allowed_regions | string[] | Only providers that process requests in these regions (us, eu, in, ...). global allows all. |
blocked_infrastructure | string[] | Never providers that run on these clouds (aws, gcp, azure, ...). |
budgets | object[] | Spending limits. See Budgets. |
limit_usd, reset_interval, include_byok_in_budgets | One budget in a short form: a USD limit, its period, and whether BYOK spend counts. | |
rpm, tpm | integer | Requests and tokens per minute for each key the guardrail covers. |
max_output_tokens | integer | The most output a request may ask for. RouterPlus lowers a larger limit to this value. |
server_tools | "allow" or "block" | block refuses requests that ask the provider to run tools (web search, web fetch, code execution). |
content_rules | object[] | Rules on request text. See Content rules. |
on_scan_limit | "allow" or "block" | What to do with a request too long to scan in full. RouterPlus scans the first 2,000,000 characters. Default allow. |
overridable | false | Makes the guardrail a hard limit. See Grants. |
A filter on a provider fact leaves out each provider for which RouterPlus does not know that fact. For example, zdr: true leaves out a provider that does not publish its retention.
Regions and infrastructure
- RouterPlus records a provider's regions and infrastructure only from the provider's published terms: its privacy policy, data processing terms, subprocessor list or docs.
allowed_regionskeeps only providers whose terms state where they process requests.- RouterPlus does not record a region that a provider offers only as an option RouterPlus does not use.
blocked_infrastructureleaves out a provider that names a blocked cloud for serving or hosting.GET /v1/models/<model>/endpointsshows each provider'sregionsandinfrastructureunderdata_policy.
Budgets
{ "budgets": [
{ "id": "monthly", "limit_usd": 500, "period": "month" },
{ "id": "opus", "limit_usd": 50, "period": "week", "model": "claude-opus-*" },
{ "id": "team-pool", "limit_usd": 2000, "period": "month", "shared": true, "include_byok": true }
] }periodisday,week(from Monday),monthorlifetime. Periods start at 00:00 UTC. A budget with no period islifetime.modelandprovidercount only the spend on that model or provider.include_byokalso counts the provider cost of requests on your own provider keys.shared: truemakes one budget for everything the guardrail is assigned to. Without it, each assignment has its own budget. For example, a guardrail on a workspace counts the spend of that workspace.- A key also has its own limit:
limitwithlimit_reseton the key.
RouterPlus refuses a request when its budget is used up. Requests that are already running finish. Spend can go past the limit by the cost of those requests.
Content rules
{ "content_rules": [
{ "kind": "pii", "preset": "credit_card", "action": "block" },
{ "kind": "pii", "preset": "email", "action": "redact" },
{ "kind": "regex", "pattern": "PROJ-[0-9]{4}", "action": "redact", "label": "project_code" },
{ "kind": "injection", "action": "block" }
] }piipresets:email,phone,ssn,credit_card,iban,ip_address,credential,aws_access_key,private_key,jwt,us_passport.regex: up to 512 characters, with flagsi,m,sandu. A pattern with lookarounds, backreferences or nested quantifiers returnsinvalid_regex_pattern.injectionfinds prompt-injection and jailbreak patterns in user text and tool results.action:redactputs[REDACTED:<label>]in place of the match before RouterPlus sends the request.blockrefuses the request.flagrecords the match and sends the request unchanged.
- When two guardrails have the same pattern with different actions,
blockwins overredact, andredactwins overflag.
Content rules read message text, tool-call arguments and tool results. They do not read images or tool definitions. RouterPlus does not store the matched text. The record holds the rule, the count and the place in the request where it matched.
Errors
| Status | error_type | When |
|---|---|---|
| 401 | key_expired | The key's expires_at has passed. |
| 403 | ip_not_allowed | The key has an IP allowlist and the request comes from another address. |
| 403 | guardrail_blocked | A model, server tool or content rule refused the request. The message names the guardrail and its id, or the content rule ids. |
| 403 | budget_exceeded | A budget is used up. x-tm-cap-reset gives the time it resets. |
| 429 | rate_limit | A guardrail's rpm or tpm is reached. |
| 404 | model_unavailable | No provider of the model meets the guardrails. |
The 401 and 403 refusals carry x-should-retry: false. Do not retry them.
Response headers:
x-tm-guardrails: the ids of the guardrails that applied.x-tm-guardrail-actions:redactedorflagged, when a content rule acted.x-tm-guardrails: unavailable: RouterPlus could not read your guardrails, so the request ran without them.
Grants
A grant is a time-boxed exception to one rule. An approved grant applies from starts_at until expires_at. After expires_at, the base rule applies again.
| Grant type | What it changes |
|---|---|
budget | Raises one budget of a guardrail to a higher limit_usd. |
key_limit | Raises a key's own limit to a higher limit_usd. |
guardrail | Lets one model (allow_model, an id or pattern) pass that guardrail's allowed_models and blocked_models. Every other guardrail still applies. |
- A grant lasts at most 90 days.
- A budget or key limit grant must raise the limit. When two grants cover the same limit, the higher one applies.
- A guardrail with
overridable: falseis a hard limit. It takes no grant. Its organization-level budgets also cap every budget grant for the same period. - A management key can request, approve, reject, cancel and list grants. An API key can request a grant for itself, and list, read and cancel the grants it requested.
- RouterPlus sends a notice when a grant is requested, decided or cancelled, and one day before it expires.
In the console, open Access > Grants. For the endpoints, see Grants in the management API.
Activity
GET /v1/guardrails/events lists the requests that a guardrail blocked, redacted or flagged. In the console, open Governance > Guardrail events.
For agents: /docs/guardrails.md and /llms.txt