Providers

A provider is an LLM gateway you connect to FreeRouter with a key you already own. FreeRouter routes across your providers and forwards each request using your key — it never resells inference.

The BYOK model

FreeRouter is bring-your-own-keys. You keep your existing accounts and billing with each gateway; FreeRouter only decides which one handles a given request. You pay each gateway directly, and you walk away from any of them by removing it from your routing rules.

Where keys sit: your app holds only the FreeRouter key; the dashboard holds your provider keys, encrypted; FreeRouter calls the gateway with the provider key, so the gateway never sees your FreeRouter key. Your app holds only fr_live_… Authorization: Bearer fr_live_… FreeRouter Dashboard Providers tab provider keys, encrypted at rest Proxy api.freerouter.com routing rule picks a target, swaps in its provider key Authorization: Bearer sk-or-… Gateway sees your provider key, never your FreeRouter key
Your application ships only the FreeRouter key (fr_live_…). The provider keys you paste under Providers are encrypted at rest and never returned after you save them; on each request the proxy decrypts the one its routing rule picked and sends it to that gateway. Delete a provider key and every rule that referenced it stops using it at once.

Supported gateways

OpenRouter, Vercel, Cloudflare, OrcaRouter, Requesty, Concentrate, LLM Gateway, Baseten, Darkbloom, Sail, Ramp Router, Together AI, Fireworks AI, Morph, Cheaper Inference, Celeris, SayGM, Experiential Labs, and NanoGPT are live for chat today. Decisions / System One hosts serve systemone-shaped FreeRouter keys, and each carries specific decision models: OpenRouter carries every vendor's decider (Jev, Perplexity Decider, GPT-6 Luna Decisions, Clef, Mercury Decide and more); TypeSafe (invite-only) and Requesty carry Jev; Cloudflare carries its Clef family (cloudflare/clef, cloudflare/clef-flash) through Workers AI on your AI Gateway, and reads images natively; OpenAI carries GPT-6 Luna (gpt-6-luna, also spelled openai/gpt-6-luna-decisions) through its own Decisions API — FreeRouter translates the System One request and answers to and from OpenAI's format, so your client code does not change. An OpenAI key is Decisions-only here: FreeRouter does not route chat to OpenAI directly. Vercel AI Gateway carries its own decision catalog — Jev (typesafe-ai/jev), GPT-6 Luna Decisions, Liquid d1, and Convai Laya — through its TypeSafe-compatible API, with the same AI Gateway key you use for chat. Vercel takes text and JSON state only for now; image requests skip it. Vercel serves decision models to paid-credit accounts only — a free-tier account answers 403 “Free tier users do not have access to this model”, and FreeRouter fails over to your next Decisions target. Celeris carries its own celeris-1-decision (see Celeris ids), with image input. Ramp Router carries Jev (jev-1.13.0, aliases jev-latest and jev-preview) on its /v1/systemone route — not in Ramp's own docs, but advertised in its catalog — with the same Ramp Router key you use for chat; text only. FreeRouter keeps Jev out of Ramp's chat model list, since a chat request to it is refused. The same OpenRouter, Requesty, Cloudflare, Vercel, Celeris, or Ramp Router key you use for chat works for Decisions; a Cloudflare token needs Workers AI permission for Clef. TypeSafe and OpenAI keys cannot be chat routing targets. FreeRouter sends each request only to hosts that carry its model — see the systemone shape. A TypeSafe, OpenRouter, Requesty, Vercel, or Ramp Router row can be the decisioner on a chat-shaped key (Cloudflare and OpenAI cannot — the decisioner runs Jev): Jev picks among that key's chat targets, then FreeRouter still returns a chat completion. Cloudflare keys also ask for your account ID and gateway name, which scope its upstream URL; the dashboard's How to find this links show where each value lives.

Every gateway below is a chat target today; the model id table says how each one spells a model and what an unknown id does. Ramp Router is the one gateway that does not serve /v1/chat/completions at all — it implements only the OpenAI Responses endpoint, and FreeRouter translates both ways (see below). More gateways are on the roadmap; adding one is a config change, never an application rewrite.

The Responses API across gateways

FreeRouter serves the OpenAI Responses API at /v1/responses on every gateway listed above, on any openai- or openrouter-shaped key. Gateways differ only in how they serve it, never in whether they do.

Gateway/v1/responsesChains (previous_response_id)
Ramp RouterNative — and the only endpoint it has; its chat traffic is the translated oneYes
OpenRouterNativeNo — rejects chaining outright (400)
RequestyNativeNo — silently ignores it; FreeRouter refuses to chain off it
Cloudflare AI GatewayNative (via its /compat endpoint)Yes
DarkbloomNative — also returns reasoning summariesNo — silently ignores it; FreeRouter refuses to chain off it
Vercel AI GatewayNativeNo — silently ignores it; FreeRouter refuses to chain off it
OrcaRouterNative — across OpenAI, Anthropic, Google and DeepSeek models alikeNo — chains only some models, so treated as unable
ConcentrateNative — also returns reasoning items and reasoning_tokensNo — accepts fabricated ids, so treated as unable
LLM GatewayNative — also serves GET /responses/{id}Yes — across all six model families tried
BasetenNative — appends a chat-style [DONE], harmless to spec-following clientsNo — rejects chaining outright (501)
SailNative — also streams reasoning-summary eventsNo — rejects chaining outright (400)
Fireworks AINative — on every model it serves; also serves GET /responses/{id} and streams reasoning summariesYes — across all seven model families tried
MorphNative — streams reasoning summaries; stateless, so GET /responses/{id} is not availableNo — rejects chaining outright (501)
Cheaper InferenceNative — on every text model it lists; stateless, so GET /responses/{id} is not availableNo — rejects chaining outright (400)
CelerisNative — on both chat models, with reasoning items on celeris-1-magnus; stateless, so GET /responses/{id} is not availableNo — rejects chaining outright (404)
SayGMNative — on every model that lists the Responses shape; stateless, so GET /responses/{id} is not availableNo — rejects chaining outright (503; store is forced back to false)
Experiential LabsNative — GET /responses/{id} is not servedYes — across GPT, Qwen, Claude and DeepSeek models tried; a fabricated id is refused (400)
NanoGPTNative — buffered and streaming. GET /responses/{id} answers, but it is not offered: chaining is not gateway-wide, and retrieval requires chainingNo — context carried on one family only (Qwen). Llama answered a different word; a fabricated id is refused (400)
Together AITranslated — deliberately. Together's own /responses route accepts only a handful of its models; translating covers all of themNo — the translated path cannot anchor a chain

Native support above was verified against every gateway with a live key on 2026-09-22 (Fireworks AI on 2026-09-29, Morph and Cheaper Inference on 2026-10-01, Celeris on 2026-10-08, SayGM, Experiential Labs and NanoGPT on 2026-10-14), buffered and streaming. There is no longer an unverified row: each entry was measured, not inferred from documentation. Only Together AI takes the translated path, and for a specific reason given below.

Together AI is the exception, and the reason the table has two translated rows: its /v1/responses is real but per model. One model (openai/gpt-oss-120b) serves it; the rest answer 400 "The requested model does not support the Responses api". Since native support here is a property of the gateway, marking Together native would break roughly 170 models to make one byte-faithful — so every Together model takes the translated path and works.

The practical difference is fidelity, not availability: reasoning summaries, hosted tools, annotations and logprobs survive only on a native gateway. Every response carries X-FreeRouter-Responses-Mode: native | translated so you never have to guess which path a given request took.

If your client chains turns by sending previous_response_id, the key must include a gateway with Yes in the Chains column — anything else serves the first turn and fails the follow-ups. See Chained turns pin to one provider for the setup consequence.

Model IDs across gateways

OpenRouter's provider/model ids are the canonical spelling. Each gateway spells the same model its own way, and FreeRouter's daily catalog crawl maps every gateway's ids onto the canonical ones, so translation runs both ways: send any gateway's spelling and each target receives its own (vertex/claude-opus-5-5 reaches OpenRouter as anthropic/claude-opus-5.5; anthropic/claude-opus-5.5 reaches Requesty as anthropic/claude-opus-5-5). A target that lists your exact id receives it unchanged; one whose catalog carries no spelling of the model is skipped without a call (model availability). Dash-written versions (claude-haiku-5-5) and dotted ones (claude-haiku-5.5) are the same model wherever a gateway lists the dotted form.

GatewayId styleExample idAuto-translatedAn unknown id returns
OpenRouterprovider/model — the canonical formopenai/gpt-4o-miniYes (reference catalog)404 → fails over (no-model)
Vercel AI Gatewayprovider/model, a few vendor slugs differ (zai/…)openai/gpt-4o-miniYesIts own error; a 404 fails over
Cloudflare AI Gatewayprovider/model; most of its catalog is prefixed by upstream (aws-bedrock/…, openrouter/…)openai/gpt-4o-miniYesIts own error; a 404 fails over
OrcaRouterprovider/model, plus orcarouter/auto (cheapest live; never transfers)openai/gpt-4o-miniYesIts own error; a 404 fails over
Requestyprovider/model with dashed versions, host routes (vertex/…, region pins @eu) and policy/… routing policies (never transfer)anthropic/claude-haiku-5-5YesIts own error; a 404 fails over
ConcentrateBare idsgpt-4o-miniYesForwarded as sent; the gateway answers (a 404 fails over)
LLM GatewayBare ids, or provider-pinned provider/model-idgpt-4o-miniYesForwarded as sent; the gateway answers (a 404 fails over)
BasetenBaseten's own mixed-case org slugs; small curated catalogzai-org/GLM-5.2YesIts own error; a 404 fails over
DarkbloomBare ids; small cataloggpt-oss-20bYes404 → fails over (no-model)
SailHuggingFace checkpoint ids, case-sensitivezai-org/GLM-5.3Yes — exact case restored before the callIts own error; a 404 fails over
Ramp RouterBare ids, version dots as p; GET /v1/models is authoritative, its web page labels are notgpt-4o-miniYes404 model_not_found → fails over (no-model)
Together AIHuggingFace-style ids, case-sensitive; catalog narrowed to the serverless fleetmeta-llama/Llama-3.3-70B-Instruct-TurboYes404 → fails over (no-model); a dedicated-endpoint model answers 400 model_not_available
Fireworks AIResource paths, version dots as p; catalog narrowed to deployed models (+ …/routers/<model>-fast); …/routers/firerouter/* ids pass straight throughaccounts/fireworks/models/kimi-k3Yes404 “Model not found, inaccessible, and/or not deployed” → fails over (no-model)
MorphMorph's own ids, mapped from its price list; -fast tiers are separate modelsmorph-glm53-744bYes — z-ai/glm-5.3 is sent as morph-glm53-744b400 “is not served by this endpoint” → read as a model miss, fails over (no-model)
Cheaper InferenceBare ids, each naming its maker (the maker breaks ties); its routing fields (min_discount_percent, zdr, ranking) pass throughclaude-opus-4.6YesIts own error; a 404 fails over
SayGMBare ids; ids ending in -tee are its confidential (TEE) variants and route as their own modelsdeepseek-v4-flash-0731Yes400 “unknown model” → read as a model miss, fails over (no-model)
Experiential LabsBare slugs; some stay locked until the account buys credits (model_requires_purchase)qwen3.8-27bYes403 model_not_granted → fails over (no-model)
NanoGPTOpenRouter-style ids. A :thinking or effort suffix is its own model. Decision-output rows, auto-model and nano-gpt-help are not in the chat catalogmeta-llama/llama-3.2-3b-instructYes400 model_not_supported → read as a model miss, fails over (no-model)
CelerisBare or celeris/…; each model lives at its own URL (https://inference.celeris.ai/<model>/v1) — FreeRouter strips the prefix and calls the right URLceleris-1YesIts own error; a 404 fails over

Experiential Labs also serves embeddings (POST /v1/embeddings, five models), an async batches API, and the Anthropic Messages API upstream. FreeRouter does not route those surfaces to it yet — embeddings and batches join it when those endpoints are verified across gateways — so its rows here cover chat and Responses only.

Experiential Labs and top_p. Its Kimi models reject top_p: 1 with HTTP 400, and that is the value most OpenAI clients send by default. It means "no nucleus cutoff," the same as leaving the field off. Other models on the same gateway accept 1. FreeRouter omits top_p only when the target is Experiential, so one request works for every model there. temperature is forwarded unchanged, and every other gateway still receives top_p.

NanoGPT also serves embeddings, a Decisions endpoint, Messages, and batches upstream. FreeRouter does not route those yet. Decision models and embeddings are queued (see the provider note in the repo); the chat catalog drops decision-output rows so a plain chat call is not sent to one. A decision model that is called anyway answers 400 invalid_response_format, which is relayed, not failed over. Prices are USD per million tokens. A subscription account that hides paid models crawls a smaller catalog than an account that shows them.

A 404 (or Morph's, SayGM's and NanoGPT's model-miss 400) is failover fuel: a priority rule moves to the next target instead of failing the request, and only when every target answers 404 do you get model_not_found. The live translation table is served at https://app.freerouter.com/api/model-map, and the model field of the response always names what actually ran — check it when a router alias such as Fireworks' firerouter/opus could silently answer from a different model (it only reaches Anthropic or OpenAI if you gave Fireworks those keys).

How we build the catalog

The generated snapshot at data/model-map.json aligns canonical ids with each gateway's catalog (built with npm run model-map from app/; refreshed daily). Vendor aliases fold HuggingFace-style slugs onto OpenRouter canonical ids (zai-org → z-ai, deepseek-ai → deepseek), Fireworks' resource paths are folded the same way (accounts/fireworks/models/glm-5p3 → z-ai/glm-5.3), and Morph's ids are mapped from its public price list, which names the model behind each id. Where catalogs name a model too differently for spelling rules — Ramp Router's glm-5p2 is z-ai/glm-5.2, Baseten's nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B is nvidia/nemotron-3-ultra-550b-a55b — the daily refresh has a small model judge the equivalence among pre-filtered candidates. Different sizes, versions, quantizations, dated snapshots, context-window variants and tiers are never matched, and uncertain matches are reviewed by the FreeRouter team before they affect routing. A gateway whose catalog is missing or more than 72 hours old is never assumed to lack a model, and a model id no catalog knows yet (a same-day launch) is forwarded untouched.

Together AI over-lists: its GET /v1/models includes models that require a dedicated endpoint you start and pay for by the hour, and calling one with an ordinary key answers 400 model_not_available. FreeRouter serves the serverless subset instead — GET /v1/models, the dashboard model picker and the Playground list only models a plain Together key can call. The subset is the union of GET /v1/endpoints?type=serverless (the running fleet) and the PRODUCT_SERVERLESS entries of GET /v2/supported-models (which catches the newest models first). Neither source alone is complete; the union was checked against 48 live calls and never excluded a model that works. Together's own /responses route accepts only a handful of its models, so every Together model takes the translated Responses path (see the Responses table).

Fireworks AI over-lists too: eleven of the 27 models in its GET /inference/v1/models answer 404 on an ordinary key because they need an on-demand deployment. FreeRouter lists only what Fireworks' own supports_serverless=true marks callable, plus the …/routers/<model>-fast tier of each. Its FireRouter ids (accounts/fireworks/routers/firerouter/auto, …/kimi, …/opus) are not in the catalog but pass straight through.

Morph's chat catalog leaves out the ids its chat endpoint does not serve (its System One and computer-use models), Fast Apply's auto router, and morph-glm52-744b, which Morph answers with GLM-5.3; its coding models (morph-v3-fast, morph-v3-large, morph-compactor, morph-warp-grep-v2.1) stay listed.

Celeris has no endpoint that lists every model, so FreeRouter reads model names and prices from Celeris's own docs (docs.celeris.ai/models and /pricing) and confirms each model against your key before listing it. On a systemone key the same Celeris key serves celeris-1-decision; images you put in state are moved into Celeris's own image field, because Celeris does not see images inside state. Ramp Router lists its decision model (Jev) in the same catalog as chat models, so it is dropped from the chat list.

NanoGPT's basic GET /models lists ids and no prices, so FreeRouter refetches GET /models?detailed=true. That list drops decision-output rows, every auto-model* router, and nano-gpt-help. A :thinking or effort suffix stays, each as its own model. Prices are already USD per million tokens; a cache-read price quoted per 1,000 tokens is scaled into the per-million field before it is stored. The API host and the website host do not list exactly the same models; the crawl uses the API host.

If a narrowing listing is unavailable, FreeRouter shows the whole catalog rather than a short or empty one — a filter should never be the reason a model is missing.

Ramp Router and the Responses endpoint

Every other gateway FreeRouter supports speaks POST /v1/chat/completions. Ramp Router implements exactly two OpenAI routes — GET /v1/models and POST /v1/responses — and returns 404 for chat completions.

You do not have to care. FreeRouter's Ramp adapter converts your chat request into a Responses create payload on the way out and converts the answer back on the way in, including streaming: response.output_text.delta events become chat.completion.chunk objects, and FreeRouter appends the data: [DONE] sentinel that Ramp does not send. Tool calls round-trip in both directions.

One behavioral difference is worth knowing. On the Responses endpoint, max_output_tokens — what your max_tokens becomes — also pays for a reasoning model's hidden reasoning tokens. A small budget on a reasoning model can therefore be spent entirely on reasoning, returning an empty message. FreeRouter reports that honestly rather than hiding it: you get finish_reason: "length" (never a bare stop) and usage.completion_tokens_details.reasoning_tokens showing where the budget went. FreeRouter will not quietly raise the budget on your behalf — that would spend your money differently than you asked. If you see an empty answer with finish_reason: "length", raise max_tokens or lower reasoning_effort.

Encrypted reasoning items returned by Ramp are dropped and never reach your client. Ramp's own error envelope is the standard OpenAI one and is relayed untouched, so 402 insufficient_credits, 404 model_not_found and the rest read exactly as they would direct.

Adding a provider

1
Open Providers → Add provider
In app.freerouter.com, choose the gateway you want to connect.
2
Paste your provider key
Provide the API key from that gateway's own dashboard. FreeRouter encrypts and stores it against your workspace (keys are verified on first use, not at save time). Cloudflare also asks for your account ID and gateway name — the form's How to find this links show where each value lives.
3
Reference it in a routing rule
Add the provider as a target in a %-split or failover rule, then attach that rule to a FreeRouter key. The same flow is available on the management API: store the key with POST /api/v1/providers, keep the returned UUID, and pass it as provider_key_id on the routing rule.

How your keys are used

Encrypted at rest and swapped in per request — see where keys sit. Two more rules:

  • Scoped to a workspace. Keys belong to the workspace you added them in.
  • Removable anytime. Delete a provider to revoke its use across every rule that referenced it.
Check gateway terms Some gateways place restrictions on commercial or multi-tenant BYOK routing in their terms of service. Confirm your intended usage is permitted with each provider before relying on it in production.

Model identifiers

Regardless of gateway, FreeRouter uses provider/model style identifiers in the model field so a request is unambiguous. Examples:

openai/gpt-4o-mini
anthropic/claude-haiku-5.5
google/gemini-2.5-flash-lite

Your routing rule selects the gateway by priority order; FreeRouter fails over to the next target on rate limits (429), upstream errors (5xx), 404/no-model responses, network errors, and a slow first byte (the failover timeout, default 5s, adjustable per key and per target) — see priority with failover. The model string is translated to each target's own spelling where the catalog knows it and passed through verbatim otherwise (see Model IDs across gateways). Use GET /v1/models to see what's available to a key.

Back to Getting Started