Gateway API
Provon exposes an OpenAI-compatible inference surface plus project-scoped discovery and Provider Key management endpoints. The configured runtime is the source of truth for endpoin
Base URLs#
For hosted Provon:
| Surface | 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:
| Surface | 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 control-plane routes. In a one-origin self-hosted deployment,
/gateway/v1 keeps model traffic distinct from Provon's control API and OTLP routes.
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:
Authorization: Bearer <PROVON_API_KEY>Relevant API-key capabilities:
| Capability | Grants |
|---|---|
gateway:invoke |
Model inference through the Gateway /v1/* surface 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#
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.
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:
x-otel-trace-id— explicit trace boundary.x-otel-gen-ai-conversation-id— conversation-scoped trace boundary.- 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:
chat-completions responses messages
embeddings rerank ocr
image-generations image-edits image-variations
audio-transcriptions audio-speech moderations
batches files fine-tuning
vector-stores realtime videos
video-extensions video-edits search
classify pipeline a2a
mcp-toolsRecognition does not imply that every provider supports every family. Query the project capability matrix:
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;availableordisabled: project Provider Key availability.
Inspect eligible model targets for one endpoint and feature set:
curl \
"$PROVON_API_URL/gateway/model-selection?endpoint=chat-completions&features=streaming,tool-calling" \
-H "Authorization: Bearer $PROVON_API_KEY"Supported feature filters are:
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-urlList the provider catalog:
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 Keys and mappings:
| Method | Path | Operation |
|---|---|---|
POST |
/v1/gateway/provider-keys |
Create a Provider Key and optional initial credential |
PATCH |
/v1/gateway/provider-keys/:keyId |
Update target settings or rotate its primary secret |
DELETE |
/v1/gateway/provider-keys/:keyId |
Delete the target, credentials, and 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 |
POST |
/v1/gateway/providers |
Create a built-in or project-defined Provider target |
PATCH |
/v1/gateway/providers/:keyId |
Update a Provider target |
DELETE |
/v1/gateway/providers/:keyId |
Delete a Provider target |
POST |
/v1/gateway/providers/test-connection |
Test a Custom Provider before saving |
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.
Custom Providers use a project-scoped provider ID and a static driverId. An exact endpoint URL
is never extended with a protocol path:
{
"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 paths include alternate forms such as /reranking, /realtime/calls,
/realtime/transcription_sessions, /videos/*, /classification, /inference, /a2a, /mcp,
and /mcp/tools. Use the capability matrix and the selected deployment's Gateway base URL before
integrating one of those paths.
Streaming#
For OpenAI-compatible streaming endpoints, send the normal request field:
{
"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:
{
"error": {
"code": "GATEWAY_PAUSED",
"message": "gateway is paused for this project",
"details": {}
}
}Usage-policy rejections return 429 with Retry-After, RateLimit-Limit,
RateLimit-Remaining, and RateLimit-Reset. Guardrail blocks return 409 with
PROVON_GATEWAY_GUARD_TRIGGERED and guardrail headers.
Provon Cloud managed model requests return 402 with INSUFFICIENT_GATEWAY_CREDITS when the
organization cannot reserve the estimated request cost. A paused project Gateway returns 503
with GATEWAY_PAUSED. Model resolution with no eligible target returns 404 with
UPSTREAM_NOT_CONFIGURED.
Upstream provider errors remain provider-compatible when possible and gain normalized classification in the Gateway trace.
Transport Limits#
Runtime defaults are:
- 4 MiB for JSON request bodies;
- 25 MiB for other supported request bodies;
- no compressed Gateway request body;
- a 60-second overall Gateway request deadline;
- 2 MiB maximum response body capture for telemetry.
Deployments can override these limits. A provider may impose stricter limits.