POST /v1/chat/completions¶
The single client-facing LLM endpoint. OpenAI Chat Completions-compatible.
Request¶
Headers¶
| Header | Required | Notes |
|---|---|---|
Authorization |
yes | Bearer <SMART_GATEWAY_API_KEY> |
Content-Type |
yes | application/json |
X-Smart-Gateway-Session |
recommended | Stable session ID. |
X-Smart-Gateway-Goal |
recommended | Goal ID inside the session. |
X-Task-Id |
optional | Per-request task ID. |
X-Goal-Id |
optional | Per-request goal ID. |
X-Pro |
optional | Force Pro routing. |
X-Scout |
optional | true to invoke Scout first. |
X-Failure-Class |
optional | STRUCTURAL, LOCAL, or NONE. |
X-Same-Error-Count |
optional | Integer. |
Body¶
{
"model": "smart-router",
"messages": [
{"role": "user", "content": "Reply with the word PONG."}
],
"temperature": 0.2,
"top_p": 1.0,
"max_tokens": 8,
"stream": false,
"metadata": {
"sensitive": true,
"session_id": "proj-A-2026-08-23",
"goal_id": "fix-flaky",
"task_id": "task-17"
}
}
Field summary:
| Field | Type | Notes |
|---|---|---|
model |
string | One of smart-router, smart-router-flash, smart-router-pro, smart-router-free. |
messages |
array | OpenAI chat completion messages. |
stream |
bool | SSE if true. |
temperature |
number | Optional. |
top_p |
number | Optional. |
max_tokens |
integer | Optional. |
stop |
string or array | Optional. |
tools |
array | OpenAI function-calling tool definitions. Forwarded unchanged. |
tool_choice |
string or object | Forwarded unchanged. |
response_format |
object | Forwarded unchanged. JSON-mode works. |
metadata |
object | Gateway-specific routing metadata. |
user |
string | Optional. Forwarded. |
The gateway also accepts any other OpenAI Chat Completions field and forwards it unchanged. Unknown fields are passed through; the gateway does not validate them. OpenRouter will reject unsupported fields with 400.
metadata¶
| Key | Type | Default | Effect |
|---|---|---|---|
sensitive |
bool | true |
Required to be false for free models on non-private work. |
reasoning |
string | auto |
high forces Pro (unless blocked by budget soft cap). |
routing |
string | auto |
Hint, not a control. pro/flash/free honored if compatible with privacy. |
session_id |
string | — | Equivalent to X-Smart-Gateway-Session. |
goal_id |
string | — | Equivalent to X-Smart-Gateway-Goal. |
task_id |
string | — | Equivalent to X-Task-Id. |
repo_id |
string | — | Optional, used for logging. |
Response (non-streaming)¶
{
"id": "gen-1787490793-…",
"object": "chat.completion",
"created": 1755000000,
"model": "deepseek/deepseek-v4-flash-0731",
"choices": [
{
"index": 0,
"message": {"role": "assistant", "content": "PONG"},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 17,
"completion_tokens": 1,
"total_tokens": 18
}
}
The model field echoes the real OpenRouter ID, not the alias
you sent. The id is the OpenRouter completion ID (gen-…).
If the upstream payload contains reasoning in message.reasoning
and message.content is null, the gateway copies the reasoning text
into message.content so that OpenAI-compatible clients see a
non-empty answer (_normalize_extended_thinking_response).
Response (streaming)¶
Content-Type: text/event-stream. Each event is a chat.completion.chunk
in OpenAI's standard SSE shape. The terminal event is
data: [DONE].
See User guide → Streaming for the exact chunk format, the reasoning-delta normalizer, and known caveats.
Status codes¶
| Status | When |
|---|---|
200 |
Successful completion (or successful stream). |
400 |
Body is not valid JSON, or contains an unsupported shape (e.g. multimodal image content). |
401 |
Missing or malformed Authorization. |
403 |
Privacy gate (A force-free request that violates privacy policy must fail closed.), Scout on sensitive (Scout cannot be called on sensitive data.), or STOP_FOR_HUMAN for non-ROUTE/SCOUT decisions. |
422 |
Pydantic validation error (e.g. negative max_tokens). |
500 |
OpenRouter returned a non-retryable 4xx, or all retries exhausted. |
502 / 503 / 504 |
Transport error after exhausting retries. |
The error body for 4xx/5xx is {"detail": "<message>"}.
Examples¶
Minimal¶
curl -sS "$BASE/v1/chat/completions" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"model":"smart-router-flash","messages":[{"role":"user","content":"PONG"}],"max_tokens":4}'
With streaming¶
curl -sN "$BASE/v1/chat/completions" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"model":"smart-router-flash","stream":true,"messages":[{"role":"user","content":"hi"}],"max_tokens":64}'
Tool calls¶
curl -sS "$BASE/v1/chat/completions" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{
"model":"smart-router",
"messages":[{"role":"user","content":"Weather in Tokyo?"}],
"tools":[{
"type":"function",
"function":{
"name":"get_weather",
"description":"Get current weather",
"parameters":{"type":"object","properties":{"city":{"type":"string"}},"required":["city"]}
}
}],
"tool_choice":"auto"
}'
Force Pro¶
curl -sS "$BASE/v1/chat/completions" \
-H "Authorization: Bearer $KEY" \
-H "X-Pro: true" \
-H "Content-Type: application/json" \
-d '{"model":"smart-router","messages":[{"role":"user","content":"[reasoning:high] design a semaphore"}],"max_tokens":500}'
See also¶
- API reference → Errors for the full error matrix.
- API reference → Overview.