Gateway API (/v1/messages)
The governed inference gateway: the /v1/messages contract, the required x-session-id header, model allow-listing, and the three profile API URLs.
On this page
TL;DR: the gateway exposes POST /v1/messages — an Anthropic-Messages-compatible
endpoint that authenticates, authorises, governs, and audits every inference call before
proxying it upstream. Every request must carry an x-session-id header and an
Authorization (or x-api-key) credential. The model named in the body must be
permitted by the gateway policy allow-list, or the gateway returns 403 before any
upstream call is made.
Request contract
POST /v1/messages
Required headers:
| Header | Purpose | Missing → |
|---|---|---|
Authorization: Bearer <jwt> or x-api-key: <key> |
Caller identity | 401 Unauthorized |
x-session-id: <session id> |
Binds the call to a session for audit and conversation continuity | 400 Bad Request ("missing required x-session-id header") |
x-gateway-conversation-id: <id> (optional) |
Pins the conversation; otherwise it is derived from the message body | — |
Body: the Anthropic Messages shape — model, max_tokens, messages[].
The x-session-id header is mandatory. A request without it is rejected with
400, not a clearer error — supply a session id minted by the session-login flow.
Model allow-listing
The profile's provider registry (profile.providers, e.g. in
.systemprompt/profiles/local/profile.yaml) declares every provider and the
models it serves; those model ids are the deployment's allow-list. A request
whose model is neither declared in the registry nor matched by a gateway route
(or absorbed by gateway.default_provider) is denied with 403 before any
upstream call — this is the egress control an air-gapped deployment relies on.
Both the dispatch gate (GatewayConfig::is_model_exposed) and the /profile
model list derive from the registry, so adding a model means editing the
providers block.
Gateway-route RBAC additionally keys on the route id. If the caller's role or
department is not assigned to the route (and the route is not default_included), the
gateway returns 403 with a message that names the route id, the model, and the
remedy.
Profile API URLs
A profile declares three server URLs; pick the right one for the caller:
| Field | Use it for |
|---|---|
api_internal_url |
Service-to-service calls inside the deployment network |
api_server_url |
The address the server binds / in-container CLI calls |
api_external_url |
The public, host-facing address; used for OAuth/WebAuthn URL generation and consumed by session login |
When the host-published port differs from the in-container port (as in the air-gap
stack), an in-container caller must use the in-container address and host callers must
use the published one — a single value cannot satisfy both. The air-gap profile pins
all three to the in-container :8080 and automated host callers pass the published
port explicitly.