Chat completions passthrough | Respan Docs
POST /api/{provider}/v1/chat/completions
Relays a provider’s own chat-completions payload and returns that provider’s own response, byte for byte. Respan authenticates the request, applies your limits and budgets, and writes the log row. It does not rewrite the request or recompute usage.
Use this when correctness matters more than portability: agent frameworks pinned to one provider’s exact semantics, tuned tool-calling behavior, or any payload where a translation layer is a liability. For one request shape across many providers, use the unified router at POST /api/chat/completions instead. That endpoint normalizes; this one does not.
{provider} is the provider id (for example openai, xai, groq). Authorization carries your Respan key, not the provider’s.
Grok is the same call with a different path segment:
With the OpenAI SDK, repoint base_url and pass your Respan key. Nothing else changes:
What is guaranteed
| Aspect | Behavior |
|---|---|
| Request body | Forwarded unchanged. Unknown fields, new provider fields, and provider-only extensions all survive. Only respan_params is removed. |
| Usage | The provider’s own numbers, including cached-token and provider-specific fields. Never recomputed or estimated. |
| Invalid requests | Stay invalid. store: false with metadata fails exactly as it fails calling the provider directly, rather than being normalized into a success. |
| Response body | The provider’s bytes, preserving key order and formatting. Streaming is relayed frame by frame. |
Headers
Forwarded upstream: accept, accept-language, content-type, user-agent, plus that provider’s x-{provider}-* extension headers. Everything else (cookies, Respan’s own headers) is dropped, so nothing leaks to the provider.
Returned to you:
| Header | Meaning |
|---|---|
X-Respan-Log-Id |
Respan log id for this request |
X-Respan-Upstream-Request-Id |
The provider’s own request id, for correlating with their support |
x-ratelimit-* |
The provider’s rate-limit headers, relayed |
retry-after |
Relayed when the provider sends it |
Errors and limits
Provider errors pass through with the provider’s status code and body, so your existing error handling keeps working. Respan’s own errors:
| Status | Meaning |
|---|---|
401 |
No usable credentials for the provider |
404 |
Provider is not available as an OpenAI-shaped passthrough |
429 |
Your Respan key’s rate limit |
Respan imposes no request-body size, context-length, or truncation limit below the provider’s own, and never silently truncates. If a provider limit is exceeded, the provider’s error is returned. The request timeout is 600s so long reasoning calls complete.
Supported providers
azure_deepseek, azure_openai, baseten, cerebras, chutes, deepseek, empiriolabs, featherless, fireworks, friendliai, gonka24, groq, inceptron, inference_net, ionet, makora, minimax, mistral, moonshot, morphllm, nebius, nextbit256, novita, openai, openai_compatible, openrouter, parasail, perplexity, qwen, tera, togetherai, wafer, xai, zai
Providers whose API is not OpenAI-shaped (Anthropic, Google, Bedrock, Cohere) have their own native passthrough endpoints. See Routing & passthrough.
OpenRouter
OpenRouter has its own path and uses your OpenRouter key rather than an org integration:
Authorization is your Respan key; x-openrouter-api-key is your OpenRouter key. A missing OpenRouter key returns 400. OpenRouter’s attribution headers http-referer and x-title are forwarded so your app still appears on their rankings.