Skip to content

Gateway API

Provon exposes an OpenAI-compatible inference API plus project-scoped discovery and Provider Key management endpoints. The configured runtime is the source of truth for endpoint and feature availability.

View as Markdown Open the plain-text version of this page.

Base URLs#

For hosted Provon:

Route group Base URL
Gateway inference https://gateway.provon.dev/v1
Gateway control API https://api.provon.dev/v1/gateway
Workbench https://app.provon.dev

For the local Node runtime:

Route group Base URL
Explicit Gateway inference http://127.0.0.1:3000/gateway/v1
OpenAI-compatible aliases http://127.0.0.1:3000/v1
Gateway control API http://127.0.0.1:3000/v1/gateway

Use the Gateway URL as the SDK base URL for model traffic. Use the API URL for discovery, Provider Key management, and other management routes. In a one-origin self-hosted deployment, /gateway/v1 keeps model traffic distinct from Provon's management API and OTLP routes.

bash
export PROVON_GATEWAY_URL="https://gateway.provon.dev/v1"
export PROVON_API_URL="https://api.provon.dev/v1"

Authentication#

Send a Provon project API key as a Bearer token:

http
Authorization: Bearer <PROVON_API_KEY>

Relevant API-key capabilities:

Capability Grants
gateway:invoke Model inference through the Gateway /v1/* routes or local /gateway/v1/*
workspace:read Provider catalog, capability matrix, model selection, and Provider Key reads
gateway:manage Provider Key and model-binding writes

Workbench sessions use project permissions instead of these API-key capabilities.

Provider credentials are not valid Gateway client credentials. They remain attached to project-scoped Provider Keys.

First Request#

bash
curl "$PROVON_GATEWAY_URL/chat/completions" \
  -H "Authorization: Bearer $PROVON_API_KEY" \
  -H "Content-Type: application/json" \
  -H "x-otel-gen-ai-conversation-id: conversation-123" \
  -d '{
    "model": "openai/gpt-5-mini",
    "messages": [{"role": "user", "content": "Hello"}]
  }'

The request and response follow the selected Gateway endpoint shape. Provider adapters may translate that shape to a native upstream protocol and translate the result back.

Model Values#

Shape Example Behavior
Provider-qualified openai/gpt-5-mini Pins provider resolution to openai
Plain model gpt-5-mini Applies a matching Model Policy, then registry inference
Auto Router provon/auto Selects an eligible mapped Provider Key model when enabled

Provider-qualified values are the safest integration default because provider intent is explicit. Plain names are useful when the project owns a stable logical model name. provon/auto is useful when target selection should consider request fit, health, latency, and estimated cost.

See Routing and reliability.

Request Context#

Gateway context headers become OpenTelemetry attributes on the root and attempt spans. They do not change provider routing unless a separately configured policy uses the same value.

Header Trace attribute
x-otel-gen-ai-conversation-id gen_ai.conversation.id
x-otel-user-id user.id
x-otel-user-hash user.hash
x-otel-user-name user.name
x-otel-user-full-name user.full_name
x-otel-user-email user.email
x-otel-session-id session.id
x-otel-gen-ai-agent-id gen_ai.agent.id
x-otel-gen-ai-agent-name gen_ai.agent.name
x-otel-gen-ai-agent-version gen_ai.agent.version
x-otel-gen-ai-workflow-name gen_ai.workflow.name

Values are trimmed and limited to 512 characters. Use stable pseudonymous user IDs when raw identity is not required. Never send secrets in context headers.

Every header above is caller context: it says who is calling, not what the inference call did. Caller context is recorded on every span of the request — the synthesized trace root, the SERVER span for the request, and the outbound CLIENT span — so a span can always be traced back to the conversation, agent, workflow and user it belongs to. Some of these attributes are named gen_ai.* because that is what the OTel GenAI conventions call them; the name is not what decides the role.

What the gateway measures itself — model, token usage, cost, response, message content — is inference telemetry and stays on the outbound CLIENT span, reported as gen_ai.* there and mirrored as gateway.* on the SERVER span.

For multi-turn diagnostics, x-otel-gen-ai-conversation-id is the most important field: it also sets the trace boundary, so every request carrying the same value joins one trace.

Trace Boundary#

trace_id resolves in this order:

  1. x-otel-trace-id — explicit trace boundary.
  2. x-otel-gen-ai-conversation-id — conversation-scoped trace boundary.
  3. the request id — one trace per request (default when neither header is sent).

A trace is a span tree, so a trace covering several requests needs a span that parents them. For the first two cases Gateway synthesizes that root itself, marks it provon.trace.root=true, and parents each request's SERVER span to it, giving one connected tree for the whole conversation. Its span id is derived from the trace id, so a stateless Gateway computes the same value on every request and the repeated writes converge onto a single row. The third case adds no such span, because a single-request trace is already rooted by its own SERVER span.

Endpoint Discovery#

Gateway recognizes these endpoint families (the GatewayProviderEndpoint union):

text
chat-completions      responses             messages
embeddings            rerank
image-generations     image-edits           image-variations
audio-transcriptions  audio-speech          moderations
batches               files                 fine-tuning
vector-stores         realtime              video-extensions
video-edits           videos                classify
pipeline

Recognition does not imply that every provider supports every family. Query the project capability matrix:

bash
curl "$PROVON_API_URL/gateway/capability-matrix?includeDisabled=false" \
  -H "Authorization: Bearer $PROVON_API_KEY"

The response distinguishes:

  • native: the provider exposes the endpoint shape directly;
  • translated: Provon adapts the Gateway shape to a provider-native endpoint;
  • bridged: the public endpoint is implemented through another provider endpoint family;
  • unsupported: the provider cannot serve that endpoint;
  • available or disabled: project Provider Key availability.

Inspect eligible model targets for one endpoint and feature set:

bash
curl \
  "$PROVON_API_URL/gateway/model-selection?endpoint=chat-completions&features=streaming,tool-calling" \
  -H "Authorization: Bearer $PROVON_API_KEY"

Supported feature filters are:

text
streaming              tool-calling          parallel-tool-calls
json-mode              structured-outputs    reasoning
vision-input           audio-input            audio-output
prompt-caching         cache-read             cache-write
reasoning-tokens       usage-metadata         native-passthrough
custom-base-url

List the provider catalog:

bash
curl "$PROVON_API_URL/gateway/providers" \
  -H "Authorization: Bearer $PROVON_API_KEY"

Control API#

Project API keys with workspace:read can inspect Gateway configuration:

Method Path Result
GET /v1/gateway/providers Runtime provider catalog
GET /v1/gateway/capability-matrix Provider and Provider Key capabilities
GET /v1/gateway/model-selection Eligible models for endpoint/features
GET /v1/gateway/provider-keys Project Provider Keys without raw secrets
GET /v1/gateway/provider-keys/:keyId/capabilities One Provider Key and its model mappings

Keys with gateway:manage can write provider targets, credentials, and model mappings:

Method Path Operation
POST /v1/gateway/providers Create a custom project-defined provider target
PATCH /v1/gateway/providers/:keyId Update a custom provider target
DELETE /v1/gateway/providers/:keyId Delete a custom provider target and its stored credentials
POST /v1/gateway/providers/test-connection Validate a custom provider endpoint before saving
POST /v1/gateway/provider-keys Attach a credential to a target and set its model mappings
PATCH /v1/gateway/provider-keys/:keyId Update settings or rotate the stored credential secret
DELETE /v1/gateway/provider-keys/:keyId Remove the credential and its model mappings
POST /v1/gateway/provider-keys/:keyId/capabilities Create or update a model mapping
DELETE /v1/gateway/provider-keys/:keyId/capabilities/:capabilityId Delete a model mapping
PATCH /v1/gateway/provider-keys/:keyId/enabled Enable or disable a target without rotating its secret

Note

Built-in catalog providers are listed by GET /v1/gateway/providers but are not created, patched, or deleted through this API and do not take caller-supplied upstream keys. The write endpoints above provision and manage only custom project-defined providers (providerKind: "custom") together with their credentials and mappings.

Signed-in Workbench routes also expose project-qualified variants under /v1/projects/:projectId/gateway/*. Prefer the unqualified paths for project API-key clients because the project is already derived from the key. Reordering provider target preference (POST /v1/projects/:projectId/gateway/provider-keys/reorder) is project-qualified only.

Custom Providers use a project-scoped provider ID and a static driverId. An exact endpoint URL is never extended with a protocol path:

json
{
  "provider": "internal-kimi",
  "providerKind": "custom",
  "driverId": "openai-compatible",
  "displayName": "Internal Kimi",
  "endpointConfig": {
    "mode": "exact-url",
    "endpointUrls": {
      "chat-completions": "https://models.example/custom/chat"
    },
    "endpointBridges": {
      "responses": "chat-completions"
    }
  },
  "authScheme": { "kind": "bearer" },
  "apiKey": "..."
}

endpointBridges.responses = "chat-completions" exposes /responses for an upstream that only implements Chat Completions. Provon performs stateless request, response, and SSE translation. Omit the bridge and configure a native responses endpoint URL when the upstream implements the Responses API directly.

Common Inference Paths#

Append these operation paths to the Gateway base URL:

Operation Path
Chat Completions /chat/completions
Responses /responses
Messages, including Anthropic native passthrough /messages
Embeddings /embeddings
Rerank /rerank
Image generation /images/generations
Audio transcription /audio/transcriptions
Audio speech /audio/speech
Realtime client secret /realtime/client_secrets
Realtime WebSocket /realtime?model=<provider/model>

This table lists common inference paths. The endpoint-family list above is the capability discovery taxonomy, not a guarantee that every family has a hosted /v1/* alias. Less common or provider-native path forms include /reranking, /realtime/calls, /realtime/transcription_sessions, /videos/*, /classification, and /inference. MCP tool calls are a separate Provon gateway with its own routes, not a Gateway inference path. Use the capability matrix and the selected deployment's Gateway base URL before integrating one of these paths.

Streaming#

For OpenAI-compatible streaming endpoints, send the normal request field:

json
{
  "model": "openai/gpt-5-mini",
  "stream": true,
  "messages": [{ "role": "user", "content": "Write one sentence." }]
}

The candidate target must declare streaming. Provon streams the provider-compatible response while collecting final attempt, usage, guardrail, and trace evidence where available.

Request IDs#

Successful and failed inference responses include x-provon-request-id after request context is established. Log this value with the application request and use it to correlate:

  • the client failure;
  • the Gateway root trace ID;
  • upstream attempt spans;
  • usage-policy and guardrail evidence.

Clients may send x-provon-request-id, but generated IDs are safer unless the caller guarantees uniqueness.

Error Shape#

Gateway-owned errors use a JSON envelope:

json
{
  "error": {
    "code": "GATEWAY_PAUSED",
    "message": "gateway is paused for this project",
    "details": {}
  }
}
Status Code Meaning
401 UNAUTHORIZED Missing or invalid project API key
403 FORBIDDEN Key lacks gateway:invoke or the required control capability
404 UPSTREAM_NOT_CONFIGURED No eligible target for the requested model
409 PROVON_GATEWAY_GUARD_TRIGGERED A configured guardrail blocked the request
413 BODY_TOO_LARGE Request body exceeds the configured Gateway limit
415 UNSUPPORTED_CONTENT_ENCODING Compressed request bodies are rejected
429 rate_limit_exceeded Per-key rate-limit policy rejected the request
429 gateway_budget_exceeded Per-key usage budget policy rejected the request
501 GATEWAY_PROVIDER_KEY_MANAGER_UNAVAILABLE Management not configured in this runtime
503 GATEWAY_PAUSED The project Gateway is paused

Usage-policy rejections return 429 together with Retry-After, RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset headers. Upstream provider errors keep their provider-compatible shape where possible and are classified in the Gateway trace.

Transport Limits#

Runtime defaults are:

  • 4 MiB for JSON request bodies;
  • 8 MiB for other supported request bodies (for example multipart/form-data audio or image uploads);
  • no compressed Gateway request body;
  • a 60-second overall Gateway request deadline;
  • 2 MiB maximum response body capture for telemetry.

These limits apply to the Gateway's dedicated /gateway/v1/* origin. That origin does not sit under the platform-wide /v1/ body middleware (the middleware ignores any path that does not begin with /v1/), so the values above are the effective ones there.

The Gateway also registers OpenAI-compatible /v1/... aliases (for example /v1/chat/completions, /v1/responses, /v1/embeddings, /v1/messages, /v1/realtime, /v1/realtime/client_secrets, and GET /v1/models). Because these alias paths begin with /v1/, they also sit under the platform-wide body middleware and are capped at 1 MiB per request body before reaching the Gateway. For larger payloads (audio, images, long prompts) send them to /gateway/v1/... rather than the /v1/ aliases.

Deployments can override these limits. A provider may impose stricter limits.