Management API

The gateway's scoped management API -- key lifecycle, spend against the governing policy, and the routable model catalog.

Management API

Alongside the inference surface, the gateway serves a small, fully-typed management API for key lifecycle, usage and model discovery. It is mounted under /api/v1/ on the main listener, authenticated with a management-kind issued key (a runtime key is refused with a 403), and each operation declares the scope it requires.

The management API is dormant unless you enable it. On a self-hosted gateway it requires MGMT_API_ENABLED=true, a configured AUTH_TOKEN, and issued-key handling switched on (GOVERNANCE_ISSUED_KEYS=true). See Self-hosting.

Authentication and scopes

One credential type covers inference and management. Scopes are a property of the issued key, set when the key is created:

ScopeGrants
keys:readListing and retrieving runtime keys.
keys:writeCreating, updating and revoking runtime keys.
usage:readReading spend against the governing policy.
models:readReading the routable model catalog.

A key issued with no scopes holds all four. Scope a management key deliberately if you want it narrow.

Keys

OperationRouteScope
List runtime keysGET /api/v1/keyskeys:read
Create a runtime keyPOST /api/v1/keyskeys:write
Retrieve a runtime keyGET /api/v1/keys/{key_id}keys:read
Update a runtime keyPATCH /api/v1/keys/{key_id}keys:write
Revoke a runtime keyDELETE /api/v1/keys/{key_id}keys:write

Listing takes offset and limit query parameters and returns next_offset.

A key resource carries id, name, kind, disabled, expires_at, last_used_at, created_at, updated_at and policy_id.

Creation returns the plaintext token exactly once. POST /api/v1/keys responds 201 with the key resource plus a key field holding the token. There is no later route that will hand it to you again.

Creating a key requires a name, and optionally takes expires_at and policy_id. A PATCH is a partial update -- absent fields are left unchanged -- and may set name, disabled, expires_at or policy_id -- but metadata fields and policy_id cannot be combined in one request, and an empty patch is a 400. Business validation (name rules, whether the policy exists, the issued-key governing-policy invariant) is the control plane's; the route shape is only the transport.

Usage

OperationRouteScope
A key's spend against its governing policyGET /api/v1/keys/{key_id}/usageusage:read
Any principal's spend -- an issued key, a linked identity, or the unattributed bucketGET /api/v1/usage?principal_kind=&principal_ref=usage:read

The response reports the governing policy, whether it is active, the counter scope and whether it is pooled, the limit, the window, the spend in the current bucket, the principal's spend and whether that figure is complete, and the remaining allowance -- all in micro-USD where they are money.

Every value that does not apply, or is not yet known, is a literal JSON null -- never a zero. A 0 in this response would read as "spent nothing", which is a different and much more reassuring claim than "we do not know".

Models

OperationRouteScope
The routable model catalogGET /api/v1/modelsmodels:read

Paged with page_token / next_page_token. Each model carries its author/slug id, the provider, input, output and cache-read prices, the context window, and benchmark scores where they are published (mmlu, human_eval, mt_bench, avg_score).

Prices are objects with a currency code, units and nanos. A price that is not published is null rather than zero: an unpublished component is not a free one.

Contract versioning

The published contract carries its own semver clock, bumped in the same change as any enforced difference -- routes, override fields, refused fields, headers, or management scopes. Loosening or adding is a minor version; tightening is a major, and is intended to be close to never.

The contract is also held against the implementation by a parity test asserting five equivalences: the routes match the keyed allowlist, the override schema matches the decoder, the refused-field schemas match the refused-field list, the header parameters match the read-and-strip list, and the management operations and scopes match the management router. If those disagree, the contract is what moves.

On this page