
What it does
One nRouter key, pointed at
https://api.nrouter.ai/v1, reaches every provider in your live catalog through the OpenAI request and response shape you already write. Choosing a different provider is a different value in themodelfield. You do not hold a provider key, a provider SDK, or a provider invoice.
The one-paragraph version: nRouter is an OpenAI-compatible endpoint sitting in front of multiple model providers. Your application keeps the OpenAI SDK it already imports, keeps its streaming loop, keeps its tool-calling code, and changes two constructor arguments. In exchange, the per-provider integration layer — the auth scheme, the request translation, the response normalisation, the key rotation, the second billing portal — stops being code you own.
This post is about that one property: breadth behind one credential. It is not about picking the cheapest model for a given call (that is routing as a cost lever), not about capping spend (budget ceilings), and not about splitting the bill across your own customers (per-customer billing). Those three sit on top of this one. This is the seam they all need first.
The job it does for you
Here is the workflow most teams are actually running, written honestly.
Before. You start with one provider because one provider was enough. Six weeks later somebody wants a second one — a cheaper model for classification, or a longer context window, or simply a hedge against a bad afternoon. Adding it means a new SDK in requirements.txt, a new secret in your secret manager with its own rotation schedule, a new client wrapper because the two SDKs disagree about what a message looks like, a new error taxonomy because the two providers disagree about what a rate limit looks like, and a new invoice that arrives on a different day of the month in a different format. None of that is hard. All of it is permanent. And because it is permanent, the third provider is a conversation rather than a change, which is how teams end up with exactly one provider and a strong opinion that they are multi-model.
The tell is the in-house abstraction layer. Almost every team past the second provider has one: a LLMClient interface, two or three concrete implementations, a factory, and a translation function that is one edge case behind whatever the providers shipped last week. It works. It is also a piece of infrastructure your team now maintains forever, whose entire job is to make three APIs look like one API — a problem that was solved by the first of the three APIs becoming the de facto standard.
The disagreements are individually trivial and collectively endless. Anthropic's Messages API takes the system prompt as a top-level system parameter and reports consumption as usage.input_tokens and usage.output_tokens; the OpenAI shape carries the system prompt as the first entry of messages and reports usage.prompt_tokens and usage.completion_tokens. Neither design is wrong. Reconciling them is simply a piece of code you now own, and it has to be right on the day a provider adds a field.
After. There is one client, one credential, one error taxonomy, one set of response headers, and one bill. The model is a string. The abstraction layer is deleted, and the thing it was abstracting is now a configuration surface rather than a code surface.
The honest version of the payoff is not "it is faster." It is that the marginal cost of considering a new model drops to roughly zero, and that changes which decisions get made. A model that would need two sprints to evaluate does not get evaluated. A model that needs a string change gets evaluated on a Tuesday afternoon.
What the catalog actually contains today
The catalog is a live thing, and this is the one place a blog post ages badly, so the answer here is a pointer rather than a list: the models page is authoritative for what your key can reach right now, and the API returns the same list programmatically. Anthropic, OpenAI and AWS Bedrock are live today. Anything else you see on that page is live too — the page is generated from what the gateway actually serves, not from a marketing table.
Two things worth knowing about how that list behaves:
- It is per-environment. What your key reaches is what your organisation is entitled to, which is why the endpoint is the right source and a hardcoded list in your code is not.
- A model that prices at nothing is not enabled. If a model appears, it has a rate. If its cost cannot be determined for a specific call, the call is reported as unpriced rather than as
$0— the reasoning is in cost honesty, and it matters here because a breadth claim that quietly includes unbillable models is not a breadth claim.
You do not bring provider keys. nRouter holds the provider relationships and you hold credits and one nRouter key. That is a real trade with real consequences in both directions, argued in full in why we do not do BYOK, and it is the reason the integration collapses to one credential at all.
How it works
The customer-visible contract is small enough to state completely.
What you configure. A base URL and a key. Optionally, a router alias if you want a name that resolves to a set of models rather than to one model.
What the gateway does. It authenticates the key, resolves the model, translates your OpenAI-shaped request into whatever the target provider expects, calls it, translates the response back, and records the call against your organisation with its settled cost.
What you get back. The standard OpenAI response body, plus a set of x-nr-* headers that describe what actually happened:
| Header | What it tells you |
|---|---|
x-nr-routed-model | Which model actually served the request |
x-nr-model-fallback | Present when failover occurred, as requested->served |
x-nr-request-cost | The settled cost of this call — absent when the cost is not knowable |
x-nr-cost-status | exact or unpriced, so an absent cost is never ambiguous |
x-nr-request-id | The identifier to quote when correlating logs |
Those headers are the reason breadth does not cost you observability. With one provider you could read the provider's own dashboard. With five you would be reconciling five dashboards, which is why most multi-provider teams end up with worse cost visibility than single-provider teams. Here the visibility is on the response, in one shape, regardless of who served it.
The last piece is failover, and it is worth stating precisely because it is easy to over-claim. If the model you asked for fails to deliver, the request is retried on an equivalent model from a different provider and the header tells you it happened. You can replace that default with your own ordered chain. What the chain cannot do is fire selectively — a model you list is attempted on any delivery failure, not only on the failure type you had in mind. Provider fallback chains covers the design, including the trap that a retry is a second call and therefore a second bill.
Set it up
The whole migration is two constructor arguments. Here is the diff against a standard OpenAI integration:
from openai import OpenAI
- client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
+ client = OpenAI(
+ base_url="https://api.nrouter.ai/v1",
+ api_key=os.environ["NROUTER_API_KEY"],
+ )Everything downstream of that line is unchanged. To read the headers alongside the body, use the SDK's raw-response accessor rather than reaching for a second HTTP client — with_raw_response is documented in the OpenAI Python SDK and works unchanged against this base URL:
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.nrouter.ai/v1",
api_key=os.environ["NROUTER_API_KEY"],
)
raw = client.chat.completions.with_raw_response.create(
model="claude-sonnet-4-5", # any id from /models
messages=[{"role": "user", "content": "Summarise this contract in 3 bullets."}],
)
completion = raw.parse()
print(completion.choices[0].message.content)
print(raw.headers.get("x-nr-routed-model"))
print(raw.headers.get("x-nr-request-cost")) # absent when unpriced
print(raw.headers.get("x-nr-cost-status")) # "exact" | "unpriced"Ask the endpoint what it can reach rather than trusting a list you wrote down:
curl -s https://api.nrouter.ai/v1/models \
-H "Authorization: Bearer $NROUTER_API_KEY"The same swap works from every client that speaks the OpenAI protocol, which in practice means most of the framework ecosystem: the Python SDK and Node SDK pages carry the exact constructor for each, and the framework pages cover the wiring for LangChain, LlamaIndex and Vercel AI. If you are coming from another gateway rather than from a provider directly, migrating off OpenRouter is the same shape of change with a few extra notes on header parity.
Adding a model that shipped this morning
The claim "adopting a new model is a string change" is true in a narrow, useful sense and false in a broad one, and it is worth separating the two.
True: the plumbing is a string. No dependency, no credential, no client, no deploy of a new integration path. Change the model value, or change what a router alias points at in Router Settings and change nothing in code at all.
Not true: the evaluation is not a string. A new model has a different tokeniser, different latency, different refusal behaviour, and different failure modes on your particular prompts. Swapping it in blind is how a quiet quality regression ships. The right sequence is a deterministic split of real traffic between the incumbent and the candidate, with a quality signal you decided on before you looked — deterministic A/B testing across model variants is the mechanics.
What the single seam buys you is that step one costs nothing, so step two actually happens.
Worked example with numbers
This is an integration-effort example, and the engineering rates are yours to substitute — the arithmetic is what generalises, not the figures.
Take a team that wants three providers in production: a flagship for reasoning, a small model for classification, and a third as a hedge. Estimate the per-provider integration at three engineer-days of first build (SDK, auth, translation, error mapping, tests) and one engineer-day per quarter of maintenance (SDK bumps, deprecations, a changed error shape).
| Line | Direct integrations | One key |
|---|---|---|
| First build, 3 providers | 9 engineer-days | 0.5 engineer-days |
| Maintenance, 4 quarters | 12 engineer-days | 0 |
| Credentials to rotate | 3 | 1 |
| Billing relationships to reconcile | 3 | 1 |
| Cost visibility | 3 dashboards, 3 formats | 1 header, on every response |
| Year-one engineering | 21 engineer-days | 0.5 engineer-days |
Illustrative effort figures, not a measured platform claim. Substitute your own build and maintenance estimates.
The line that usually decides it is not the 21 days. It is row three and row four. Three provider credentials means three rotation calendars and three chances to be the team that discovers an expired key in production. Reducing that to one nRouter credential is a security simplification before it is a convenience — and the one credential you keep is itself divisible into scoped, revocable keys per service, which is the subject of virtual keys vs master key.
What it costs
The breadth is not a paid feature, and neither is anything else: the single line a plan moves is the platform fee — 4% on top of provider spend on pay as you go, 0% on Pro at $50/mo or $500/yr — and the current table is on the pricing page.
The crossover is arithmetic you can do without a call: the 4% fee reaches $50 at around $1,250/month of provider spend on the monthly plan, and around $1,042/month on the annual one. Below that, pay as you go is cheaper. The full walkthrough, including when the annual commitment is the wrong answer, is in from credits to Pro.
Two things to be plain about. There is no free tier here: the card comes before the first call, the $5 minimum is a real charge with the platform fee on top, and the only offset is a $10 first-purchase bonus — load $5, get $15, once per organisation, after the payment clears. And because the fee sits on top of a public provider rate, a team that has negotiated committed-spend pricing directly with a provider will not carry that rate through here. For those teams the arithmetic can come out the other way, and it should be run before anything else.
Where it fits with the rest of the platform
Breadth behind one key is the substrate. The capabilities worth having are the ones that become possible once every call passes through one place:
- Routing. Once a model is a string and an alias is a set, choosing per request stops being an architecture decision. Cut LLM costs by routing is the cost-lever version of that argument.
- Ceilings. One seam is where a hard dollar cap can actually live. Budget ceilings that turn AI spend into a forecast covers the scopes and what each returns when it bites.
- Attribution. One place that sees every call is the only place that can split the bill by the customer it served — bill your customers for the AI they actually used.
- Guardrails. Content checks that run before egress and before the client sees the response, on every plan: guardrails on every request.
- Scoping. Keys, budgets and guardrails hang off an org/team/member hierarchy rather than off a single global credential — org, team, member.
Limits and what it will not do
An unqualified capability post is marketing, so here is the qualified version.
- It does not give you every model in the world. It gives you your live catalog. The models page is the answer, and if a model you need is not on it, the honest answer today is that it is not available through us today.
- It does not let you bring your own provider key. No BYOK. If you have a negotiated rate with a provider, you cannot carry it through this seam.
- It adds a hop. Your availability now includes ours. That is why the status page is public and why failover behaviour is documented rather than implied.
- Compatibility is the OpenAI protocol, not every provider's private extensions. A parameter that exists only in one vendor's own SDK, with no OpenAI-shaped equivalent, is not reachable by definition.
- A fallback chain cannot be scoped by failure type. A model you list will be attempted on any delivery failure — 5xx, network error, 429 and context-window-exceeded alike. Design the chain knowing that.
- SOC 2 Type II is in progress, not certified. The trust page states the current posture; if you ever see us write "certified" before it is true, that is the sentence to hold us to.
Try it
Create an account at signup, load the $5 minimum (a first purchase is matched with a $10 bonus, so $5 becomes $15 in credits), and point one existing service at https://api.nrouter.ai/v1 with NROUTER_API_KEY. Then do the thing that actually proves the claim: call two different providers from the same client in the same afternoon, and read x-nr-routed-model off both. The quick start is ten minutes end to end, and the chat-completions reference is the full request shape.
See also
- Migrate off OpenRouter: the base-URL swap and what does not map — the same swap when you are coming from another gateway rather than from a provider directly.
- Why we do not do BYOK — the trade that makes one credential possible, argued against itself.
- Cut LLM costs by routing, not by rewriting your app — what to do with breadth once you have it.
- Provider fallback chains: surviving an OpenAI outage — how failover behaves, and why a retry is a second bill.
- Deterministic A/B testing across model variants — how to adopt a new model without shipping a quality regression.
- Cost honesty: we read the number, we do not invent it — why an unknown cost is reported as unpriced rather than as zero.
- The models page — the live catalog, which is authoritative over any list written in prose.
Sources
Verified 2026-08-23. If any linked page has changed since, email hello@nrouter.ai and we will correct this post.
- nRouter plans and fees: nrouter.ai/pricing — $0 subscription with a 4% platform fee on top, Pro at $50/mo or $500/yr at 0%, $5 minimum purchase.
- nRouter live catalog: nrouter.ai/models — the authoritative list of models a key can reach.
- OpenAI API reference: platform.openai.com/docs/api-reference — the request and response shape
https://api.nrouter.ai/v1is compatible with. - OpenAI API pricing: openai.com/api/pricing — published per-model rates.
- Anthropic pricing: anthropic.com/pricing — published per-model rates for the Claude family.
- AWS Bedrock pricing: aws.amazon.com/bedrock/pricing — Bedrock is live on nRouter and AWS publishes its own rates.
- Anthropic Messages API reference: platform.claude.com/docs/en/api/messages — the top-level
systemparameter and theusage.input_tokens/usage.output_tokensshape quoted above, as the concrete example of what a translation layer exists to reconcile. - OpenAI Python SDK — accessing raw response data: github.com/openai/openai-python — the
with_raw_responseaccessor used in the header example.
OpenAI, Anthropic and AWS are trademarks of their respective owners. nRouter is not affiliated with or endorsed by them. All claims above are sourced from their public pricing or documentation on the date shown.


