OpenRouter Will Finally Make Sense After This
OpenRouter is one address and one key in front of hundreds of AI models run by dozens of companies. We sent real requests on free models: a free Gemma answered 429 because one provider's free pool was full, Nemotron answered through NVIDIA, the OpenAI library worked with one changed line, the key showed its 50 free requests a day and $0 spending limit, and a list of models kept Ana answered. Then when to use OpenRouter and when to go direct.

The first free request
You made an OpenRouter key for the free models, and the very first request came back: error 429. Provider returned error. Ana's tea shop script just got the same thing from a free Gemma model. The reason is in the reply: rate-limited upstream, at Google AI Studio, in a shared pool.
./ask google/gemma-4-31b-it:freeerror 429: Provider returned error
jq -r '.error.metadata | .raw, .provider_name, .limit_source' reply.json | cut -d. -f1google/gemma-4-31b-it:free is temporarily rate-limited upstream Google AI Studio upstream_provider_shared_pool
So what is OpenRouter? Not a model, and not a cloud. It's a router: one address and one key, in front of hundreds of models run by dozens of companies. By the end you'll know where a request really goes, what free gets you, and how that same busy Gemma request got an answer anyway.
Someone asked a sharper version on Hacker News: OpenRouter just routes to providers like DeepInfra, so why not use them directly? What's the five percent markup for? Fair question. We'll answer it with real requests.

What OpenRouter is
What's actually behind that one key? OpenRouter's model list is public, no key needed. 460 models today, from 69 makers. And twelve of them end in colon free.
curl -s https://openrouter.ai/api/v1/models | jq '.data | length'460
curl -s https://openrouter.ai/api/v1/models | jq '[.data[].id | split("/")[0]] | unique | length'69
curl -s https://openrouter.ai/api/v1/models | jq -r '.data[].id | select(endswith(":free"))'liquid/lfm-3-1.7b:free recursive/flint-v1.0:free xingchen-agi/xing4.0-29b-a4b:free nvidia/nemotron-3.5-super-vl:free dots-studio/dots-3-note-preview:free liquid/lfm-2.5-2.6b:free nvidia/nemotron-3.5-lightning:free cohere/north-mini-code:free nvidia/nemotron-3-ultra-550b-a55b:free nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free google/gemma-4-26b-a4b-it:free google/gemma-4-31b-it:free
Here's the whole picture. Ana's script sends every request to one address: OpenRouter's. OpenRouter checks her key and her spending limit, picks a provider, a company that runs that model on its own servers, passes the request on, and sends the answer back, with the cost counted in one place.

Why would you want a router at all? Without one, Ana's script needs an account and a key at every company whose models she wants to try, each with its own bill, and some with their own request format. With OpenRouter, it's one account, one key, one format, and trying another model means changing its name.

Every model on that list has a name in three parts. First, who made it: Google. Then the model itself, Gemma 4, the 31 billion size, tuned to follow instructions. And an optional variant after a colon: free.

One request, end to end
How does a request get there? Ana's ask script is plain curl, a tool for web requests. It posts her question to OpenRouter's chat completions address, with the key in a header, read from an environment variable: a named setting the shell hands to programs, so the key never sits in the script. The model is just one field.
cat ask#!/usr/bin/env bash # ./ask MODEL, or ./ask MODEL1 MODEL2 (a list: if the first fails, OpenRouter tries the next) Q="Describe our Sencha green tea in one calm sentence." if [ $# -gt 1 ]; then PICK=$(printf '%s\n' "$@" | jq -R . | jq -cs '{models: .}') else PICK=$(jq -cn --arg m "$1" '{model: $m}'); fi BODY=$(jq -cn --argjson pick "$PICK" --arg q "$Q" '$pick + {messages: [{role: "user", content: $q}]}') curl -s --max-time 120 https://openrouter.ai/api/v1/chat/completions \ -H "Authorization: Bearer $OPENROUTER_API_KEY" \ -H "Content-Type: application/json" -d "$BODY" > reply.json jq -r 'if .error then "error \(.error.code): \(.error.message | sub(" Manage it.*| Please retry.*"; ""))" else (.choices[0].message.content | gsub("^\\s+|\\s+$"; "")), "", "model: \(.model)", "provider: \(.provider)" end' reply.json
Ana tries another free model, this one made by NVIDIA: Nemotron Lightning. Same script, same key, only the model's name changed. An answer. And the reply says which model answered, and which provider ran it: NVIDIA itself.
./ask nvidia/nemotron-3.5-lightning:freeSteamed to perfection, it yields a luminous green cup with gentle seaweed sweetness, a breath of fresh grass, and a serene, lingering calm that washes over the senses. model: nvidia/nemotron-3.5-lightning:free provider: Nvidia
Inside that one request: the script sends the question and the key to OpenRouter. OpenRouter checks the key, then sends the question on to NVIDIA. NVIDIA's servers run the model and answer, and OpenRouter hands it back with the model's name, the provider, and the token count.

OpenRouter keeps a record of every request. A token is a piece of a word, the unit models count and charge by. Ana's cost script looks this one up: 28 tokens in, 750 out, for one sentence. 708 of them were the model thinking before it answered. Cost: zero dollars.
./costmodel: nvidia/nemotron-3.5-lightning-20260807:free provider: Nvidia tokens in: 28 tokens out: 750 of them, thinking: 708 cost: $0
Why so many tokens for one sentence? Nemotron is a reasoning model: it writes hidden notes to itself before the answer. Here that was 708 tokens of thinking, and 42 for the sentence you read. OpenRouter's docs say thinking tokens count as output, and are charged that way. Free here, but on a paid model you pay for all of them.

A model is not a provider
Why did the free Gemma fail when Nemotron didn't? Because a model and a provider aren't the same thing. Google made Gemma and published it openly, so other companies run it on their servers too. 19 providers run this Gemma, each at its own price, from.10 dollars per million tokens in. The free version? One provider: Google AI Studio.
./providers google/gemma-4-31b-it19 providers run google/gemma-4-31b-it CoreWeave $0.10 in, $0.34 out Venice $0.12 in, $0.36 out Chutes $0.12 in, $0.37 out DeepInfra $0.14 in, $0.51 out DekaLLM $0.14 in, $0.40 out
./providers google/gemma-4-31b-it:free1 provider runs google/gemma-4-31b-it:free Google AI Studio $0.00 in, $0.00 out
That's the four two nine. Everyone using the free Gemma shares one provider's free pool. When that pool is full, OpenRouter has nowhere else to send it. The paid version has 19 places to go: if a provider returns an error, OpenRouter tries the next one by itself.

Because most models have several providers, you can steer the choice. Add a variant to the name: colon nitro sorts providers by speed, colon floor by price. Colon free is different: it's a separate free listing, with its own limits.

What changes in your code
Most apps don't use curl, though. Ana's Python describer was written for OpenAI's own library. Diff compares two files, and they differ in one line, the client: OpenRouter's address as the base URL, and the OpenRouter key. OpenRouter accepts the same request format, so the library works unchanged, and now a Cohere model answers.
diff describe_openai.py describe.py5c5 < client = OpenAI(api_key=os.environ["OPENAI_API_KEY"]) --- > client = OpenAI(base_url="https://openrouter.ai/api/v1", api_key=os.environ["OPENROUTER_API_KEY"])
python describe.py cohere/north-mini-code:freeOur Sencha green tea delivers a gentle, refreshing taste with subtle grassy notes and a calming smoothness that invites quiet moments of serenity. model: cohere/north-mini-code:free
What free really means
So who pays? OpenRouter runs on credits: money you put in first. Each provider sets a price per million tokens, and OpenRouter passes that price through with no markup. It charges its fee when you buy credits: 5.5% on the standard plan. That's the markup from the question.

Free models cost nothing, but they're limited. Ana's key has never had credits. Her usage script asks OpenRouter what it knows about the key. Guess first: how many free requests a day does it get? Fifty. We've used 20 already, testing this video today. And its spending limit is zero dollars, so it can never be charged.
./usagefree tier: true spending limit: $0 free requests today: 20 of 50
OpenRouter's own rule: fifty free requests a day until you've bought at least ten dollars of credits, then one thousand requests a day. Free variants can also have their own limits, and less availability, like that busy Gemma. Enough to learn with, not to run a shop on.

And a paid model? Ana asks Claude Haiku 5.5 with the same key. 403, key limit exceeded. The zero-dollar limit stopped it at OpenRouter, before any provider saw the question.
./ask anthropic/claude-haiku-5.5error 403: Key limit exceeded (total limit).
So two things stand between a request and a bill. The key's own spending limit, and your account's credits. Teams use key limits to hand out keys safely: each app gets its own key, with its own cap, and a leaked key can only spend what its cap allows.

When a model is busy
Now the busy Gemma. Ana's script can send a list of models instead of one: Gemma first, Nemotron second. Gemma's pool is still full. Guess first: which model answers? Nemotron. OpenRouter tried Gemma, got the error, and moved down the list, inside one request.
./ask google/gemma-4-31b-it:free nvidia/nemotron-3.5-lightning:freeSteeped in tranquility, our Sencha unfurls fresh vegetal notes and a soft, lingering calm that soothes the spirit with every sip. model: nvidia/nemotron-3.5-lightning:free provider: Nvidia
One rule matters here. You pay for the model that answered. Put a paid model after a free one, and a fallback is billed at the paid price. To stay free, list only free models.

Or let OpenRouter choose. The model called openrouter slash free picks a free model at random, one that supports what your request needs. This time, a small model from Liquid answered.
./ask openrouter/freeOur Sencha green tea is a calm, lightly fragrant green infusion that brings a refreshing, earthy clarity to your cup with smooth, vegetal notes and a gentle, lingering finish. model: liquid/lfm-3-1.7b:free provider: Liquid
So when a free model says four two nine, you have three ways out. Wait and try again later, because the pool is shared. Send a list of free models, so another one can answer. Or add credits and use the paid version, which has many providers behind it.

Where your prompt goes
Where did Ana's question go? Through OpenRouter, to whichever provider ran it: NVIDIA, Cohere, Liquid. Each provider has its own rules for keeping prompts and training on them. In your OpenRouter settings you choose whether to allow providers that may train on your data, with separate settings for paid and free models. So check the provider before you send anything private.

When to use it
Real apps run on this every day. Kilo Code, an open-source coding agent, is near the top of OpenRouter's public rankings page, with 667 billion tokens. That's requests like Ana's, at a much bigger scale.

So, OpenRouter or a provider directly? Keys: one for everything, or one per company. Models: hundreds from dozens of makers, or that one company's. When a provider fails: OpenRouter tries the next, or your own code has to. Price: the provider's price plus the fee on credits, or just the provider's. In one line: one key for many providers, or one key per provider.

So that five percent buys one key, one bill, and fallbacks. Use OpenRouter to try models and compare them, or to keep working when a provider is down. Go direct when you've settled on one model at high volume, or need a feature only that company offers.

Every command and the lab files are linked in the description, ready for your own free key.

Recap
So: one key to OpenRouter, a provider runs the model, free models share small pools, and a list of models keeps you answered.
If OpenRouter finally makes sense, a like helps YouTube show this to more beginners, and subscribing brings you the next one.
Every request here went to the real OpenRouter, on free models. Thanks for watching Cloud Explainers.
Sources
- OpenRouter FAQ (a unified API; pricing passed through with no markup; a fee when buying credits; free-model limits: 50 requests a day, 1000 after buying at least 10 credits; fallback to the next provider)
- OpenRouter pricing (platform fee: Standard 5.5%)
- Free variant (:free models may have different rate limits or availability)
- Model fallbacks (the models array; priced by the model that answered; to stay free, list only :free models)
- Free Models Router (openrouter/free picks a free model at random)
- Provider logging (each provider's own policies; separate training settings for paid and free models)
- OpenRouter rankings, top apps (Kilo Code, 667B tokens, 2026-11-07)
- OpenRouter models API (public model list; endpoints per model)
- Hacker News, Ask HN: Why would I use Openrouter over something like DeepInfra directly?
Demos: one container on our own Mac standing in for Ana's laptop, sending real requests to OpenRouter with our own free-tier key (never shown); the tea shop is made up. Watch the full video on YouTube.