# Router One API Compatibility Facts

Last updated: 2026-09-11

- Product: Router One
- Category: LLM API Gateway / AI Model Router
- Scope: which wire formats and request features the gateway accepts on each endpoint, and what it rejects before calling any model; per-model capability flags live in the catalog, not here
- OpenAI-compatible base URL: https://api.router.one/v1
- Anthropic-compatible / Claude Code base URL: https://api.router.one
- API key format: sk-rk-...; send it as Authorization: Bearer on every endpoint below — the x-api-key header the Anthropic SDK sends for api_key is accepted as an equivalent (Claude Code sends Bearer through ANTHROPIC_AUTH_TOKEN)

## Endpoints

- POST https://api.router.one/v1/chat/completions: OpenAI Chat Completions wire format; serves every chat model in the catalog
- POST https://api.router.one/v1/messages: Anthropic Messages wire format (the path Claude Code uses); serves the currently listed Claude-family models and DeepSeek ids (deepseek-v4.1-flash and deepseek-v4-flash, listed 2026-09-10)
- POST https://api.router.one/v1/responses: OpenAI Responses wire format (the path Codex CLI uses); served natively for the currently listed GPT-family models and DeepSeek ids — the authoritative list is the set of models whose detail page lists POST /v1/responses
- POST https://api.router.one/v1/images/generations: image-generation models (flat per-image pricing; see the pricing facts)
- POST https://api.router.one/v1/images/edits: image-to-image editing for the image models whose catalog entry lists image among its input modalities; the request is multipart/form-data because the reference images are uploaded as files (repeat the image field for more than one; 25 MB per file), and the response shape and flat per-image pricing match image generation
- POST https://api.router.one/v1/videos/generations and GET https://api.router.one/v1/videos/generations/{task_id}: video-generation models; submit, then poll the task id — clip length and resolution are fixed per model, not chosen per request
- Endpoint rule: each model's detail page linked from https://router.one/models lists exactly the endpoints that model serves; https://router.one/models.md is the machine-readable source of truth and overrides any family shorthand above
- No cross-protocol promise: a model is reachable only on the endpoints its detail page lists; Router One does not advertise a translation path from one wire format to another
- Wrong-endpoint rejection: a model ID sent to an endpoint that does not serve it is rejected with HTTP 400 invalid_request_error before any model is called, and the message names the path to use ("model '<id>' must be called via ...")

## Responses API (POST /v1/responses)

- Accepted on every model the endpoint serves: text and multi-part input, instructions, streaming, and function tools
- Accepted on natively served Responses models (currently listed GPT-family models and DeepSeek ids) and billed at the model's standard token rate: custom tools; previous_response_id, conversation, and prompt references; hosted tools (file_search, code_interpreter, computer_use, mcp, web_search); file_id and file_url input parts; every service_tier value
- Hosted-tool boundary: hosted tool fields are accepted on the endpoint and metered — Router One does not execute tools itself (see the trust boundary below)
- Rejected with HTTP 400 invalid_request_error before any model is called: the image_generation tool and image_generation_call input items (use POST /v1/images/generations instead), and background: true
- Also rejected with HTTP 400 invalid_request_error before any model is called: a Claude-family model ID, which this endpoint does not serve ("model '<id>' must be called via /v1/messages or /v1/chat/completions")

## Messages API (POST /v1/messages)

- Accepted on every model the endpoint serves (currently listed Claude-family models and DeepSeek ids): text and multi-part input, streaming, and the client-side tool definitions Claude Code sends (tools with input_schema, tool_choice; tool_use / tool_result blocks round-trip)
- Anthropic server tools accepted and metered at the model's standard token rate: web_search, and code_execution including its bash and text-editor sub-tools and container reuse across turns — Router One does not execute tools itself (see the trust boundary below)
- Rejected with HTTP 400 invalid_request_error before any model is called: the web_fetch server tool, mcp_toolset, and the mcp_servers field (MCP connector)
- Error bodies use the Anthropic envelope {"type":"error","error":{type,message,code},"request_id"}
- Request headers: the anthropic-beta header is passed through as sent, and none of the accepted server tools requires it; a rejected server tool or MCP field returns the 400 above with a message that names the rejected feature

## Hosted search on Chat Completions (google/gemini-3-flash)

- Scope: the google/gemini-3-flash id only, on POST /v1/chat/completions; no other id gets this treatment — on every other id the tools array is forwarded as sent, and a hosted-search tool type the model does not accept is rejected by that model's route
- Request: tools: [{"type": "google_search"}] with tool_choice: "auto" (the model decides whether to search), or web_search_options: {}; tool_choice: "none" turns the search off; streaming and non-streaming both work, and stream_options: {"include_usage": true} is honoured
- Response: the sources the model grounded on come back as OpenAI-style url_citation annotations — choices[0].message.annotations on a non-streaming reply, choices[0].delta.annotations on a stream; duplicate and invalid URLs are dropped, and no source HTML is injected into the answer
- Billing: at the model's posted token rates — the search context counts as input tokens and the model's reasoning as output tokens; there is no separate search line and no promise that every tool_choice: "auto" request performs a search
- Rolled out 2026-09-09; the tool-calling guide (https://router.one/llm-tool-calling) and the Gemini access page (https://router.one/gemini-api-china) carry the request example

## Streaming, tool calling, vision

- Streaming (stream: true), tool calling, and vision input are per-model capability flags published in the catalog; https://router.one/models.md is the source of truth and this sheet does not hand-enumerate models
- Streaming guide: https://router.one/llm-streaming; tool-calling guide: https://router.one/llm-tool-calling

## Structured outputs (POST /v1/chat/completions)

- response_format.type = json_object and response_format.type = json_schema are both accepted
- Envelope validation happens at the gateway, before any model is called: a json_schema request is rejected with HTTP 400 invalid_request_error when response_format.json_schema is missing ("response_format.json_schema is required when response_format.type is json_schema"), when json_schema.name is missing ("response_format.json_schema.name is required"), or when json_schema.schema is missing ("response_format.json_schema.schema is required"); strict and description are optional
- A valid response_format object is forwarded to the model unchanged; whether the schema is enforced is decided by the model, when the model supports it — Router One does not validate response bodies against the schema
- Schema-dialect failover: when a model route rejects a schema for using $defs or $ref, the gateway treats that as a route-specific 400 and fails over to the next candidate route for the same model
- Guide: https://router.one/llm-structured-outputs

## Thinking on -thinking model ids

- Scope: catalog ids that end in -thinking — currently anthropic/claude-opus-4.6-thinking, anthropic/claude-opus-4.7-thinking and anthropic/claude-sonnet-4.6-thinking; https://router.one/models.md is the source of truth for which ids carry the suffix
- Default: a request to such an id that carries no thinking field is sent to the model with thinking enabled — when the gateway has to add the field itself it uses thinking: {"type": "adaptive"} (the model decides how much to think) — so callers get thinking output without adding the field; the rule keys off the -thinking suffix and adds nothing to ids without it (anthropic/claude-opus-4.6, anthropic/claude-sonnet-4.6, etc.)
- Explicit values are respected: the gateway never adds a thinking setting to a request that already carries one, and {"type": "disabled"} is forwarded as sent. On the Opus 4.7-generation ids (today anthropic/claude-opus-4.7-thinking), which accept only adaptive thinking, a legacy {"type": "enabled", "budget_tokens": N} value is translated to {"type": "adaptive"} and temperature / top_p / top_k are dropped before the call; on the other -thinking ids the value is forwarded as sent, and whether the model accepts it is decided by the model
- Same rule on both endpoints: on POST /v1/messages it applies to the Anthropic request body as sent, streaming or not; on POST /v1/chat/completions it applies to the top-level thinking field of the JSON body, which takes the same object shape; the OpenAI-style reasoning_effort field is not translated into a thinking setting for Claude-family ids
- Output: thinking blocks the model returns are passed through as thinking content blocks on POST /v1/messages and surfaced in the message's reasoning_content field on POST /v1/chat/completions; they are billed at the model's output rate (see Token accounting below)

## Token accounting

- Reasoning / thinking tokens: output produced by thinking or reasoning models (for example the claude-*-thinking variants) is billed at that model's posted output rate and counted in the request's total token count; there is no separate reasoning price line (see the pricing facts)
- Empty-but-metered replies: a reply that carries no content, no tool calls and no refusal but reports non-zero usage is returned as HTTP 200 exactly as it came back, and settlement follows the usage the response reports — it is not retried and not failed over, so clients should read finish_reason, refusal and usage instead of retrying automatically; a reply that reports no usage at all is treated as an upstream failure (HTTP 502, next candidate tried)

## Not included

- Gateway-side response caching or any wire-format conversion beyond the endpoint rows above. The direct API retention policy and saved Playground history are described at https://router.one/data-retention
- Trust boundary: Router One handles model invocation, routing, billing, and observability; it is not an agent orchestration runtime, workflow engine, tool executor, vector database, or application framework

## Canonical pages

- OpenAI-compatible API: https://router.one/openai-compatible-api
- Codex CLI and the Responses API: https://router.one/codex-responses-api
- Tool calling: https://router.one/llm-tool-calling
- Streaming: https://router.one/llm-streaming
- Structured outputs: https://router.one/llm-structured-outputs
- Documentation: https://router.one/docs (markdown: https://router.one/docs.md)
- Model catalog: https://router.one/models (markdown: https://router.one/models.md)
- Integration facts: https://router.one/facts/integrations.md
- Pricing facts: https://router.one/facts/pricing.md
- Company facts: https://router.one/facts/company.md
