Policies
Restrict which models and providers the AI Gateway may use, at organization or application scope.
A policy decides what the gateway is allowed to do with a request before it picks a provider. Use it to hold an application to an approved model list, to force zero-data-retention routing, or to stop a caller asking for a 100,000-token answer.
What a policy controls
| Field | Default | Effect |
|---|---|---|
allowedModels | null | Allow-list of model ids. null allows every model |
allowedProviders | null | Allow-list of routing-provider ids. null allows every provider |
requireZdr | false | Route only to providers with zero-data-retention handling |
allowFallbacks | true | When false, fallback_models is stripped and provider fallback is off |
maxOutputTokens | null | Ceiling on output tokens per request |
maxOutputTokens does double duty. A request whose max_tokens is above the cap is rejected; a request
that omits max_tokens gets the cap applied as its default.
allowedProviders names routes, not owners. The 18 valid ids are openrouter, deepinfra, togetherai,
openai, anthropic, google, google-vertex, amazon-bedrock, xai, alibaba, mistral,
deepseek, groq, cerebras, cohere, perplexity, fireworks-ai and huggingface. An unknown model
id or provider id in either list is rejected with HTTP 400 at write time, so a typo cannot quietly block
traffic later.
Organization and application scope
An organization has one default policy. Any application may have its own, and the two do not merge: when an application has its own policy it is used whole, and the organization policy is ignored for that application.
That is why the console refuses to save an empty application policy over an application that has none. An allow-everything override would silently lift the organization's restrictions for that application, so the Policies page in application scope shows "This application inherits the organization policy" and blocks the save until you actually restrict something.
Writing a policy needs the network:ai_gateway:policies:write scope, and a user acting on their own
behalf must be an owner or admin of the organization. Reading needs
network:ai_gateway:policies:read. Every write is recorded in the audit log under ai_gateway_policy.
A gigadrive login session carries neither scope, so the CLI reaches these commands through an
organization API key exported as GIGADRIVE_CLIENT_ID and GIGADRIVE_CLIENT_SECRET.
Setting a policy
PUT replaces the policy rather than patching it. A field you leave out reverts to its default, so send
the whole object every time.
import { GigadriveClient } from '@gigadrive/sdk';
const client = new GigadriveClient({
clientId: process.env.GIGADRIVE_CLIENT_ID,
clientSecret: process.env.GIGADRIVE_CLIENT_SECRET,
});
const organizationId = '0197b2f0-8b6d-7c2a-9f4e-111111111111';
// Organization default
await client.organizations.aiGateway.policies.put(organizationId, {
allowedModels: ['openai/gpt-4o', 'anthropic/claude-haiku-4-5'],
allowedProviders: ['openai', 'anthropic'],
requireZdr: true,
allowFallbacks: false,
maxOutputTokens: 4096,
});
// Override for one application
await client.organizations.aiGateway.policies.put(organizationId, {
applicationId: '0195c11c-0000-7000-8000-000000000042',
allowedModels: ['anthropic/claude-haiku-4-5'],
maxOutputTokens: 1024,
});
const effective = await client.organizations.aiGateway.policies.get(organizationId, {
applicationId: '0195c11c-0000-7000-8000-000000000042',
});What a blocked request returns
Policy refusals happen before routing and come back as HTTP 403 with "type": "policy_violation". The
code names which rule stopped it.
| Code | Cause |
|---|---|
policy_model_not_allowed | model is not on allowedModels |
policy_fallback_model_not_allowed | An entry in fallback_models is not on allowedModels |
policy_provider_not_allowed | The caller's provider.order and allowedProviders have nothing in common |
policy_max_output_tokens_exceeded | max_tokens is above maxOutputTokens |
A policy that permits the request still shapes it. requireZdr forces provider.require_zdr,
allowFallbacks: false leaves the first eligible provider and nothing behind it, and an
allowedProviders list narrows the routing order rather than adding to it.
