What's different from calling the gateway directly
Response headers FreeRouter adds
| Header | When | Value |
|---|---|---|
X-FreeRouter-Request-Id | Every response, errors included | Opaque id for support and Logs correlation. |
request-id | /v1/messages, errors included | The same id under the name the Anthropic SDKs read. |
X-FreeRouter-Provider | Whenever a gateway was called | The gateway that answered. |
X-FreeRouter-Attempts | Every /v1 response | Upstream calls made; 0 when the request never left FreeRouter. |
X-FreeRouter-Failover | Only after a failover | gateway:reason,… for each losing attempt — see reading the failover headers. |
X-FreeRouter-Decisioner | When a decisioner ran on the key | Which target it picked and why (Routing Rules → Decisioner). |
X-FreeRouter-Key-Grace-Until | Calls made with a rotated key's old secret | When that secret stops working. |
X-FreeRouter-Responses-Mode | /v1/responses | native (gateway serves Responses itself) or translated (round-tripped through chat). |
X-RateLimit-*, Retry-After | Every response that reached a gateway, and 429 after every target rate-limited | The gateway's own rate-limit headers, passed through under its names (buffered, streamed and translated shapes alike); on a final 429, the last gateway's Retry-After. No other gateway header is forwarded. |
The full header reference is in API Reference → Response headers.
Request headers forwarded — and not
| Header | Forwarded? | Note |
|---|---|---|
HTTP-Referer, X-Title | Yes | OpenRouter app attribution. Values over 512 characters, or with control characters, are dropped silently. |
Idempotency-Key | Yes | Lets a gateway that honours it de-duplicate a client retry. Same 512-character cap. |
Authorization, x-api-key, x-goog-api-key | No | Your FreeRouter key is replaced by the stored provider key for the chosen gateway. |
Anything else (custom headers, User-Agent, cookies) | No | Forwarding is an allowlist; the three above are the whole list. |
Request body
On the openai and openrouter shapes the body goes upstream as you sent it, apart from three things FreeRouter does on purpose: a model remap or alias may rewrite model, a steering message may be prepended to the system prompt, and the ad_request / link_request siblings are peeled off before forwarding. The anthropic and google shapes are translated to the gateway's chat format and back — on anthropic that includes extended thinking (budget out, thinking blocks back), document blocks as file parts and server tools passed through, while top_k and cache_control are dropped; the full list is in API Reference → anthropic. OpenRouter's models and provider fields ride through untouched and never influence which gateway FreeRouter tries — see API Reference.
Not supported
| Feature | What happens | Instead |
|---|---|---|
POST /v1/completions (legacy) | 404 not_found | Use /v1/chat/completions. |
POST /v1/embeddings on a gateway with no embeddings route | Skipped (no-embeddings); 501 embeddings_unsupported when no target has one | Route the key to a gateway that serves embeddings — see API Reference → embeddings. |
POST /v1/messages/count_tokens with the model's own tokenizer | Served locally as an estimate (X-FreeRouter-Count-Tokens: estimate) | Budget with it; bill from usage on the response. See count_tokens. |
Gemini :streamGenerateContent and any /v1beta/… path | 400 (streaming) / 404 (/v1beta) | Call /v1/models/{model}:generateContent; stream through an openai-shaped key. |
Browser calls (CORS) on /v1 | No Access-Control-* headers; the browser blocks the response | Call from a server. Your key would be visible in the page anyway. |
OpenAI file ids (/v1/files, file_id in batches) | 404 not_found | Send files by URL; batches take their requests inline. |
Responses conversation objects | Rejected | Use previous_response_id on a chain-capable gateway (chaining). |
Limits and timeouts
| Limit | Default | Range | Note |
|---|---|---|---|
| JSON body | 10 MB | — | Over it: 413 request_too_large. Batch submits stream through and are exempt. |
| Failover timeout (first byte) | 5 s | 1–30 s per key or per target | Streaming requests only: a non-last target that sends no first byte in time is abandoned and the next one tried. Buffered requests wait the full upstream timeout, because most gateways send headers only with the finished completion. |
| Upstream timeout | 60 s | 5–90 s per key | Capped at 90 s because Cloudflare returns 524 when the origin is silent for about 100 s. |
| Request deadline | 95 s | platform-wide | The whole request — every failover hop, remap, decisioner pick and MCP tool round together. A hop gets only the time left; past the deadline no further target is called and the request fails with the last failure or 504 deadline_exceeded. A response that has started streaming is never cut. |
| Failover triggers | Connection errors, timeouts, and upstream 401 / 402 / 403 / 404 / 429 / 5xx — on buffered and streaming requests alike. Set in Routing Rules → Timeouts. | ||
| Rate limit | None on FreeRouter's side. 429s come from the gateways and fail over. | ||
Added latency
Sub-millisecond for a plain routing decision, 20–30 ms when remaps, translation or a drained failover attempt are involved. The breakdown, and how the dashboard separates router time from upstream time, is in Usage & Spend → What latency does FreeRouter add?.
IP allowlist scope
A workspace allowlist and a per-key allowlist can both be set; when either is non-empty the caller must be admitted by every non-empty list, or the request is refused with 403 ip_not_allowed naming the address seen. The lists cover inference on /v1 only — management keys and the MCP server at /mcp are not covered. Details: API Reference → IP allowlists.
Responses chaining
previous_response_id is honoured, but the id FreeRouter returns (resp_fr_…) is pinned to the provider that produced it: a chained turn goes back to that provider with no failover, and only chain-capable gateways can continue a thread. A chained turn whose provider is no longer on the key answers 409 response_chain_target_unavailable. The gateway list and the rules are in API Reference → Responses chaining.