Skip to content
Skip to content
Router One

FAQ & Troubleshooting

The questions we hear most from developers wiring up the gateway — with the exact place to look when something fails.

Which base URL do I use — with or without /v1?

OpenAI-compatible clients (OpenAI SDK, Chat Completions, Responses, images, videos, Codex CLI) use https://api.router.one/v1 — with /v1. Anthropic-compatible clients (Anthropic SDK, Claude Code) use https://api.router.one — without /v1, because the client appends /v1/messages itself. A 404 right after setup is almost always this.

Quickstart · base URLs →

I get 401 Unauthorized. What should I check?

Three things, in order: the key was copied in full (starts with sk-, no trailing spaces); the request sends it as Authorization: Bearer <key>; and the key still exists and hasn't expired in Dashboard → API Keys. For Claude Code, also check ~/.claude/settings.json — its env block overrides shell environment variables, so an old key there wins over a new export. The mangled header values we see most: Bearer written twice (Bearer Bearer sk-…) because the client adds the scheme and the variable already contains it, quotes pasted into the value, a newline inside the key, or a dashboard session token sent where an API key is expected — a valid key mangled this way is rejected before any lookup.

API Keys →Error codes reference →Claude Code 401 & 403 fixes →

I get 402 Payment Required.

The key is valid, but the wallet balance (or the key's maxSpend) cannot cover the initial reservation this request needs — usually because it is used up; a large input, or funds held by other in-flight requests, can also cause it. Top up with a card or Alipay through one hosted checkout, or with USDT/USDC on six chains (Tron, BSC, Ethereum, Polygon, Base, Arbitrum) — or raise the key's maxSpend.

Dashboard →Pricing →Product & billing FAQ →Error codes reference →

I get 429 Too Many Requests.

No low fixed cap for normal paid usage. Each key and each account runs under default request-per-minute and token-per-minute limits, and upstream constraints may still apply; if a request returns 429, back off and retry (honor Retry-After when it is sent), and if your traffic needs higher limits, email support@router.one to have the key or account limits raised. The code names the limit (RATE_LIMIT_EXCEEDED, TOKEN_QUOTA_EXCEEDED, SUBSCRIPTION_QUOTA_EXCEEDED); a 429 from your key's or account's limits is refused before any model is called, so only a 429 that came back from upstream after the gateway's retries has a row in Logs.

Logs →Error codes reference →

A request came back 200 but the message content is empty.

That is a completed response, not an error, so don't auto-retry it. Models sometimes spend tokens without writing an answer — a system prompt that tells them to stay silent, a reasoning pass that ends without output, or a refusal carried in message.refusal. The reply is passed through as it came back, and settlement follows the usage the response reports, so a retry loop pays for the same silence again. Check finish_reason, refusal and usage on the reply first. A reply that reports no usage at all is the failure case: it is treated as an upstream error and another candidate for the same model is tried.

Logs →Error codes reference →

Claude Code still shows the official login screen (or answers from the wrong account).

That means the gateway env vars aren't visible to Claude Code. The one-click script writes ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN into the env block of ~/.claude/settings.json — verify they're there, then restart Claude Code. If you configured shell exports manually instead, open a new terminal so the exports load, and make sure no old value in settings.json overrides them.

One-click setup →

Codex says the ROUTER_ONE_API_KEY environment variable is missing.

Codex reads your key from the ROUTER_ONE_API_KEY environment variable (declared as env_key in ~/.codex/config.toml). The install script appends the export to your shell profile — run source ~/.zshrc (or your shell's profile) in the current terminal, or open a new one. On Windows the variable is set at user level and new sessions pick it up automatically.

One-click setup →Codex Responses API guide →

Codex says stream disconnected before completion.

Codex raises this itself when its SSE stream ends early. With idle timeout waiting for SSE, no event arrived within stream_idle_timeout_ms (300000 ms by default): long-reasoning GPT runs can stay silent that long, so raise it on your custom [model_providers.<id>] block, for example to 600000. With stream closed before response.completed, the connection closed before the final event: check your proxy, VPN or network first. The gateway does not end a native Responses stream for being idle.

Codex stream errors →

Do streaming, tool calling, and structured outputs work the same across models?

The request shape does: set stream: true on the same endpoint for SSE chunks in the official shape, declare tools once in the OpenAI-compatible tools array, and send response_format (json_object, or json_schema with a named schema) on the same request. Support still varies by model — the catalog marks tool calling per model, and schema enforcement is the model's, not the gateway's. One vendor rule the catalog does not show: per OpenAI's docs (checked 2026-10-01), GPT-6 Astra and GPT-6.1 Sol take tool calls only on the Responses API, and GPT-6 Sol takes function calls on Chat Completions only with reasoning_effort set to none. The gateway checks the response_format envelope and returns 400 before any model call when json_schema, its name, or its schema is missing. Per-model differences show up in the request trace in Dashboard → Logs.

Streaming guide →Tool calling guide →Structured outputs guide →

Where do I find model IDs, and what does model: "auto" do?

The model catalog lists every model ID with pricing, context window, and capabilities — IDs are case-sensitive, so copy them exactly. With auto, the gateway classifies the request (rules plus a lightweight classifier) into a low, medium or high tier and serves it with a model from that tier's server-managed list; pin an exact ID when you need a specific model, since a request that names a catalog model ID is served by that model. IDs prefixed azure/, aws/ or vertex/ select a separately priced sales channel of the same base model, with its own routing pool and quota accounting; bare and vendor-prefixed IDs (openai/, anthropic/) keep the default channel.

Model catalog →GET /v1/models →Channel model IDs guide →

How do I see what each request cost?

Each request the gateway sends to a model is normally recorded with the model that served it, the API key that sent it, tokens, cost, total time (plus time to first token on streamed requests that produced output) and status. Dashboard → Logs shows per-request records and filters by model, API key, status and date; Dashboard → Usage aggregates spend over time. A request missing from Logs is a clue, not proof: it may never have reached the gateway (base URL, key or network), been refused before any model was called (a 401 for the key, a 402 for funds, a 429 from your key's or account's limits, or a 400 or 404 for the model ID or endpoint), failed before any output as a streamed request, or still be awaiting pricing.

Usage →Logs →

How do I connect other tools (LangChain, Cherry Studio, Cline, …)?

Any tool that lets you set a custom OpenAI-compatible base URL works: set the base URL to https://api.router.one/v1, paste your sk- key, and pick a model ID from the catalog. For tools that speak the Anthropic protocol, use https://api.router.one instead.

Does it work from Mainland China?

Yes — the gateway is directly reachable from Mainland China without a VPN, and the configuration is identical everywhere.

Image or video requests seem slow — should I set a client timeout?

Generation endpoints are slower than chat by nature: image generation typically takes tens of seconds, and video generation is asynchronous — submit returns a task_id you poll via GET /v1/videos/generations/{task_id}. Avoid short client timeouts; for chat, prefer streaming so output arrives as it's generated.

Claude Code 2.1.284 sends claude-sonnet-5-5: does Router One serve it, and does a plan cover it?

Per its changelog and model-config docs (checked 2026-10-01), Claude Code 2.1.284 (2026-09-28) points the sonnet alias at Claude Sonnet 5.5 and sends claude-sonnet-5-5. Router One lists claude-sonnet-5-5 from 2026-09-29, but no Pro, Max or Ultra tier lists it in the 2026-09-29 plan response, so on a plan /model sonnet, subagents defined with model: sonnet, /statusline and the execution phase of opusplan bill per token to the wallet (the model column in Dashboard → Logs shows which ID each call used). To keep them on plan quota, add ANTHROPIC_DEFAULT_SONNET_MODEL=claude-sonnet-5 to the env block of ~/.claude/settings.json; with or without a plan, you can add ANTHROPIC_DEFAULT_HAIKU_MODEL=claude-haiku-4-5 there too, then restart Claude Code. Per its changelog and model configuration docs (Claude Code 2.1.300, checked 2026-10-15), the fable alias resolves to claude-fable-5-1, which Router One lists again as of the 2026-10-15 catalog, so it needs no pin, and Claude Code 2.1.293 and later resolve the haiku alias to claude-haiku-5-5 (Claude Haiku 5.5), which Router One lists as of the 2026-10-10 catalog but no plan tier lists in the 2026-10-10 plan response, so without the Haiku line that alias bills per token to the wallet. Claude Fable 5.1, like Claude Fable 5, is in no plan tier as of the 2026-10-15 plan response, so the fable alias bills to the wallet. If you added ANTHROPIC_DEFAULT_FABLE_MODEL=claude-fable-5 earlier, the alias stays on Claude Fable 5 until you remove it.

Claude Code setup guide →Claude Code on Opus 5.5 →

I have a Pro, Max or Ultra plan — why did Claude Code charge my wallet?

Check the model column in Dashboard → Logs. Per its changelog and model-config docs (checked 2026-10-01), Claude Code 2.1.280 and later default to Claude Opus 5.5 and send claude-opus-5-5 unless a model is pinned, and as of the 2026-09-29 plan response no Pro, Max or Ultra tier lists that ID, so those calls bill per token to the wallet. To keep drawing plan quota, set ANTHROPIC_MODEL=claude-opus-5 and ANTHROPIC_DEFAULT_OPUS_MODEL=claude-opus-5 in the env block of ~/.claude/settings.json — Claude Opus 5 is in the Premium models tier of all three plans. A model outside the plan's tiers, or a request after a tier's monthly quota is used up, also bills to the wallet. On 2.1.284 or later, the sonnet alias also bills to the wallet on a plan unless you pin it (previous question).

Claude Code on Opus 5.5 →Plans & quotas →

Why did one request use several plan requests?

Its total input was above the model's long-context threshold. A standard request draws 1 request from its model tier; a request whose total input is strictly above the threshold draws more, by input-length band — Claude Opus 5, for example, draws 2 above 256,000 input tokens and 4 above 512,000 (catalog as of 2026-10-01). Input counts once including cached input, output does not count, and an input exactly at a threshold stays in the lower band. Wallet-billed calls draw no plan requests and keep the model's posted token rates. /pricing.md lists the live bands for every plan-covered model.

Live quota bands (pricing.md) →Pricing →

Claude Code 2.1.285 and later: why does a long session use plan quota faster?

Per the Claude Code changelog and model-config docs (checked 2026-10-01), from 2.1.285 a session behind a custom ANTHROPIC_BASE_URL gives Sonnet 5 and later, Opus 4.7 and later, and the Fable models the same 1M context window they have on the Anthropic API, and compacts at about 967K tokens by default. Each turn resends the conversation, so a long session's requests grow past the quota bands of the previous question: a claude-sonnet-5 or claude-opus-5 request whose input is above 256,000 tokens draws 2 plan requests, and one above 512,000 draws 4 (catalog as of 2026-10-01). To compact before the first band, add CLAUDE_CODE_AUTO_COMPACT_WINDOW=240000 (a plain integer) to the env block of ~/.claude/settings.json and restart Claude Code; it applies to every model. /autocompact 240k in a session works too, but per the model-config docs (checked 2026-10-03) Claude Code 2.1.288 and later save it for the current model only, so run it on each model you switch to; when both are set, the variable wins. One turn that adds a large file or tool result can still cross the band. CLAUDE_CODE_DISABLE_1M_CONTEXT=1 holds these models to a 200K window instead.

Claude Code on Opus 5.5 →Live quota bands (pricing.md) →

Claude Code says this session isn't eligible for auto mode's uncharged classifier requests: what does that mean?

Per Claude Code's auto mode classifier billing docs (checked 2026-10-01), the notice means auto mode's server-side checks aren't reaching this session, so Claude Code makes its own classifier requests instead, billed as they were before: nothing is broken, and auto mode keeps working. When Claude Code can identify a gateway in the path, the notice names it. It holds the first action it would check until you answer: Enter continues and, when the notice named a gateway, keeps it from reappearing on that machine for 24 hours; Esc or Ctrl+C cancels the held action and the turn. To stop the notice, set CLAUDE_CODE_AUTO_MODE_SERVER=0 in the env block of ~/.claude/settings.json (or in your shell) before you start the session; classifier requests are then always Claude Code's own, billed the same way. The docs call the variable a temporary setting that may be removed in a later release.

Claude Code in China →Claude Code setup guide →