AI Gateway management API reference
Stacklok LLM Gateway Management API (0.1.0)
Download OpenAPI specification:Download
Admin-scoped HTTP API backing the help-desk UI. The server is a thin
facade over the Kubernetes API: write endpoints translate to typed
AIPolicy CR create/update/delete calls via controller-runtime, and
introspection endpoints read from the same cache. No parallel store.
Each API server instance is bound to exactly one Kubernetes namespace
(configured via operator flag) and all AIPolicy CRs live in that
namespace. The namespace is therefore not in the URL path; multi-
namespace deployments run multiple API instances. A future major version
may introduce /v1/namespaces/{ns}/... if multi-tenant scoping is
required; clients should treat the current paths as namespace-local.
GET on a single policy returns an ETag header whose value is the
quoted metadata.resourceVersion. PATCH and DELETE both
require the If-Match header. Concurrency failures use distinct
status codes so the UI can branch without parsing error strings:
- 428 Precondition Required (RFC 6585) —
If-Matchheader is missing. This is a client bug; UIs should surface it as a dev-tools error rather than a user-facing "policy changed" dialog. - 412 Precondition Failed (RFC 7232) —
If-Matchwas sent but the value no longer matches the server'sresourceVersion(another admin edited concurrently). UIs should re-fetch and offer a merge/overwrite flow. - 409 Conflict — reserved for
POSTwith ametadata.namethat already exists. UIs should prompt for a different name.
List all MCP servers visible to the gateway.
Forward-compatible; always returns an empty items array in
Phase 8. Enforcement lands in a later phase.
Authorizations:
header Parameters
| X-Request-Id | string Correlation ID; echoed on responses and included in audit records. |
Responses
Response samples
- 200
- 401
- 429
- 503
{- "items": [
- {
- "description": "string",
- "name": "string",
- "ready": true
}
]
}List all models visible to the gateway in the current namespace.
Derived from the owning AIGateway's spec.routes[].match.model.
Deduplicated and sorted by model id, OpenAI-shaped
(object:"list", data[]) to match the data-plane
GET /v1/models intercept.
Authorizations:
header Parameters
| X-Request-Id | string Correlation ID; echoed on responses and included in audit records. |
Responses
Response samples
- 200
- 400
- 401
- 403
- 404
- 429
- 503
{- "data": [
- {
- "context_window": 200000,
- "created": 1690000000,
- "display_name": "string",
- "id": "openai/gpt-4o-mini",
- "object": "model",
- "owned_by": "openai"
}
], - "object": "list"
}Return the owning gateway's identity.
Returns the AIGateway name and namespace this api-key-service serves. Sourced from the operator-injected GATEWAY_NAME / GATEWAY_NAMESPACE — authoritative and unambiguous.
Authorizations:
header Parameters
| X-Request-Id | string Correlation ID; echoed on responses and included in audit records. |
Responses
Response samples
- 200
- 401
{- "name": "prod-gateway",
- "namespace": "llm-gateway"
}Return the caller's identity and resolved policy bindings.
Returns subject, groups, resolved roles, the set of AIPolicies whose principalMatchers the caller satisfies, and the union of models granted by those policies' budgets. Matched-only — the response never includes policies the caller does not match.
Authorizations:
header Parameters
| X-Request-Id | string Correlation ID; echoed on responses and included in audit records. |
Responses
Response samples
- 200
- 401
- 403
- 429
- 503
{- "email": "admin@example.com",
- "groups": [
- "string"
], - "matchedPolicies": [
- {
- "description": "string",
- "mcpPolicy": {
- "servers": [
- "string"
]
}, - "name": "string"
}
], - "models": [
- "string"
], - "roles": [
- "string"
], - "subject": "github|42",
- "unrestrictedModels": false
}Create a new AIPolicy.
Use metadata.name as the idempotency key. Retrying a POST
with the same name returns 409 Conflict; clients should treat
this as either a duplicate submission (succeeded previously) or
a deliberate collision (surface to the user).
Authorizations:
header Parameters
| X-Request-Id | string Correlation ID; echoed on responses and included in audit records. |
Request Body schema: application/jsonrequired
Full AIPolicy object. metadata.namespace is ignored; the server's configured namespace wins.
Responses
Request samples
- Payload
{ }Response samples
- 201
- 400
- 401
- 403
- 409
- 422
- 429
- 503
{- "apiVersion": "string",
- "kind": "string",
- "metadata": {
- "annotations": {
- "property1": "string",
- "property2": "string"
}, - "creationTimestamp": "2019-08-24T14:15:22Z",
- "deletionGracePeriodSeconds": 0,
- "deletionTimestamp": "2019-08-24T14:15:22Z",
- "generation": 0,
- "labels": {
- "property1": "string",
- "property2": "string"
}, - "name": "main-budget",
- "namespace": "string",
- "resourceVersion": "string",
- "uid": "07cc67f4-45d6-494b-adac-09b5cbc7e2b5"
}, - "spec": {
- "description": "string",
- "gatewayRef": {
- "name": "main"
}, - "mcpPolicy": {
- "servers": [
- "string"
]
}, - "principalMatchers": [
- {
- "claims": {
- "property1": "string",
- "property2": "string"
}
}
]
}, - "status": {
- "appliedToSecurityPolicy": "string",
- "conditions": [
- {
- "lastTransitionTime": "2019-08-24T14:15:22Z",
- "message": "string",
- "observedGeneration": 0,
- "reason": "string",
- "status": "True",
- "type": "string"
}
], - "observedGeneration": 0
}
}Delete an AIPolicy.
If-Match is required; missing returns 428 and stale returns 412, so accidental wipes during a concurrent edit never silently succeed.
Authorizations:
path Parameters
| name required | string Policy name. |
header Parameters
| If-Match required | string Quoted resourceVersion from a preceding GET. Required. |
| X-Request-Id | string Correlation ID; echoed on responses and included in audit records. |
Responses
Response samples
- 401
- 403
- 404
- 412
- 428
- 429
- 503
{- "error": "unauthenticated",
- "requestId": "e7c61d23-0b1a-4d3e-8a0b-18d4f1d7e2c3",
- "violations": [
- {
- "field": "/spec/principalMatchers/0/claims",
- "message": "must contain at least one entry"
}
]
}Get a single AIPolicy by name.
Authorizations:
path Parameters
| name required | string Policy name (DNS-1123 subdomain, max 253 chars). |
header Parameters
| X-Request-Id | string Correlation ID; echoed on responses and included in audit records. |
Responses
Response samples
- 200
- 401
- 403
- 404
- 429
- 503
{- "apiVersion": "string",
- "kind": "string",
- "metadata": {
- "annotations": {
- "property1": "string",
- "property2": "string"
}, - "creationTimestamp": "2019-08-24T14:15:22Z",
- "deletionGracePeriodSeconds": 0,
- "deletionTimestamp": "2019-08-24T14:15:22Z",
- "generation": 0,
- "labels": {
- "property1": "string",
- "property2": "string"
}, - "name": "main-budget",
- "namespace": "string",
- "resourceVersion": "string",
- "uid": "07cc67f4-45d6-494b-adac-09b5cbc7e2b5"
}, - "spec": {
- "description": "string",
- "gatewayRef": {
- "name": "main"
}, - "mcpPolicy": {
- "servers": [
- "string"
]
}, - "principalMatchers": [
- {
- "claims": {
- "property1": "string",
- "property2": "string"
}
}
]
}, - "status": {
- "appliedToSecurityPolicy": "string",
- "conditions": [
- {
- "lastTransitionTime": "2019-08-24T14:15:22Z",
- "message": "string",
- "observedGeneration": 0,
- "reason": "string",
- "status": "True",
- "type": "string"
}
], - "observedGeneration": 0
}
}List AIPolicies in the configured namespace.
Returns a page of AIPolicies. limit caps the underlying
apiserver page size (max 500; larger values are clamped).
pageToken resumes a prior list at the next page boundary.
labelSelector accepts the standard apimachinery selector
syntax (e.g., team=eng,tier!=internal). gatewayRef is a
post-list filter applied to the returned page; when used with
limit, the returned page may contain fewer matches than the
limit — callers must keep paging while nextPageToken is
non-empty to enumerate every match. When labelSelector is
set, the apiserver omits remainingItemCount (per the
Kubernetes API spec: the remaining count is unknown for
selector-filtered lists), so the field will be absent on the
response regardless of how many pages remain. A
present-but-empty value for limit, pageToken, or
labelSelector (e.g., ?limit=) is equivalent to the
parameter being absent and uses the server default for that
parameter — empty is not "explicitly clear this filter".
Authorizations:
query Parameters
| limit | integer Max items per page (1..500). Values above 500 are clamped to 500; 0 or omitted uses the server default (500). |
| pageToken | string Opaque continue token from a previous response. An expired or malformed token returns 400; restart the list from page one. |
| labelSelector | string Kubernetes label selector (e.g., team=eng,tier!=internal). Malformed selectors return 400. |
| gatewayRef | string Restrict to policies targeting this AIGateway name. Applied as a post-list filter; may reduce the returned page size below limit. |
header Parameters
| X-Request-Id | string Correlation ID; echoed on responses and included in audit records. |
Responses
Response samples
- 200
- 400
- 401
- 403
- 429
- 503
{- "apiVersion": "string",
- "items": [
- {
- "apiVersion": "string",
- "kind": "string",
- "metadata": {
- "annotations": {
- "property1": "string",
- "property2": "string"
}, - "creationTimestamp": "2019-08-24T14:15:22Z",
- "deletionGracePeriodSeconds": 0,
- "deletionTimestamp": "2019-08-24T14:15:22Z",
- "generation": 0,
- "labels": {
- "property1": "string",
- "property2": "string"
}, - "name": "main-budget",
- "namespace": "string",
- "resourceVersion": "string",
- "uid": "07cc67f4-45d6-494b-adac-09b5cbc7e2b5"
}, - "spec": {
- "description": "string",
- "gatewayRef": {
- "name": "main"
}, - "mcpPolicy": {
- "servers": [
- "string"
]
}, - "principalMatchers": [
- {
- "claims": {
- "property1": "string",
- "property2": "string"
}
}
]
}, - "status": {
- "appliedToSecurityPolicy": "string",
- "conditions": [
- {
- "lastTransitionTime": "2019-08-24T14:15:22Z",
- "message": "string",
- "observedGeneration": 0,
- "reason": "string",
- "status": "True",
- "type": "string"
}
], - "observedGeneration": 0
}
}
], - "kind": "string",
- "nextPageToken": "string",
- "remainingItemCount": 0
}Update an AIPolicy using JSON merge patch.
Patches are applied against spec only; any status or
metadata.resourceVersion sent in the body is ignored (use
If-Match for optimistic concurrency). spec.gatewayRef is
immutable after creation; attempting to modify it returns 422.
Authorizations:
path Parameters
| name required | string Policy name. |
header Parameters
| If-Match required | string Quoted resourceVersion from a preceding GET. Required: missing returns 428 Precondition Required; stale returns 412 Precondition Failed. |
| X-Request-Id | string Correlation ID; echoed on responses and included in audit records. |
Request Body schema: required
RFC 7396 JSON merge patch; only /spec may be patched.
object (AIPolicySpecPatch) | |||||||
| |||||||
Responses
Request samples
- Payload
{- "spec": {
- "description": "string",
- "mcpPolicy": {
- "servers": [
- "string"
]
}, - "principalMatchers": [
- {
- "claims": {
- "property1": "string",
- "property2": "string"
}
}
]
}
}Response samples
- 200
- 400
- 401
- 403
- 404
- 412
- 422
- 428
- 429
- 503
{- "apiVersion": "string",
- "kind": "string",
- "metadata": {
- "annotations": {
- "property1": "string",
- "property2": "string"
}, - "creationTimestamp": "2019-08-24T14:15:22Z",
- "deletionGracePeriodSeconds": 0,
- "deletionTimestamp": "2019-08-24T14:15:22Z",
- "generation": 0,
- "labels": {
- "property1": "string",
- "property2": "string"
}, - "name": "main-budget",
- "namespace": "string",
- "resourceVersion": "string",
- "uid": "07cc67f4-45d6-494b-adac-09b5cbc7e2b5"
}, - "spec": {
- "description": "string",
- "gatewayRef": {
- "name": "main"
}, - "mcpPolicy": {
- "servers": [
- "string"
]
}, - "principalMatchers": [
- {
- "claims": {
- "property1": "string",
- "property2": "string"
}
}
]
}, - "status": {
- "appliedToSecurityPolicy": "string",
- "conditions": [
- {
- "lastTransitionTime": "2019-08-24T14:15:22Z",
- "message": "string",
- "observedGeneration": 0,
- "reason": "string",
- "status": "True",
- "type": "string"
}
], - "observedGeneration": 0
}
}