OpenRouter Guide: API, Pricing, Provider Routing and BYOK

By Updated

What is OpenRouter?

OpenRouter is a cloud gateway to language models: one OpenAI-compatible API and one credit balance give you access to hundreds of models from different labs. OpenRouter sends each request to one of the providers that serve the model. There's no markup on inference prices; the fee is charged when you buy credits.

TL;DR

  • -To connect, change base_url to https://openrouter.ai/api/v1 and use an OpenRouter key. The model is a vendor/model string such as anthropic/claude-haiku-5.5. An Anthropic-compatible /api/v1/messages endpoint serves Anthropic-format clients.
  • -OpenRouter passes provider prices through without markup. The fee comes at top-up: 5.5% with an $0.80 minimum on Standard, 5% for crypto, 8% on Business. A $5 top-up costs $0.80 in fees, or 16%.
  • -One model can sit behind several providers with different quantization, prices and parameter support. In a November 7 test, the quantizations: ["fp8"] filter moved qwen/qwen3-coder from DeepInfra (fp4) to Venice, and the request cost 28% more.
  • -Fallback through the models list bills the price of whichever model answered. In testing, a chain of a :free model and Haiku 5.5 was answered by the paid Haiku twice, because the free pool was busy at the provider.
  • -OpenRouter doesn't store prompts by default, but each provider sets its own retention and training policy. For sensitive data, turn on provider.zdr: true or ZDR only mode in account settings.

OpenRouter is a cloud gateway to language models. One OpenAI-compatible API and one credit balance give you hundreds of models from different labs, from Claude and GPT to open Qwen, DeepSeek and Gemma. You pick a model with a string like anthropic/claude-haiku-5.5, and OpenRouter routes the request to one of the providers serving it. Inference prices carry no markup; the fee is charged when you top up. In its August 19, 2026 announcement, OpenRouter cited 400+ models and 10+ million developers.

Your first request takes a base_url change. The trouble starts with money and routing. A $5 top-up costs $0.80 in fees. A “free model first, paid model second” fallback chain turns out to be paid in practice. The same open model runs in different quantizations, with different parameter sets, at different providers. And a request with tool_choice can land on a provider that silently ignores it.

This guide covers how the OpenRouter catalog and providers work, what a top-up really costs, how to control provider selection and fallback, what happens to your data and cache, and how to connect Claude Code, OpenCode and Codex CLI. API behavior was tested on November 7, 2026 with a key capped at $5: a Python script using only the standard library, POST /api/v1/chat/completions, a short prompt and max_tokens: 30. All tests together cost $0.0018. The top-up fee, BYOK, ZDR and Claude Code through OpenRouter weren’t tested; those parts come from the documentation.

What OpenRouter is and when you need it

OpenRouter handles four jobs. It gives you one API format for many labs: code written for the OpenAI SDK switches between Claude, GPT and Qwen by changing the model string. It keeps one balance and one bill instead of an account with every vendor. It fails over between providers of one model and, if you ask, between different models. And it shows spend by key, model and provider in one place.

OpenRouterDirect provider APILiteLLM Proxy
Where it runsOpenRouter cloudProvider cloudYour server
KeysOne OpenRouter key (or your own via BYOK)A key per vendorProvider keys stay with you, virtual keys for the team
BillingCredits, fee at top-upA bill from each vendorProvider bills, the software is free
Fallback across labsYes, the models parameterNoYes, in config.yaml
Data pathThrough OpenRouter and the chosen providerProvider onlyThrough your host and the provider
What you maintainNothingNothingServer, database, updates

A direct API makes more sense when you work with one vendor and need its features on release day, with no fee and no extra hop. The Claude API guide covers Anthropic’s API directly. A self-hosted gateway fits when provider keys must stay inside your perimeter or you need per-employee budgets; see the LiteLLM guide. Where a gateway sits in a multi-provider setup is covered in Multi-Provider LLM Routing.

Models and providers: how the catalog works

The catalog needs no key: GET https://openrouter.ai/api/v1/models. On November 7, 2026 it had 460 entries, including :free and :batch variants and service routers. The vendors with the most models were openai (98), google (43), qwen (43) and anthropic (30). The count changes almost daily.

A model ID is vendor/model. Besides pinned versions there are tilde aliases: ~anthropic/claude-sonnet-latest always points to the newest model in the family (latest resolution). An alias is handy for a prototype. In production, pin the version so behavior doesn’t change without a release on your side.

IDs take suffixes. Per the FAQ, there are two kinds:

SuffixKindWhat it does
:freeCatalogFree version of the model, a separate entry with its own limits
:batchCatalogBatch processing, half price for Claude 5.5
:nitroRoutingProviders sorted by throughput, plus priority endpoints
:floorRoutingProviders sorted by price, plus flex endpoints
:exactoRoutingProviders ordered by tool-calling reliability
:onlineRouting, deprecatedWeb search in the prompt; replaced by the server tool openrouter:web_search

Catalog variants exist only for models that list them in /models. Routing suffixes work on any model.

One model, different providers

Several providers serve most models, each through its own endpoint. You can see the list without a key: GET /api/v1/models/<vendor>/<model>/endpoints. For open models the gap between providers can be large.

Snapshot for qwen/qwen3-coder on November 7, 2026:

ProviderQuantizationPrice per 1M (input / output)Parameterstool_choiceContext
DeepInfrafp4$0.30 / $1.0015none, auto, required, function262,144
Venicefp8$0.35 / $1.5011none and auto only256,000

Of these two providers, only DeepInfra supports logit_bias, min_p, repetition_penalty and seed. If a request with tool_choice: "required" lands at Venice, you won’t get an error: per the documentation, without special settings an unsupported parameter is simply ignored.

Closed models vary less, but they still vary. On the same date Haiku 5.5 was served by Anthropic, Amazon Bedrock, Google Vertex, Azure and Claude Platform on AWS. Global endpoints cost $0.10 per 1M input tokens; regional ones (google-vertex/europe, amazon-bedrock/eu-west-1 and others) cost $0.11.

Quick start: your first request

You need an account and a key from openrouter.ai/settings/keys; the key looks like sk-or-v1-.... The API base URL is https://openrouter.ai/api/v1. OpenRouter implements OpenAI-compatible /chat/completions, /completions and /responses (FAQ). The Quickstart examples now use /responses, but /chat/completions works the same way.

curl

curl https://openrouter.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $OPENROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -H "HTTP-Referer: https://example.com" \
  -H "X-OpenRouter-Title: My App" \
  -d '{
    "model": "anthropic/claude-haiku-5.5",
    "max_tokens": 30,
    "messages": [{"role": "user", "content": "Reply with exactly: ok"}]
  }'

The HTTP-Referer and X-OpenRouter-Title headers are optional: they attribute your app in the openrouter.ai rankings. Per the documentation, the old X-Title name is still accepted.

OpenAI SDK

import os
from openai import OpenAI

client = OpenAI(
    base_url="https://openrouter.ai/api/v1",
    api_key=os.environ["OPENROUTER_API_KEY"],
)

resp = client.chat.completions.create(
    model="anthropic/claude-haiku-5.5",
    max_tokens=30,
    messages=[{"role": "user", "content": "Reply with exactly: ok"}],
)
print(resp.choices[0].message.content)

TypeScript works the same way: baseURL: "https://openrouter.ai/api/v1" in the OpenAI constructor. Parameters the OpenAI SDK doesn’t know about (models, provider) go through extra_body; there’s an example in the fallback section below.

What comes back in the response

Besides the usual OpenAI-format fields, the response includes provider (who actually served the request), model (which model answered, which matters with fallback) and usage.cost (cost in dollars). Per the usage accounting docs as of November 7, usage with cost comes back in every response. The usage: {include: true} parameter is deprecated and has no effect.

Verified: November 7, 2026, anthropic/claude-haiku-5.5, prompt “Reply with exactly: ok”. The answer “ok” arrived in 1.05 s from provider Claude Platform on AWS, with 18 input and 4 output tokens and a cost of $0.0000038. That matches the price of $0.10 / $0.50 per 1M tokens. Usage in GET /api/v1/key showed 0 right after the tests and updated a few minutes later.

OpenRouter pricing and fees

OpenRouter passes provider prices through unchanged, and the FAQ says so directly: there’s no markup on inference. The platform makes its money on a fee when you buy credits.

PlanTop-up feeBYOKLimits
FreeDoesn’t applyNo50 requests a day, free models only
Standard5.5%, $0.80 minimum; crypto 5% with no minimum$25,000 a month at list price with no fee, 5% above thatPay-as-you-go
Business8%Same as StandardPay-as-you-go
EnterpriseBy contractCustomBy contract

The 5.5% and 8% rates come from the Pricing page. The $0.80 minimum and the 5% crypto rate come from the fee post (updated June 11, 2026). Terms are as of November 2026. The actual charge couldn’t be verified: the test account already had a balance, and no new top-up was made.

Because of the $0.80 minimum, the effective rate depends on the amount:

Top-upFeeEffective rate
$5$0.8016%
$10$0.808%
$25$1.385.5%
$100$5.505.5%
$1,000$55.005.5%

A few more conditions from the Terms (version of August 31, 2026). A single purchase is $5 to $25,000. You can request a refund of unused credits only within 24 hours of payment; the fee isn’t refunded, and crypto payments are never refunded. OpenRouter may expire unused credits 365 days after purchase, so topping up a year ahead doesn’t pay off.

Claude 5.5 and Fable 5.1 prices in the catalog

As of November 7, 2026, per 1M tokens:

ModelInputOutputCache read
Fable 5.1$10$50$0.25
Opus 5.5$4$20$0.20
Sonnet 5.5$2$10$0.10
Haiku 5.5$0.10$0.50$0.01

All four have :batch variants at half price. How to measure cost per solved task rather than per token is covered in LLM Cost Optimization.

Provider routing: how to pick a provider

If you don’t name a provider, OpenRouter picks one. The default algorithm weighs provider price and stability, and it changes over time. When tested on November 7, the documentation described it as comparing effective price, speed, time to first token, 429 and error rates, and tool-call quality. If a provider fails, the request moves to the next one automatically. Setting sort, order, :nitro, :floor or your own provider key turns the default algorithm off.

The provider object in the request body controls the choice:

FieldDefaultWhat it does
order-Providers in priority order
allow_fallbackstrueWith false, only providers from order; otherwise an error
only / ignore-Provider allowlist and blocklist
sort-price, throughput or latency
quantizations-Filter: int4, int8, fp4, fp8, fp16, bf16, unknown and others
require_parametersfalseOnly providers that support every parameter in the request
data_collection"allow""deny" excludes providers that store data and may train on it
zdr-ZDR endpoints only
max_price-Price cap per 1M tokens; if no provider fits, the request fails
preferred_min_throughput, preferred_max_latency-Soft speed thresholds: slow providers move down the list but aren’t excluded

Example: fp8 only, no more than $1 per 1M input and $2 per 1M output tokens.

{
  "model": "qwen/qwen3-coder",
  "messages": [{"role": "user", "content": "Reply with exactly: ok"}],
  "provider": {
    "quantizations": ["fp8"],
    "max_price": {"prompt": 1, "completion": 2}
  }
}

Verified: November 7, 2026, qwen/qwen3-coder, the same short prompt.

RequestProvidercost, $
sort: "price"DeepInfra0.0000059
sort: "throughput"DeepInfra0.0000059
quantizations: ["fp8"]Venice0.00000755

Without a filter the request went to DeepInfra, which runs fp4 per /endpoints. With the fp8 filter, Venice served it, and the request cost 28% more. On an open model, quantization affects answer quality, so set it explicitly.

404 errors and routing_funnel

OpenRouter’s routing errors are detailed, which helps with debugging.

Verified: November 7, 2026, anthropic/claude-haiku-5.5, provider: {only: ["nonexistent-provider"], allow_fallbacks: false}. The response was a 404. Its metadata listed the model’s providers (google-vertex, claude-on-aws, azure, anthropic, amazon-bedrock), a step-by-step routing_funnel and failed_routing_step. The funnel: 10 endpoints, 5 after the regional markup filter, 0 after the provider filter. The error shows the full model ID: anthropic/claude-haiku-5.5-20261007.

The funnel tells you right away which filter killed the route: a typo in a provider slug, a max_price that’s too strict, or account privacy settings.

Model fallbacks and Auto Router

Fallback between providers of one model is on by default. You set fallback between different models with a models list in priority order (model fallbacks). OpenRouter tries the next model on any error from the first: context overflow, moderation refusal, rate limit, downtime. You pay for the model that answered, and its name comes back in the model field.

With the OpenAI SDK, pass the list through extra_body. The model in model goes first, and models holds the fallbacks in order:

resp = client.chat.completions.create(
    model="anthropic/claude-haiku-5.5",
    messages=[{"role": "user", "content": "Reply with exactly: ok"}],
    extra_body={
        "models": ["anthropic/claude-sonnet-5.5"],  # fallback models, in order
    },
)
print(resp.model)  # the model that actually answered

Verified: November 7, 2026. A request with models: ["nonexistent-vendor/no-such-model", "anthropic/claude-haiku-5.5"] returned 400 “is not a valid model ID”. OpenRouter validates the model list before routing, so a typo in the first model fails the whole request instead of falling through to the next one. Two requests in a row with models: ["google/gemma-4-26b-a4b-it:free", "anthropic/claude-haiku-5.5"] both returned 200 from anthropic/claude-haiku-5.5 at $0.0000038 each. The free model was rate-limited at the provider at that moment, and the request quietly went to the paid one.

The documentation warns about this: if a paid model follows a :free one in models, fallback bills the paid price. To keep a request guaranteed free, list only :free models, or use the openrouter/free router, which switches only between free models. Log model from the response in your app, or a switch to the fallback model goes unnoticed.

For the Anthropic format (/api/v1/messages) there’s a fallbacks parameter instead of models. It takes at most 3 entries, each with only a model field, and it can’t be combined with models. Breaking any of these rules returns 400.

Auto Router

Auto Router (openrouter/auto) picks a model for each request. The router itself costs nothing extra: you pay the price of the chosen model, and provider.max_price still applies. OpenRouter updates its routers often. On November 7 the catalog had several entries with the openrouter/ prefix (auto, auto-code, free and others), and the Auto Router page already described a new generation with a cost_tier parameter. Auto Router wasn’t run in testing. For predictable production spend, set the model explicitly.

Free models (:free)

Models with the :free suffix cost $0. They’re separate catalog entries with their own limits and providers. On November 7, 2026 the catalog had 12 of them plus the openrouter/free router. Limits per the documentation:

Credits bought (all time)Requests per minuteRequests per day
Fewer than 102050
10 or more201,000

GET /api/v1/key returns the current daily counter in the free_model_daily_requests field. The documentation adds a caveat to the threshold: to cover rounding and fees, the higher daily limit kicks in one credit early. With a negative balance, you may see errors even on free models.

Verified: November 7, 2026, google/gemma-4-26b-a4b-it:free. The response was 429 “temporarily rate-limited upstream”, limit_source: upstream_provider_shared_pool, provider Google AI Studio. The remedy_hint suggested adding your own key (BYOK) or picking another provider. The response had no X-RateLimit-* headers.

You can get a 429 on :free with your personal limit untouched: the free model’s pool at the provider is shared, and your own counter won’t explain it. Beyond experiments, free models aren’t reliable. Mind privacy too: the account setting that allows providers who train on data is separate for paid and free models (provider logging).

BYOK: bring your own provider keys

BYOK (bring your own key) means connecting your own provider key, for example Anthropic or Bedrock. Requests still go through the OpenRouter API, but you pay for inference on your provider account, and the rate limits are yours too. Per the BYOK docs and Pricing, on the Standard and Business plans the first $25,000 a month at list price carries no fee. Above that, OpenRouter deducts 5% of the cost of the same request from your credits. The Free plan has no BYOK. Older summaries mention a “1 million free BYOK requests a month” rule; the cost-based limit replaced it.

Two details affect the bill:

  • Shared capacity fallback. By default, if your key hits a limit or returns an error, OpenRouter falls back to its own endpoints and spends your credits. To prevent that, pick “Never use shared capacity” in the key settings.
  • Priority. Keys are either Prioritized (tried before OpenRouter endpoints) or Fallback (tried after them). Without order in the request, providers you hold a Prioritized key for go first.

BYOK wasn’t tested: it needs a separate provider key.

Privacy, logging and ZDR

Per the FAQ, OpenRouter logs request metadata (time, model, token counts) and doesn’t store prompts or responses unless you turn logging on. If you do, OpenRouter gives a 1% discount on usage.

The request still goes to a provider, and every provider has its own policy. As of November 7, the ZDR documentation splits endpoints into three tiers:

TierWhat happens to data
ZDR (Zero Data Retention)Prompts and responses usually aren’t stored after processing
Safety RetentionThe provider or OpenRouter may keep data only for abuse prevention, no training
Retention and TrainingStored per the provider’s policy, training possible

How to restrict the route:

  • provider.zdr: true in the request: ZDR endpoints only (plus Safety Retention if the account allows it).
  • provider.data_collection: "deny": no providers that collect data.
  • Account privacy settings or guardrails: ZDR only mode, no training. If you set provider and no provider matches the account settings, the request fails.

Self-serve accounts allow Safety Retention by default; Enterprise accounts get ZDR only. ZDR covers inference but not plugins and server tools such as web search, which follow their own third-party policies. When tested, the ZDR page also said that all requests, ZDR traffic included, are screened for CSAM, and suspicious content may be kept for review. For sensitive data, check the specific endpoint’s policy before sending, and keep a data policy layer in your application, as in Multi-Provider LLM Routing.

Prompt caching through OpenRouter

The prompt cache lives at the provider, so a repeat request has to reach the same provider. OpenRouter handles this with sticky routing (prompt caching). It turns on only when the provider’s cache read is cheaper than normal input, and it doesn’t work with a manual provider.order. OpenRouter identifies a conversation by a hash of the first system message and the first non-system message, or by an explicit session_id in the body or the x-session-id header (up to 256 characters). Per the documentation as of November 7, a session lives for 60 minutes without requests.

The rules differ by provider:

ProviderHow it’s enabledCache writeRead
AnthropicExplicitly, cache_control (on a block or at the top level of the request)1.25x input (5-minute TTL), 2x (1-hour TTL)0.1x input; 0.05x on Opus 5.5 and Sonnet 5.5, 0.025x on Fable 5.1
OpenAIAutomatically from 1,024 tokensFree on models before GPT-5.6, 1.25x on GPT-5.6 and later (30-minute TTL) or 2.5x (12 hours)0.1x or 0.05x input on GPT-6 and GPT-6.1, 0.25x or 0.5x on older models
Alibaba QwenExplicitly, cache_control1.25x, 5-minute TTL0.1x input

Gemini, DeepSeek and a cache break-even formula are covered in how prompt caching works across providers.

The minimum cacheable prompt for Claude 5.5 and Fable 5.1 is 512 tokens. Here’s an example with the cache on the system prompt:

{
  "model": "anthropic/claude-haiku-5.5",
  "messages": [
    {"role": "system", "content": [
      {"type": "text", "text": "<long instructions or document>",
       "cache_control": {"type": "ephemeral"}}
    ]},
    {"role": "user", "content": "Reply with exactly: ok"}
  ]
}

How much the cache saves: a Haiku 5.5 test

Verified: November 7, 2026, anthropic/claude-haiku-5.5, a 12,635-token system prompt with cache_control: {type: "ephemeral"}, two identical requests 2 s apart.

Requestcached_tokenscost, $Time, s
First (cache write)00.001581.51
Second (cache read)12,6190.000131.41

The second request was 12 times cheaper than the first. The first cost more than a normal request: 12,635 tokens at $0.10 per 1M would be $0.00126, but $0.00158 was charged, which is the 1.25x cache write premium. The same provider served both requests; otherwise the cache read wouldn’t have happened.

The cache pays off from the second hit, and a prompt you send only once costs 25% more with cache_control. Cache metrics come back in usage.prompt_tokens_details.cached_tokens and cache_write_tokens. How caching works on Anthropic’s side is covered in the Claude API guide.

Tool calling and structured outputs: what differs

In the November 7 catalog, 398 of 460 entries support tools, 393 support tool_choice, 387 structured_outputs and 401 response_format. That’s support at the model level. A specific provider can support less, as Venice does for Qwen3 Coder.

Per the documentation, tools, the response format (response_format, structured outputs) and verbosity act as soft preferences: if the model has providers that support them, the request goes there. With require_parameters: false, a provider that doesn’t support any other parameter simply ignores it. To send a request only to providers that support all of its parameters, set require_parameters: true.

{
  "model": "qwen/qwen3-coder",
  "messages": [{"role": "user", "content": "What time is it?"}],
  "tools": [{"type": "function", "function": {
    "name": "get_time", "parameters": {"type": "object", "properties": {}}}}],
  "tool_choice": "required",
  "provider": {"require_parameters": true}
}

Verified: November 7, 2026, qwen/qwen3-coder, one tool get_time, tool_choice: "required", provider: {require_parameters: true}. The response was 200 from DeepInfra and included tool_calls. That matches the /endpoints data: Venice doesn’t support tool_choice: required, and DeepInfra does.

For agents that rely on tool calls, require_parameters: true is a sensible default. The alternative is the :exacto suffix, which orders providers by tool-calling reliability; it wasn’t run in testing.

Connecting agents: Claude Code, OpenCode, Codex CLI

Claude Code

Per the official OpenRouter guide, Claude Code connects through environment variables with no local proxy, because OpenRouter accepts the Anthropic Messages API.

export ANTHROPIC_BASE_URL="https://openrouter.ai/api"
export ANTHROPIC_AUTH_TOKEN="$OPENROUTER_API_KEY"
export ANTHROPIC_API_KEY=""            # must be explicitly empty
# optional: pin models per class
export ANTHROPIC_DEFAULT_SONNET_MODEL="~anthropic/claude-sonnet-latest"
export ANTHROPIC_DEFAULT_HAIKU_MODEL="~anthropic/claude-haiku-latest"
claude

If you previously signed in to Claude Code with an Anthropic account, run /logout once; otherwise the cached session conflicts with the gateway key. Put the variables in your shell profile, not in a project .env: the native Claude Code installer doesn’t read it. Check the connection with /status: the Auth token line should name ANTHROPIC_AUTH_TOKEN.

The setup comes with two warnings. The OpenRouter guide itself says it’s guaranteed to work only with the Anthropic first-party provider and recommends putting that provider first in provider routing. And the Claude Code documentation says plainly that Anthropic doesn’t endorse or audit third-party gateways and doesn’t support routing Claude Code to non-Claude models through any gateway. Anthropic gives no official support for Claude Code with OpenRouter, so you run it at your own risk. Claude Code through OpenRouter wasn’t run for this article.

OpenCode

OpenRouter is a built-in provider in OpenCode (guide). In the TUI, run /connect, choose OpenRouter and enter the key, then pick a model with /models. Add more models to opencode.json by their OpenRouter slug. Agent configuration and model tests are covered in the OpenCode guide.

Codex CLI

Codex CLI connects through a provider block in ~/.codex/config.toml (guide):

model_provider = "openrouter"
model = "<vendor/model from the catalog>"

[model_providers.openrouter]
name = "openrouter"
base_url = "https://openrouter.ai/api/v1"

[model_providers.openrouter.auth]
command = "sh"
args = ["-c", "echo $OPENROUTER_API_KEY"]

env_key = "OPENROUTER_API_KEY" also works, but then Codex doesn’t load the OpenRouter model catalog and shows an unknown-model warning for non-OpenAI models.

Limits and errors

CodeWhenWhat to do
400Invalid model ID (including in models), extra fields in fallbacksCheck the ID against /api/v1/models
402Not enough credits, or the in-flight budget is used upCheck metadata.reason, lower max_tokens, top up
404No provider passed the filters (only, max_price, privacy)Check routing_funnel and failed_routing_step
429:free limit or the provider’s shared poolCheck limit_source, retry with backoff, add a fallback

The in-flight budget (limits) applies to some prepaid accounts with small balances and to new accounts. OpenRouter reserves the estimated cost of running requests and returns 402 when that runs short, even with a positive balance. reason: "in_flight_budget_exhausted" is temporary: wait for Retry-After. reason: "weight_exceeds_budget" means a single request costs more than the whole budget. Retrying won’t help; cut max_tokens or the prompt.

The documentation doesn’t name a fixed RPM for paid models. Capacity is managed globally, and extra accounts or keys don’t raise the limit. When a provider returns 429, OpenRouter first tries other providers of the same model and only then passes the error to the client. GET /api/v1/key shows spend and the remaining limit for a key: limit_remaining, usage_daily, usage_weekly, usage_monthly. You can set a spend limit on each key, which is an easy way to cap an experiment or a single service.

OpenRouter limitations and when to use something else

  • Data goes through a third party. Even with ZDR, the request passes through OpenRouter’s and the provider’s servers. If keys and traffic must stay inside your perimeter, you need a self-hosted gateway such as LiteLLM or a local model. The options are collected in the local LLM guide, setup is covered in the Ollama guide, and the choice between the two popular apps in LM Studio vs Ollama.
  • Quality depends on the provider. Quantization and parameter support differ between providers of one model, and the default provider can change without you doing anything. For reproducible results, pin quantizations, order or only and log provider from the response.
  • The catalog changes. Models get an expiration_date, and prices and provider lineups shift. A hardcoded ID with no monitoring will start returning errors one day.
  • Fees on small amounts. A $5 top-up costs 16% on top. You can get credits refunded only in the first 24 hours, and unused credits can expire after a year.
  • One vendor and its new features. If you work only with Anthropic or OpenAI and need new API features on release day, the direct API is simpler and cheaper by the size of the fee.

How to tie the gateway, fallback, evals and monitoring into one system is covered in Production LLM Stack.

Where to start

  1. Create a key on openrouter.ai and set a spend limit on it right away.
  2. If you plan regular use, top up at least $25: at that amount the fee is 5.5%, not 16%. Keep the 24-hour refund window and the 365-day expiry in mind.
  3. Connect the OpenAI SDK by changing base_url, and log model, provider and usage.cost from every response.
  4. For open models, check /api/v1/models/<id>/endpoints and pin quantizations or order.
  5. For agents and tool calls, set provider.require_parameters: true.
  6. For sensitive data, turn on ZDR only mode in privacy settings or send provider.zdr: true with requests.
  7. Send long system prompts to Claude with cache_control and check cached_tokens on the second request.

Frequently Asked Questions

Does OpenRouter mark up model prices?
No. Per the OpenRouter FAQ, provider prices pass through with no markup on inference. The platform earns its money from a fee on credit purchases: as of November 2026, 5.5% with an $0.80 minimum on the Standard plan, 5% for crypto payments and 8% on the Business plan.
How much does an OpenRouter top-up cost with the fee?
Per the table in the OpenRouter blog, the fee is $0.80 on $5, also $0.80 on $10, $1.38 on $25, $5.50 on $100 and $55 on $1,000. Because of the $0.80 minimum, small top-ups cost more in percentage terms. The fee isn't refundable, and under the Terms unused credits can expire 365 days after purchase.
Are OpenRouter free models really free?
Models with the :free suffix cost $0 but have limits: 20 requests per minute and 50 per day if the account has bought fewer than 10 credits, or 1,000 per day after buying at least 10. A 429 on :free can also come from the provider's shared pool. If a paid model follows a :free one in the models list, fallback bills the paid price.
Does OpenRouter store my prompts?
Per the OpenRouter FAQ, it logs request metadata (time, model, token counts) but doesn't store prompts and responses unless you turn logging on. The providers that receive the request follow their own policies: ZDR, Safety Retention, or retention with training. For strict requirements, set provider.zdr: true or ZDR only mode in privacy settings.
How do I stop OpenRouter from switching to another provider?
Set provider.order to a list of providers and allow_fallbacks: false. The request then goes only to those providers and returns an error if they're unavailable. provider.only is softer: it keeps an allowlist, but OpenRouter picks within it. Fallback between models is a different parameter, models.
Can I connect Claude Code to OpenRouter?
Yes, per the official OpenRouter guide: ANTHROPIC_BASE_URL=https://openrouter.ai/api, the OpenRouter key in ANTHROPIC_AUTH_TOKEN and an empty ANTHROPIC_API_KEY. OpenRouter guarantees it only with the Anthropic first-party provider. Anthropic doesn't audit third-party gateways and doesn't support Claude Code on non-Claude models, so you run this setup at your own risk.
What is BYOK in OpenRouter and what does it cost?
BYOK means connecting your own provider key: requests go through OpenRouter but are billed to your account with the provider. On the Standard and Business plans, the first $25,000 a month at list price carries no fee; above that, OpenRouter deducts 5% of the cost of the same request from your credits. The Free plan has no BYOK.
OpenRouter or LiteLLM?
OpenRouter is a cloud service with one bill and a model catalog, with nothing to host, but requests pass through its servers and top-ups carry a fee. LiteLLM is a self-hosted proxy: provider keys stay with you, and you set up budgets and per-employee keys yourself, along with running the server. You can add OpenRouter to LiteLLM as one of its providers.