Chat completions (streaming + non-streaming, with reasoning)
OpenAI-compatible chat completions over an upstream provider chosen by `model`. Set `"stream": true` for SSE; otherwise the response is a single JSON body. ### Reasoning Opt into model thinking with top-level `reasoning_effort` (`minimal | low | medium | high | xhigh | max`). Allowed values are per-model — query `/v1/models` for `reasoning_levels`. Reasoning is **streaming-only**: non-streaming responses drop it entirely. Streaming reasoning surfaces two channels per `delta`: - `reasoning_content` — display text for live UI (DeepSeek-style extension; concatenate across chunks like `content`). - `reasoning_meta` — structured snapshot at block close, carrying the `signature` (Anthropic) or `encrypted_content` (OpenAI) clients need to replay reasoning on subsequent turns. ### Multi-turn replay Persist `reasoning_meta` between turns and send it back as a `{"type": "reasoning", ...}` block on the assistant message — before text and tool calls (Anthropic enforces this order). Required on Anthropic for tool-using turns (the API 400s without the matching thinking block); recommended on OpenAI so the model doesn't re-derive its plan and re-bill reasoning tokens. OpenAI's Responses API requires `id` on every replayed reasoning block — the gateway 400s pre-flight if missing. Anthropic ignores `id` (signatures live per-block instead). Signatures and encrypted blobs are **model-bound**: persist `model` alongside the reasoning meta and refuse to replay across models. See `docs/llm-gateway/REASONING.md` for the full contract, JSONL persistence shape, and end-to-end curl examples.
/v1/chat/completionsOpenAI-compatible chat completions over an upstream provider chosen by model. Set "stream": true for SSE; otherwise the response is a single JSON body.
Reasoning
Opt into model thinking with top-level reasoning_effort (minimal | low | medium | high | xhigh | max). Allowed values are per-model — query /v1/models for reasoning_levels. Reasoning is streaming-only: non-streaming responses drop it entirely.
Streaming reasoning surfaces two channels per delta:
reasoning_content— display text for live UI (DeepSeek-style extension; concatenate across chunks likecontent).reasoning_meta— structured snapshot at block close, carrying thesignature(Anthropic) orencrypted_content(OpenAI) clients need to replay reasoning on subsequent turns.
Multi-turn replay
Persist reasoning_meta between turns and send it back as a {"type": "reasoning", ...} block on the assistant message — before text and tool calls (Anthropic enforces this order). Required on Anthropic for tool-using turns (the API 400s without the matching thinking block); recommended on OpenAI so the model doesn't re-derive its plan and re-bill reasoning tokens.
OpenAI's Responses API requires id on every replayed reasoning block — the gateway 400s pre-flight if missing. Anthropic ignores id (signatures live per-block instead).
Signatures and encrypted blobs are model-bound: persist model alongside the reasoning meta and refuse to replay across models.
See docs/llm-gateway/REASONING.md for the full contract, JSONL persistence shape, and end-to-end curl examples.
Authorization
bearerAuth In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
OpenAI-compatible chat completions request.
model picks the upstream provider (see /v1/models). Set
"stream": true to receive text/event-stream of ChatChunk deltas
instead of a single ChatResponse body. Tool-calling and reasoning are
both streaming-only in v1.
Response Body
application/json
application/json
application/json
curl -X POST "https://example.com/v1/chat/completions" \ -H "Content-Type: application/json" \ -d '{ "messages": [ { "role": "user" } ], "model": "gpt-5.5", "stop": {} }'{ "choices": [ { "finish_reason": "stop", "index": 0, "message": { "content": "string", "role": "assistant" } } ], "created": 0, "id": "string", "model": "gpt-5.5", "object": "chat.completion", "usage": { "cache_creation_input_tokens": 0, "cache_read_input_tokens": 0, "completion_tokens": 0, "prompt_tokens": 0, "total_tokens": 0 }}{ "error": { "message": "model not supported: foo", "type": "invalid_request_error" }}{ "error": { "message": "model not supported: foo", "type": "invalid_request_error" }}{ "error": { "message": "model not supported: foo", "type": "invalid_request_error" }}Overview
Previous Page
AI SDK UI Message Stream chat (streaming-only) POST
Vercel AI SDK–native chat endpoint, parallel to `/v1/chat/completions`. Accepts a `UIMessage[]` body and streams the AI SDK **UI Message Stream** protocol (typed `data: {"type":…}` chunks under `x-vercel-ai-ui-message-stream: v1`, terminated by `data: [DONE]`). Point `useChat` / `DefaultChatTransport` at it. Streaming-only: `stream: false` returns 400. Top-level fields (`model`, `reasoning_effort`, `tools`, `tool_choice`, `stop`, `temperature`, `top_p`, `max_tokens`, `stream_options`) are identical to `/v1/chat/completions`; only `messages` takes the AI SDK shape. **Client-side tools only** in v1 — the gateway emits `tool-input-*` (the model's call); clients execute tools and replay results as `tool-<name>` parts with `state: "output-available"`. Reasoning replays via `reasoning` parts; `providerMetadata` round-trips the replay payload. See `docs/llm-gateway/AISDK.md` for the chunk union and multi-turn replay contract.