Rate limits API
Manage the request and token limits that the Policy Engine's Rate, Token & Timeout Limits card configures, as typed resources. You never write QuilrQL: each write is validated and published as one policy revision. For what a limit counts and what clients see when they hit one, see Rate, token and budget limits.
This page covers rate limits (requests and tokens over a window). Spend budgets, budget grants and pricing are in the Budgets API: they have their own scopes (budgets:*), are priced in USD and report usage from a periodic snapshot, while rate limits count live.
limits:read does not need read. Try every operation in the Management API playground.
Before you start
- The Policy Engine must be on for the LLM Gateway. While it is off, every call answers
409 policy_not_enabled. - Limits are regional. Every gateway in a region shares the same counters, so a limit of 60 requests per minute is 60 for the region, not per gateway. Usage reads report
scope: "regional". - Writes follow the same rules as routing controls: content-idempotent PUT,
If-MatchETags,If-None-Match: *for create only,?dry_run=true, console rows read only, andPOST /controls/_batchfor several changes in one revision. See Writes, versions and idempotency.
Rate limits
{
"label": "Support requests per minute",
"metric": "requests",
"limit": 60,
"window": {"kind": "rolling", "unit": "minute"},
"group_by": ["user"],
"scope": {"apps": ["support-bot"]},
"mode": "enforce",
"adjustments": {"ceiling": 120, "max_duration": "2d"},
"alerts": [{"at_pct": 80}]
}
group_by accepts short aliases; responses return the full field name:
They cannot change in place (422 identity_field_immutable), because usage is counted against them. To change one, create a rate limit with a new id and delete the old one. An id used before with another identity is 422 quota_id_reused.
POST /controls/rate-limits:migrate-legacy converts an app's older per-app window limits into rate limits in one revision; ?dry_run=true shows the result first.
Temporary raises (grants)
A grant raises one subject's limit until expires_at: extra adds to the limit, limit sets it (exactly one). Name the subject by the rate limit's grouping, for example {"user": "alex@example.com"}.
export API="$MANAGEMENT_URL/llmgateway/management/v1"
auth=(-H "Authorization: Bearer $MANAGEMENT_KEY" -H 'Content-Type: application/json')
curl -X POST "$API/controls/rate-limits/support-rpm/grants" "${auth[@]}" -H "Idempotency-Key: launch-alex" \
-d '{"subject": {"user": "alex@example.com"}, "extra": 60, "expires_at": "2026-11-01T00:00:00Z", "reason": "launch"}'
- The rate limit needs
adjustments(409 rate_limit_not_adjustable). A grant aboveceilingis422 grant_above_ceiling; longer thanmax_durationis422 grant_too_long. - A new grant for the same subject supersedes the active one (returned as
superseded). - Revoke with
DELETE /controls/rate-limits/{id}/grants/{grant_id}?reason=...and the grant ETag inIf-Match. - Grants never publish a policy revision.
Usage
GET /controls/rate-limits/{id}/usage returns live counters: one subject's bucket with subject.user= or subject.app= (or bucket=), or the busiest buckets (top, default 20).
Request guards and model limits
- Request guards cap
max_tokens_per_requestandtimeout_sfor a scope. When several apply at one priority, the strictest value wins. - Model limits set the same caps per model:
{"limits": [{"model": "gpt-4.1", "max_tokens_per_request": 4000}]}, with optionalprovider_labelper entry. For requests or tokens per window per model, use a rate limit withgroup_by: ["model"]; the older window keys on model limits are422 deprecated_field.
Exemptions
{"scope": {"users": ["oncall@example.com"]}, "quotas": "all", "reason": "on call", "expires_at": "2027-01-01T00:00:00Z"} skips every rate limit for that user until the expiry. quotas can instead list rate limit ids. Exemptions here cover rate limits only; budget exemptions are in the Budgets API (422 budget_exemption_not_supported). expires_at must be in the future.
Custom limit responses
A limit response replaces the default message of a blocked request for its scope:
{"scope": {"apps": ["support-bot"]}, "message": "Limit {limit} reached; resets {reset}", "url": "https://help.example.com/limits", "retry": "never"}
message may use {limit}, {reset} and {budget}. url must be https://. retry: "never" tells clients not to retry; default keeps the normal retry hint. Two limit responses must name app lists with no app in common, otherwise 422 limit_response_conflict, so each app gets exactly one message.
Effective limits
GET /limits/effective?app=&user=&requested_model=&model=&provider_label= returns every rate limit, request guard and model limit that applies, the one that binds first (tightest, tightest_tokens_per_request), exemptions, grants and the limit response, with live counters unless include_usage=false. unknown_facts lists inputs the active policy reads that the query did not supply (for example a user id); they count as empty.
Errors
Endpoints
Rate limits, usage and grants
/controls/rate-limitsList rate limits
Every managed rate limit with its ETag, then the console policy rules of the same kind as read-only rows (source console, policy, rule_index, view). Console rows cannot be written here (409 rule_not_api_managed). Paginated (limit, cursor bound to the revision) and filtered by source, app, requested_model, mode and references.
limits:readPath, query & header parameters 7
limit (query)integeroptionalPage size.
cursor (query)stringoptionalnext_cursor of the previous page; bound to the revision (409 collection_changed when the policy changed).
source (query)objectoptionalOnly managed resources or only console rows.
"managed""console"app (query)stringoptionalRows that can apply to this app (rows scoped only by smart group, user or tag are kept). app_name is a deprecated alias.
requested_model (query)stringoptionalRows that can apply to this requested model. model is a deprecated alias.
mode (query)stringoptionalRows with this mode (routes: active, observe, disabled; limits: enforce, alert, paused).
references (query)stringoptional<provider_label> or <provider_label>/<model>: rows that name it, following destination and failover-profile refs (adds references [paths]).
No request body.
curl --request GET \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/rate-limits?limit=example' \
--header 'Authorization: Bearer <management-key>'
Authentication, errors & retry rules Try it in the playground
/controls/rate-limits/{resource_id}Delete a rate limit
Removes the rate limit; refused while other controls reference it. If-Match is required.
limits:writePath, query & header parameters 4
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
dry_run (query)booleanoptionalPreview: spec and policy diff, diagnostics, warnings, would_publish and impact; nothing is saved.
If-Match (header)stringrequiredResource ETag "r<revision>-<id>-<hash8>" from the latest read, or the collection ETag "r<revision>". Required to change or delete an existing resource (428 when missing, 412 when stale); an unrelated publish does not invalidate it.
Idempotency-Key (header)stringoptionalUnique per logical write. A retry with the same key and body returns the original result, including after a crash once the revision was published. Optional on PUT, PATCH and DELETE.
Full request body specification application/json
Unknown fields are rejected in this object.
curl --request DELETE \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/rate-limits/eu-pool' \
--header 'Authorization: Bearer <management-key>' \
--header 'If-Match: "r12-eu-pool-1a2b3c4d"'
Authentication, errors & retry rules Try it in the playground
/controls/rate-limits/{resource_id}Read a rate limit
One rate limit and its ETag.
limits:readPath, query & header parameters 1
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
No request body.
curl --request GET \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/rate-limits/eu-pool' \
--header 'Authorization: Bearer <management-key>'
Authentication, errors & retry rules Try it in the playground
/controls/rate-limits/{resource_id}Update a rate limit
JSON merge patch of the rate limit (null removes a field); the result is validated as a whole. If-Match is required. Writes publish one policy revision. A PUT whose content equals the stored resource returns changed false and publishes nothing.
limits:writePath, query & header parameters 4
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
dry_run (query)booleanoptionalPreview: spec and policy diff, diagnostics, warnings, would_publish and impact; nothing is saved.
If-Match (header)stringrequiredResource ETag "r<revision>-<id>-<hash8>" from the latest read, or the collection ETag "r<revision>". Required to change or delete an existing resource (428 when missing, 412 when stale); an unrelated publish does not invalidate it.
Idempotency-Key (header)stringoptionalUnique per logical write. A retry with the same key and body returns the original result, including after a crash once the revision was published. Optional on PUT, PATCH and DELETE.
Full request body specification application/json
A rate limit. Its quota id rl_<id> is customer-visible (the x-quilr-quota-id header of a refused request). metric, group_by and window are the counter's identity: they are ForceNew (changing them is 422 identity_field_immutable; create a rate limit with a new id).
adjustmentsobjectoptionalRequired for temporary raises (grants).
Object fields
auto_approveobjectoptionalObject fields
max_countintegeroptionalperstringoptional"day""week""month"smart_groupsarray<string>optionalArray item specification
stringup_to_pctintegerrequiredUnknown fields are rejected in this object.
ceilingnumberrequiredmax_durationstringoptionaloverflowobjectoptionalObject fields
add_pctintegerrequiredUnknown fields are rejected in this object.
requestablebooleanoptionalUnknown fields are rejected in this object.
alertsarray<object>optionalArray item specification
at_pctintegerrequiredUnknown fields are rejected in this object.
descriptionstringoptionalfamilystringoptionalgroup_byarray<string>optionalOne counter per distinct combination; [] = one shared counter.
Array item specification
stringA QuilrQL field name, or an alias (app = application.group_key, app_key = application.key_id, method = application.method_key, method_type = application.method_type, model = gateway.actual_model, provider = gateway.actual_provider.name, provider_label = gateway.actual_provider.label, smart_group = user.active_smart_group, tenant = tenant.id, user = user.email, user_id = user.id). Aliases are translated; responses return field names.
Values: "tenant.id""user.id""user.email""user.active_smart_group""application.key_id""application.group_key""application.method_key""application.method_type""gateway.actual_provider.name""gateway.actual_provider.label""gateway.actual_model""app""app_key""method""method_type""model""provider""provider_label""smart_group""tenant""user""user_id"
kind"rate"optionallabelstringoptionallimitintegerrequiredmetricobjectrequired"requests""input_tokens""output_tokens""total_tokens"modeobjectoptional"enforce""alert""paused"overridesarray<string>optionalRate quota ids this one replaces where both apply: managed rate limits (rl_<id>) or console quotas of kind rate. Budgets are 422 override_target_not_allowed.
Array item specification
stringquota_idstringoptionalscopeobjectoptionalEvery non-empty list must match (AND); empty or omitted lists do not restrict. Returned with every field present.
Object fields
app_tagsarray<string>optionalArray item specification
stringappsarray<string>optionalArray item specification
stringsmart_groupsarray<string>optionalArray item specification
stringusersarray<string>optionalArray item specification
stringUnknown fields are rejected in this object.
windowone of 2 variantsrequiredVariant 1 object
kind"rolling"requiredsizeintegeroptionalWindow length in units (1 = omitted).
unitobjectrequired"minute""hour""day""week""month""year"Unknown fields are rejected in this object.
Variant 2 object
kind"calendar"requiredtimezonestringoptionalIANA timezone.
unitobjectrequired"day""month""week""year"Unknown fields are rejected in this object.
Unknown fields are rejected in this object.
curl --request PATCH \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/rate-limits/eu-pool' \
--header 'Authorization: Bearer <management-key>' \
--header 'If-Match: "r12-eu-pool-1a2b3c4d"'
Authentication, errors & retry rules Try it in the playground
/controls/rate-limits/{resource_id}Create or replace a rate limit
Creates (201) or replaces (200) the rate limit. Changing an existing one needs If-Match; If-None-Match: * creates only. Writes publish one policy revision. A PUT whose content equals the stored resource returns changed false and publishes nothing.
limits:writePath, query & header parameters 5
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
dry_run (query)booleanoptionalPreview: spec and policy diff, diagnostics, warnings, would_publish and impact; nothing is saved.
If-Match (header)stringoptionalResource ETag "r<revision>-<id>-<hash8>" from the latest read, or the collection ETag "r<revision>". Required to change or delete an existing resource (428 when missing, 412 when stale); an unrelated publish does not invalidate it.
Idempotency-Key (header)stringoptionalUnique per logical write. A retry with the same key and body returns the original result, including after a crash once the revision was published. Optional on PUT, PATCH and DELETE.
If-None-Match (header)"*"optionalCreate only: 412 when the resource exists with different content.
Full request body specification application/json
A rate limit. Its quota id rl_<id> is customer-visible (the x-quilr-quota-id header of a refused request). metric, group_by and window are the counter's identity: they are ForceNew (changing them is 422 identity_field_immutable; create a rate limit with a new id).
adjustmentsobjectoptionalRequired for temporary raises (grants).
Object fields
auto_approveobjectoptionalObject fields
max_countintegeroptionalperstringoptional"day""week""month"smart_groupsarray<string>optionalArray item specification
stringup_to_pctintegerrequiredUnknown fields are rejected in this object.
ceilingnumberrequiredmax_durationstringoptionaloverflowobjectoptionalObject fields
add_pctintegerrequiredUnknown fields are rejected in this object.
requestablebooleanoptionalUnknown fields are rejected in this object.
alertsarray<object>optionalArray item specification
at_pctintegerrequiredUnknown fields are rejected in this object.
descriptionstringoptionalfamilystringoptionalgroup_byarray<string>optionalOne counter per distinct combination; [] = one shared counter.
Array item specification
stringA QuilrQL field name, or an alias (app = application.group_key, app_key = application.key_id, method = application.method_key, method_type = application.method_type, model = gateway.actual_model, provider = gateway.actual_provider.name, provider_label = gateway.actual_provider.label, smart_group = user.active_smart_group, tenant = tenant.id, user = user.email, user_id = user.id). Aliases are translated; responses return field names.
Values: "tenant.id""user.id""user.email""user.active_smart_group""application.key_id""application.group_key""application.method_key""application.method_type""gateway.actual_provider.name""gateway.actual_provider.label""gateway.actual_model""app""app_key""method""method_type""model""provider""provider_label""smart_group""tenant""user""user_id"
kind"rate"optionallabelstringoptionallimitintegerrequiredmetricobjectrequired"requests""input_tokens""output_tokens""total_tokens"modeobjectoptional"enforce""alert""paused"overridesarray<string>optionalRate quota ids this one replaces where both apply: managed rate limits (rl_<id>) or console quotas of kind rate. Budgets are 422 override_target_not_allowed.
Array item specification
stringquota_idstringoptionalscopeobjectoptionalEvery non-empty list must match (AND); empty or omitted lists do not restrict. Returned with every field present.
Object fields
app_tagsarray<string>optionalArray item specification
stringappsarray<string>optionalArray item specification
stringsmart_groupsarray<string>optionalArray item specification
stringusersarray<string>optionalArray item specification
stringUnknown fields are rejected in this object.
windowone of 2 variantsrequiredVariant 1 object
kind"rolling"requiredsizeintegeroptionalWindow length in units (1 = omitted).
unitobjectrequired"minute""hour""day""week""month""year"Unknown fields are rejected in this object.
Variant 2 object
kind"calendar"requiredtimezonestringoptionalIANA timezone.
unitobjectrequired"day""month""week""year"Unknown fields are rejected in this object.
Unknown fields are rejected in this object.
curl --request PUT \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/rate-limits/eu-pool' \
--header 'Authorization: Bearer <management-key>' \
--header 'If-Match: "r12-eu-pool-1a2b3c4d"' \
--header 'Content-Type: application/json' \
--data '{
"adjustments": {
"ceiling": 120,
"max_duration": "2d"
},
"group_by": [
"user.email"
],
"label": "Support requests per minute",
"limit": 60,
"metric": "requests",
"scope": {
"apps": [
"support-bot"
]
},
"window": {
"kind": "rolling",
"unit": "minute"
}
}'
Authentication, errors & retry rules Try it in the playground
/controls/rate-limits/{resource_id}/grantsList rate limit grants
Temporary raises of one rate limit.
limits:readPath, query & header parameters 1
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
No request body.
curl --request GET \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/rate-limits/eu-pool/grants' \
--header 'Authorization: Bearer <management-key>'
Authentication, errors & retry rules Try it in the playground
/controls/rate-limits/{resource_id}/grantsGrant a temporary raise
Raises one subject's limit until expires_at (extra adds to the limit, limit sets it), capped by the rate limit's adjustments. A new grant supersedes the bucket's previous one.
limits:grantPath, query & header parameters 2
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
Idempotency-Key (header)stringrequiredUnique per logical write. A retry with the same key and body returns the original result, including after a crash once the revision was published. Not needed with dry_run=true.
Full request body specification application/json
A temporary raise for one bucket, capped by the rate limit's adjustments. A new grant supersedes the bucket's previous one. POST takes an Idempotency-Key; a retry returns the original grant.
Variant 1 object
objectVariant 2 object
objectcurl --request POST \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/rate-limits/eu-pool/grants' \
--header 'Authorization: Bearer <management-key>' \
--header 'Idempotency-Key: eu-routing-change-001' \
--header 'Content-Type: application/json' \
--data '{
"expires_at": "2026-11-01T00:00:00Z",
"extra": 60,
"reason": "launch",
"subject": {
"user": "alex@example.com"
}
}'
Authentication, errors & retry rules Try it in the playground
/controls/rate-limits/{resource_id}/grants/{grant_id}Revoke a grant
Ends the grant now. If-Match (the grant ETag) is required.
limits:grantPath, query & header parameters 4
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
grant_id (path)stringrequiredIf-Match (header)stringrequiredGrant ETag from the latest read (428 when missing, 412 when stale).
reason (query)stringoptionalRecorded with the revocation.
Full request body specification application/json
Unknown fields are rejected in this object.
curl --request DELETE \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/rate-limits/eu-pool/grants/grt_4f9a2c1b7e3d' \
--header 'Authorization: Bearer <management-key>' \
--header 'If-Match: "3f1c0a9e5b7d"'
Authentication, errors & retry rules Try it in the playground
/controls/rate-limits/{resource_id}/usageRead rate limit usage
Live counters of one rate limit: one subject's bucket, or the busiest buckets.
limits:readPath, query & header parameters 5
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
subject.user (query)stringoptionalOne user's bucket.
subject.app (query)stringoptionalOne app's bucket.
bucket (query)stringoptionalA bucket in canonical form.
top (query)integeroptionalBusiest buckets listed when no subject is given.
No request body.
curl --request GET \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/rate-limits/eu-pool/usage' \
--header 'Authorization: Bearer <management-key>'
Authentication, errors & retry rules Try it in the playground
/controls/rate-limits:migrate-legacyMigrate legacy limits
Converts the deprecated per-app window limits to rate limits in one revision. dry_run=true previews the quotas and diff.
limits:writePath, query & header parameters 2
dry_run (query)booleanoptionalPreview: spec and policy diff, diagnostics, warnings, would_publish and impact; nothing is saved.
Idempotency-Key (header)stringrequiredUnique per logical write. A retry with the same key and body returns the original result, including after a crash once the revision was published. Not needed with dry_run=true.
Full request body specification application/json
dry_runbooleanoptionalUnknown fields are rejected in this object.
curl --request POST \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/rate-limits:migrate-legacy' \
--header 'Authorization: Bearer <management-key>' \
--header 'Idempotency-Key: eu-routing-change-001' \
--header 'Content-Type: application/json' \
--data '{}'
Authentication, errors & retry rules Try it in the playground
Request guards
/controls/request-guardsList request guards
Every managed request guard with its ETag, then the console policy rules of the same kind as read-only rows (source console, policy, rule_index, view). Console rows cannot be written here (409 rule_not_api_managed). Paginated (limit, cursor bound to the revision) and filtered by source, app, requested_model, mode and references.
limits:readPath, query & header parameters 7
limit (query)integeroptionalPage size.
cursor (query)stringoptionalnext_cursor of the previous page; bound to the revision (409 collection_changed when the policy changed).
source (query)objectoptionalOnly managed resources or only console rows.
"managed""console"app (query)stringoptionalRows that can apply to this app (rows scoped only by smart group, user or tag are kept). app_name is a deprecated alias.
requested_model (query)stringoptionalRows that can apply to this requested model. model is a deprecated alias.
mode (query)stringoptionalRows with this mode (routes: active, observe, disabled; limits: enforce, alert, paused).
references (query)stringoptional<provider_label> or <provider_label>/<model>: rows that name it, following destination and failover-profile refs (adds references [paths]).
No request body.
curl --request GET \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/request-guards?limit=example' \
--header 'Authorization: Bearer <management-key>'
Authentication, errors & retry rules Try it in the playground
/controls/request-guards/{resource_id}Delete a request guard
Removes the request guard; refused while other controls reference it. If-Match is required.
limits:writePath, query & header parameters 4
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
dry_run (query)booleanoptionalPreview: spec and policy diff, diagnostics, warnings, would_publish and impact; nothing is saved.
If-Match (header)stringrequiredResource ETag "r<revision>-<id>-<hash8>" from the latest read, or the collection ETag "r<revision>". Required to change or delete an existing resource (428 when missing, 412 when stale); an unrelated publish does not invalidate it.
Idempotency-Key (header)stringoptionalUnique per logical write. A retry with the same key and body returns the original result, including after a crash once the revision was published. Optional on PUT, PATCH and DELETE.
Full request body specification application/json
Unknown fields are rejected in this object.
curl --request DELETE \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/request-guards/eu-pool' \
--header 'Authorization: Bearer <management-key>' \
--header 'If-Match: "r12-eu-pool-1a2b3c4d"'
Authentication, errors & retry rules Try it in the playground
/controls/request-guards/{resource_id}Read a request guard
One request guard and its ETag.
limits:readPath, query & header parameters 1
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
No request body.
curl --request GET \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/request-guards/eu-pool' \
--header 'Authorization: Bearer <management-key>'
Authentication, errors & retry rules Try it in the playground
/controls/request-guards/{resource_id}Update a request guard
JSON merge patch of the request guard (null removes a field); the result is validated as a whole. If-Match is required. Writes publish one policy revision. A PUT whose content equals the stored resource returns changed false and publishes nothing.
limits:writePath, query & header parameters 4
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
dry_run (query)booleanoptionalPreview: spec and policy diff, diagnostics, warnings, would_publish and impact; nothing is saved.
If-Match (header)stringrequiredResource ETag "r<revision>-<id>-<hash8>" from the latest read, or the collection ETag "r<revision>". Required to change or delete an existing resource (428 when missing, 412 when stale); an unrelated publish does not invalidate it.
Idempotency-Key (header)stringoptionalUnique per logical write. A retry with the same key and body returns the original result, including after a crash once the revision was published. Optional on PUT, PATCH and DELETE.
Full request body specification application/json
Per-request token and timeout guards for the scoped requests; where several apply, the strictest value wins.
Variant 1 object
objectVariant 2 object
objectcurl --request PATCH \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/request-guards/eu-pool' \
--header 'Authorization: Bearer <management-key>' \
--header 'If-Match: "r12-eu-pool-1a2b3c4d"'
Authentication, errors & retry rules Try it in the playground
/controls/request-guards/{resource_id}Create or replace a request guard
Creates (201) or replaces (200) the request guard. Changing an existing one needs If-Match; If-None-Match: * creates only. Writes publish one policy revision. A PUT whose content equals the stored resource returns changed false and publishes nothing.
limits:writePath, query & header parameters 5
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
dry_run (query)booleanoptionalPreview: spec and policy diff, diagnostics, warnings, would_publish and impact; nothing is saved.
If-Match (header)stringoptionalResource ETag "r<revision>-<id>-<hash8>" from the latest read, or the collection ETag "r<revision>". Required to change or delete an existing resource (428 when missing, 412 when stale); an unrelated publish does not invalidate it.
Idempotency-Key (header)stringoptionalUnique per logical write. A retry with the same key and body returns the original result, including after a crash once the revision was published. Optional on PUT, PATCH and DELETE.
If-None-Match (header)"*"optionalCreate only: 412 when the resource exists with different content.
Full request body specification application/json
Per-request token and timeout guards for the scoped requests; where several apply, the strictest value wins.
Variant 1 object
objectVariant 2 object
objectcurl --request PUT \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/request-guards/eu-pool' \
--header 'Authorization: Bearer <management-key>' \
--header 'If-Match: "r12-eu-pool-1a2b3c4d"' \
--header 'Content-Type: application/json' \
--data '{
"max_tokens_per_request": 8000,
"scope": {
"smart_groups": [
"eng"
]
},
"timeout_s": 30
}'
Authentication, errors & retry rules Try it in the playground
Model limits
/controls/model-limitsList model limits
Every managed model limit with its ETag, then the console policy rules of the same kind as read-only rows (source console, policy, rule_index, view). Console rows cannot be written here (409 rule_not_api_managed). Paginated (limit, cursor bound to the revision) and filtered by source, app, requested_model, mode and references.
limits:readPath, query & header parameters 7
limit (query)integeroptionalPage size.
cursor (query)stringoptionalnext_cursor of the previous page; bound to the revision (409 collection_changed when the policy changed).
source (query)objectoptionalOnly managed resources or only console rows.
"managed""console"app (query)stringoptionalRows that can apply to this app (rows scoped only by smart group, user or tag are kept). app_name is a deprecated alias.
requested_model (query)stringoptionalRows that can apply to this requested model. model is a deprecated alias.
mode (query)stringoptionalRows with this mode (routes: active, observe, disabled; limits: enforce, alert, paused).
references (query)stringoptional<provider_label> or <provider_label>/<model>: rows that name it, following destination and failover-profile refs (adds references [paths]).
No request body.
curl --request GET \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/model-limits?limit=example' \
--header 'Authorization: Bearer <management-key>'
Authentication, errors & retry rules Try it in the playground
/controls/model-limits/{resource_id}Delete a model limit
Removes the model limit; refused while other controls reference it. If-Match is required.
limits:writePath, query & header parameters 4
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
dry_run (query)booleanoptionalPreview: spec and policy diff, diagnostics, warnings, would_publish and impact; nothing is saved.
If-Match (header)stringrequiredResource ETag "r<revision>-<id>-<hash8>" from the latest read, or the collection ETag "r<revision>". Required to change or delete an existing resource (428 when missing, 412 when stale); an unrelated publish does not invalidate it.
Idempotency-Key (header)stringoptionalUnique per logical write. A retry with the same key and body returns the original result, including after a crash once the revision was published. Optional on PUT, PATCH and DELETE.
Full request body specification application/json
Unknown fields are rejected in this object.
curl --request DELETE \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/model-limits/eu-pool' \
--header 'Authorization: Bearer <management-key>' \
--header 'If-Match: "r12-eu-pool-1a2b3c4d"'
Authentication, errors & retry rules Try it in the playground
/controls/model-limits/{resource_id}Read a model limit
One model limit and its ETag.
limits:readPath, query & header parameters 1
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
No request body.
curl --request GET \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/model-limits/eu-pool' \
--header 'Authorization: Bearer <management-key>'
Authentication, errors & retry rules Try it in the playground
/controls/model-limits/{resource_id}Update a model limit
JSON merge patch of the model limit (null removes a field); the result is validated as a whole. If-Match is required. Writes publish one policy revision. A PUT whose content equals the stored resource returns changed false and publishes nothing.
limits:writePath, query & header parameters 4
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
dry_run (query)booleanoptionalPreview: spec and policy diff, diagnostics, warnings, would_publish and impact; nothing is saved.
If-Match (header)stringrequiredResource ETag "r<revision>-<id>-<hash8>" from the latest read, or the collection ETag "r<revision>". Required to change or delete an existing resource (428 when missing, 412 when stale); an unrelated publish does not invalidate it.
Idempotency-Key (header)stringoptionalUnique per logical write. A retry with the same key and body returns the original result, including after a crash once the revision was published. Optional on PUT, PATCH and DELETE.
Full request body specification application/json
Per-request guards for individual models (provider_label scopes one to a provider). Window limits per model are rate limits with group_by ["model"].
descriptionstringoptionallimitsarray<object | object>requiredArray item specification
Variant 1 object
objectVariant 2 object
objectscopeobjectoptionalEvery non-empty list must match (AND); empty or omitted lists do not restrict. Returned with every field present.
Object fields
app_tagsarray<string>optionalArray item specification
stringappsarray<string>optionalArray item specification
stringsmart_groupsarray<string>optionalArray item specification
stringusersarray<string>optionalArray item specification
stringUnknown fields are rejected in this object.
Unknown fields are rejected in this object.
curl --request PATCH \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/model-limits/eu-pool' \
--header 'Authorization: Bearer <management-key>' \
--header 'If-Match: "r12-eu-pool-1a2b3c4d"'
Authentication, errors & retry rules Try it in the playground
/controls/model-limits/{resource_id}Create or replace a model limit
Creates (201) or replaces (200) the model limit. Changing an existing one needs If-Match; If-None-Match: * creates only. Writes publish one policy revision. A PUT whose content equals the stored resource returns changed false and publishes nothing.
limits:writePath, query & header parameters 5
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
dry_run (query)booleanoptionalPreview: spec and policy diff, diagnostics, warnings, would_publish and impact; nothing is saved.
If-Match (header)stringoptionalResource ETag "r<revision>-<id>-<hash8>" from the latest read, or the collection ETag "r<revision>". Required to change or delete an existing resource (428 when missing, 412 when stale); an unrelated publish does not invalidate it.
Idempotency-Key (header)stringoptionalUnique per logical write. A retry with the same key and body returns the original result, including after a crash once the revision was published. Optional on PUT, PATCH and DELETE.
If-None-Match (header)"*"optionalCreate only: 412 when the resource exists with different content.
Full request body specification application/json
Per-request guards for individual models (provider_label scopes one to a provider). Window limits per model are rate limits with group_by ["model"].
descriptionstringoptionallimitsarray<object | object>requiredArray item specification
Variant 1 object
objectVariant 2 object
objectscopeobjectoptionalEvery non-empty list must match (AND); empty or omitted lists do not restrict. Returned with every field present.
Object fields
app_tagsarray<string>optionalArray item specification
stringappsarray<string>optionalArray item specification
stringsmart_groupsarray<string>optionalArray item specification
stringusersarray<string>optionalArray item specification
stringUnknown fields are rejected in this object.
Unknown fields are rejected in this object.
curl --request PUT \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/model-limits/eu-pool' \
--header 'Authorization: Bearer <management-key>' \
--header 'If-Match: "r12-eu-pool-1a2b3c4d"' \
--header 'Content-Type: application/json' \
--data '{
"limits": [
{
"max_tokens_per_request": 4000,
"model": "gpt-4.1"
}
]
}'
Authentication, errors & retry rules Try it in the playground
Limit exemptions
/controls/limit-exemptionsList limit exemptions
Every managed limit exemption with its ETag, then the console policy rules of the same kind as read-only rows (source console, policy, rule_index, view). Console rows cannot be written here (409 rule_not_api_managed). Paginated (limit, cursor bound to the revision) and filtered by source, app, requested_model, mode and references.
limits:readPath, query & header parameters 7
limit (query)integeroptionalPage size.
cursor (query)stringoptionalnext_cursor of the previous page; bound to the revision (409 collection_changed when the policy changed).
source (query)objectoptionalOnly managed resources or only console rows.
"managed""console"app (query)stringoptionalRows that can apply to this app (rows scoped only by smart group, user or tag are kept). app_name is a deprecated alias.
requested_model (query)stringoptionalRows that can apply to this requested model. model is a deprecated alias.
mode (query)stringoptionalRows with this mode (routes: active, observe, disabled; limits: enforce, alert, paused).
references (query)stringoptional<provider_label> or <provider_label>/<model>: rows that name it, following destination and failover-profile refs (adds references [paths]).
No request body.
curl --request GET \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/limit-exemptions?limit=example' \
--header 'Authorization: Bearer <management-key>'
Authentication, errors & retry rules Try it in the playground
/controls/limit-exemptions/{resource_id}Delete a limit exemption
Removes the limit exemption; refused while other controls reference it. If-Match is required.
limits:writePath, query & header parameters 4
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
dry_run (query)booleanoptionalPreview: spec and policy diff, diagnostics, warnings, would_publish and impact; nothing is saved.
If-Match (header)stringrequiredResource ETag "r<revision>-<id>-<hash8>" from the latest read, or the collection ETag "r<revision>". Required to change or delete an existing resource (428 when missing, 412 when stale); an unrelated publish does not invalidate it.
Idempotency-Key (header)stringoptionalUnique per logical write. A retry with the same key and body returns the original result, including after a crash once the revision was published. Optional on PUT, PATCH and DELETE.
Full request body specification application/json
Unknown fields are rejected in this object.
curl --request DELETE \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/limit-exemptions/eu-pool' \
--header 'Authorization: Bearer <management-key>' \
--header 'If-Match: "r12-eu-pool-1a2b3c4d"'
Authentication, errors & retry rules Try it in the playground
/controls/limit-exemptions/{resource_id}Read a limit exemption
One limit exemption and its ETag.
limits:readPath, query & header parameters 1
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
No request body.
curl --request GET \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/limit-exemptions/eu-pool' \
--header 'Authorization: Bearer <management-key>'
Authentication, errors & retry rules Try it in the playground
/controls/limit-exemptions/{resource_id}Update a limit exemption
JSON merge patch of the limit exemption (null removes a field); the result is validated as a whole. If-Match is required. Writes publish one policy revision. A PUT whose content equals the stored resource returns changed false and publishes nothing.
limits:writePath, query & header parameters 4
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
dry_run (query)booleanoptionalPreview: spec and policy diff, diagnostics, warnings, would_publish and impact; nothing is saved.
If-Match (header)stringrequiredResource ETag "r<revision>-<id>-<hash8>" from the latest read, or the collection ETag "r<revision>". Required to change or delete an existing resource (428 when missing, 412 when stale); an unrelated publish does not invalidate it.
Idempotency-Key (header)stringoptionalUnique per logical write. A retry with the same key and body returns the original result, including after a crash once the revision was published. Optional on PUT, PATCH and DELETE.
Full request body specification application/json
Exempts the scoped requests from rate limits only (kinds is always [rate]; budget exemptions use the budgets API).
expires_atstringoptionalMust be in the future.
familiesarray<string>optionalArray item specification
stringkindsarray<object>optionalArray item specification
objectValues: "rate"
quotasone of 2 variantsrequiredVariant 1 "all"
"all"Variant 2 array<string>
array<string>reasonstringrequiredscopeobjectoptionalEvery non-empty list must match (AND); empty or omitted lists do not restrict. Returned with every field present.
Object fields
app_tagsarray<string>optionalArray item specification
stringappsarray<string>optionalArray item specification
stringsmart_groupsarray<string>optionalArray item specification
stringusersarray<string>optionalArray item specification
stringUnknown fields are rejected in this object.
Unknown fields are rejected in this object.
curl --request PATCH \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/limit-exemptions/eu-pool' \
--header 'Authorization: Bearer <management-key>' \
--header 'If-Match: "r12-eu-pool-1a2b3c4d"'
Authentication, errors & retry rules Try it in the playground
/controls/limit-exemptions/{resource_id}Create or replace a limit exemption
Creates (201) or replaces (200) the limit exemption. Changing an existing one needs If-Match; If-None-Match: * creates only. Writes publish one policy revision. A PUT whose content equals the stored resource returns changed false and publishes nothing.
limits:writePath, query & header parameters 5
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
dry_run (query)booleanoptionalPreview: spec and policy diff, diagnostics, warnings, would_publish and impact; nothing is saved.
If-Match (header)stringoptionalResource ETag "r<revision>-<id>-<hash8>" from the latest read, or the collection ETag "r<revision>". Required to change or delete an existing resource (428 when missing, 412 when stale); an unrelated publish does not invalidate it.
Idempotency-Key (header)stringoptionalUnique per logical write. A retry with the same key and body returns the original result, including after a crash once the revision was published. Optional on PUT, PATCH and DELETE.
If-None-Match (header)"*"optionalCreate only: 412 when the resource exists with different content.
Full request body specification application/json
Exempts the scoped requests from rate limits only (kinds is always [rate]; budget exemptions use the budgets API).
expires_atstringoptionalMust be in the future.
familiesarray<string>optionalArray item specification
stringkindsarray<object>optionalArray item specification
objectValues: "rate"
quotasone of 2 variantsrequiredVariant 1 "all"
"all"Variant 2 array<string>
array<string>reasonstringrequiredscopeobjectoptionalEvery non-empty list must match (AND); empty or omitted lists do not restrict. Returned with every field present.
Object fields
app_tagsarray<string>optionalArray item specification
stringappsarray<string>optionalArray item specification
stringsmart_groupsarray<string>optionalArray item specification
stringusersarray<string>optionalArray item specification
stringUnknown fields are rejected in this object.
Unknown fields are rejected in this object.
curl --request PUT \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/limit-exemptions/eu-pool' \
--header 'Authorization: Bearer <management-key>' \
--header 'If-Match: "r12-eu-pool-1a2b3c4d"' \
--header 'Content-Type: application/json' \
--data '{
"expires_at": "2027-01-01T00:00:00Z",
"quotas": "all",
"reason": "on call",
"scope": {
"users": [
"oncall@example.com"
]
}
}'
Authentication, errors & retry rules Try it in the playground
Limit responses
/controls/limit-responsesList limit responses
Every managed limit response with its ETag, then the console policy rules of the same kind as read-only rows (source console, policy, rule_index, view). Console rows cannot be written here (409 rule_not_api_managed). Paginated (limit, cursor bound to the revision) and filtered by source, app, requested_model, mode and references.
limits:readPath, query & header parameters 7
limit (query)integeroptionalPage size.
cursor (query)stringoptionalnext_cursor of the previous page; bound to the revision (409 collection_changed when the policy changed).
source (query)objectoptionalOnly managed resources or only console rows.
"managed""console"app (query)stringoptionalRows that can apply to this app (rows scoped only by smart group, user or tag are kept). app_name is a deprecated alias.
requested_model (query)stringoptionalRows that can apply to this requested model. model is a deprecated alias.
mode (query)stringoptionalRows with this mode (routes: active, observe, disabled; limits: enforce, alert, paused).
references (query)stringoptional<provider_label> or <provider_label>/<model>: rows that name it, following destination and failover-profile refs (adds references [paths]).
No request body.
curl --request GET \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/limit-responses?limit=example' \
--header 'Authorization: Bearer <management-key>'
Authentication, errors & retry rules Try it in the playground
/controls/limit-responses/{resource_id}Delete a limit response
Removes the limit response; refused while other controls reference it. If-Match is required.
limits:writePath, query & header parameters 4
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
dry_run (query)booleanoptionalPreview: spec and policy diff, diagnostics, warnings, would_publish and impact; nothing is saved.
If-Match (header)stringrequiredResource ETag "r<revision>-<id>-<hash8>" from the latest read, or the collection ETag "r<revision>". Required to change or delete an existing resource (428 when missing, 412 when stale); an unrelated publish does not invalidate it.
Idempotency-Key (header)stringoptionalUnique per logical write. A retry with the same key and body returns the original result, including after a crash once the revision was published. Optional on PUT, PATCH and DELETE.
Full request body specification application/json
Unknown fields are rejected in this object.
curl --request DELETE \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/limit-responses/eu-pool' \
--header 'Authorization: Bearer <management-key>' \
--header 'If-Match: "r12-eu-pool-1a2b3c4d"'
Authentication, errors & retry rules Try it in the playground
/controls/limit-responses/{resource_id}Read a limit response
One limit response and its ETag.
limits:readPath, query & header parameters 1
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
No request body.
curl --request GET \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/limit-responses/eu-pool' \
--header 'Authorization: Bearer <management-key>'
Authentication, errors & retry rules Try it in the playground
/controls/limit-responses/{resource_id}Update a limit response
JSON merge patch of the limit response (null removes a field); the result is validated as a whole. If-Match is required. Writes publish one policy revision. A PUT whose content equals the stored resource returns changed false and publishes nothing.
limits:writePath, query & header parameters 4
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
dry_run (query)booleanoptionalPreview: spec and policy diff, diagnostics, warnings, would_publish and impact; nothing is saved.
If-Match (header)stringrequiredResource ETag "r<revision>-<id>-<hash8>" from the latest read, or the collection ETag "r<revision>". Required to change or delete an existing resource (428 when missing, 412 when stale); an unrelated publish does not invalidate it.
Idempotency-Key (header)stringoptionalUnique per logical write. A retry with the same key and body returns the original result, including after a crash once the revision was published. Optional on PUT, PATCH and DELETE.
Full request body specification application/json
The response sent when a limit refuses a request. Two different responses must pin scope.apps to lists with no app in common (else 422 limit_response_conflict).
Variant 1 object
objectVariant 2 object
objectVariant 3 object
objectcurl --request PATCH \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/limit-responses/eu-pool' \
--header 'Authorization: Bearer <management-key>' \
--header 'If-Match: "r12-eu-pool-1a2b3c4d"'
Authentication, errors & retry rules Try it in the playground
/controls/limit-responses/{resource_id}Create or replace a limit response
Creates (201) or replaces (200) the limit response. Changing an existing one needs If-Match; If-None-Match: * creates only. Writes publish one policy revision. A PUT whose content equals the stored resource returns changed false and publishes nothing.
limits:writePath, query & header parameters 5
resource_id (path)stringrequiredClient-chosen control ID, ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$ (console rules read as console:<policy>:<rule_index>).
dry_run (query)booleanoptionalPreview: spec and policy diff, diagnostics, warnings, would_publish and impact; nothing is saved.
If-Match (header)stringoptionalResource ETag "r<revision>-<id>-<hash8>" from the latest read, or the collection ETag "r<revision>". Required to change or delete an existing resource (428 when missing, 412 when stale); an unrelated publish does not invalidate it.
Idempotency-Key (header)stringoptionalUnique per logical write. A retry with the same key and body returns the original result, including after a crash once the revision was published. Optional on PUT, PATCH and DELETE.
If-None-Match (header)"*"optionalCreate only: 412 when the resource exists with different content.
Full request body specification application/json
The response sent when a limit refuses a request. Two different responses must pin scope.apps to lists with no app in common (else 422 limit_response_conflict).
Variant 1 object
objectVariant 2 object
objectVariant 3 object
objectcurl --request PUT \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/controls/limit-responses/eu-pool' \
--header 'Authorization: Bearer <management-key>' \
--header 'If-Match: "r12-eu-pool-1a2b3c4d"' \
--header 'Content-Type: application/json' \
--data '{
"message": "Limit {limit} reached; resets {reset}",
"retry": "never",
"url": "https://help.example.com/limits"
}'
Authentication, errors & retry rules Try it in the playground
Effective limits
/limits/effectiveRead effective limits
Every quota, request guard and model limit that applies to an app, user and model, the binding one, exemptions and grants, with live counters.
limits:readPath, query & header parameters 6
app (query)stringoptionalApp name.
user (query)stringoptionalUser email.
requested_model (query)stringoptionalRequested model.
model (query)stringoptionalDeprecated alias of requested_model.
provider_label (query)stringoptionalProvider label of the target.
include_usage (query)booleanoptionalAdd live counters.
No request body.
curl --request GET \
'https://guardrails-usa-1.quilr.ai/llmgateway/management/v1/limits/effective' \
--header 'Authorization: Bearer <management-key>'
Authentication, errors & retry rules Try it in the playground
Related
- Rate, token and budget limits - what limits count and what clients see.
- Budgets API - spend, request and token budgets with pricing and budget grants.
- Routing and failover API - the write, ETag and restore rules shared by every control.
- Management API - authentication, scopes, errors and retry rules.