OpenRouter provider routing guide — provider selection, fallbacks and response validation
In OpenRouter, provider.order is a priority list, not an allowlist. How order, only and allow_fallbacks differ, and what restricting providers costs.
On this page
Even when you pick a single model on OpenRouter, the provider that serves the request can vary. For the case where a model name itself starts pointing to a different version, see our separate DeepSeek V4.1 Flash migration guide. In the official docs, provider.order is a priority order, and with the default allow_fallbacks: true, a request can also move on to other eligible providers outside the list. Before you go to production, decide not only which model to use but also how far requests are allowed to fall back. [1]
1. Executive summary
OpenRouter is a platform that connects many models and model-hosting services behind a single API. A provider is the service that actually runs the model, and routing is the process of choosing which model and provider a request goes to. One model can have several providers, and supported features and terms of use can differ from provider to provider. [1]
When we checked on 2026-09-12 (Korea Standard Time, UTC+9), the Hacker News (HN) post about an operator's experience with OpenRouter had 663 points and 182 comments. We chose the topic on that signal of interest; it is not a ranking of overall user demand. This guide compares the official docs with an operator's first-hand account; it is not our own experiment on provider performance. [6]
2. Why you need to tell models and providers apart
So you want to use OpenRouter?, published on September 7, records the provider-specific problems with image handling, tool calls and empty responses that the operator of the AI assistant Olly ran into. It also describes how a setup restricted to a few providers lost availability when some routes disappeared or ran into rate limits. These are observations from that operator's own service, not evidence of the current state of every provider. [5]
There is no need to generalize that experience into a defect rate for the product as a whole today. The official docs alone show why developers need to check model and provider separately. OpenRouter supports choosing providers per model, lets you target a provider's regional or special execution routes with separate identifiers, and can filter candidates by whether they support a parameter. [1]
| Layer | What it decides | What is easy to confuse |
|---|---|---|
| Model selection | The model ID to request | The same model ID does not mean a single serving provider |
| Provider selection | The service and execution route that runs the model | A priority order is not an allowlist |
| Model fallback | Other models to try if the first model returns an error | Separate from switching providers for the same model |
| Application validation | Whether the result lets the next step of the task proceed | HTTP success and task success are judged separately |
A fallback is an attempt at an alternative route when the original one is unavailable. OpenRouter's models array tries other models in order. The official docs say the model that was finally used is returned in the response's model field and the request is billed for that model. The provider settings in this report are a separate set of rules for choosing providers. [2]
3. A priority order is not an allowlist
The field names below are as they appear in the JSON body of a Chat Completions request; SDKs may spell them differently. Everything happens within the candidates that actually serve the model and pass your account and request filters. None of these settings makes a service outside that candidate list available. [1]
| Setting | Role in the official docs | Operational reading |
|---|---|---|
provider.order | Tries the listed providers first, in order | With default settings, other eligible providers can also become fallback providers |
provider.allow_fallbacks | Default true. false blocks moving on to providers outside the list | If you set an order, do not read false as also turning off attempts at the next provider within that order |
provider.only | The providers allowed for the request | Applied together with the account's allowlist. A provider must satisfy both |
provider.ignore | The providers excluded for the request | Combined with the account's exclusion list |
Listing the same two providers can give different results
A, B and C in the next table are hypothetical providers for illustration, not real API identifiers. Assume all three serve the chosen model and pass every other filter. The examples do not configure switching to other models through models.
| Setting | If A fails and then B fails too | What the choice means |
|---|---|---|
order: [A, B], default fallbacks | C can become an eligible fallback | Sets a priority but keeps fallback routes wide |
order: [A, B], allow_fallbacks: false | Does not move on to C | Tries A and B in order only, and accepts an error if both fail |
only: [A, B] and order: [A, B] | C is outside what is allowed | States the allowed scope and the priority order separately |
The official docs say that if no provider satisfies both the account allowlist and the request's only list, the request fails with HTTP 404. So when you get a 404, do not just look for a typo in the URL; also check the model's provider list against the combination of account and request filters. [1]
A provider slug is the string you put in routing settings. A base slug can cover several execution routes within the same provider that differ by region or processing mode. To target a specific region or variant, copy the exact full slug from the model's detail page. Routes split by service tier, such as priority and flex processing, also have their own selection rules. So listing one company name does not mean you have pinned requests to a single execution route. [1]
4. Where parameter and data policies apply
The default for provider.require_parameters is false. The official docs say that providers that do not support some parameters can still receive the request, and that parameters a provider does not support may be ignored. Setting it to true limits candidates to providers that support every parameter in the request. This is a rule for choosing providers by what they support; it does not guarantee that the results are accurate. [1]
Even at the default, tools, response_format and verbosity have a built-in filter based on support. If the model has providers that support them, only those providers remain as candidates. But if none of the model's providers supports the item, the docs say the request can be sent anyway with the item ignored, instead of the model being dropped from the candidates. For features that must be applied, require them explicitly instead of relying on the default preference rule alone. [1]
| Requirement | Setting to check | What still needs checking |
|---|---|---|
| Support for request parameters | require_parameters: true | Whether the actual response format and tool arguments meet the task's conditions |
| Restricting providers by data collection policy | data_collection: "deny" | The provider policies on the model detail page and the terms of each execution route |
| Restricting to zero data retention (ZDR) routes | zdr: true | The policies of plugins, external tools and your application's logs |
ZDR (Zero Data Retention) is a policy under which the provider does not retain data. OpenRouter's ZDR filter restricts selection to model inference routes that have this policy. However, the official docs state explicitly that the filter does not apply to plugins and tools such as web search. They also say in-memory prompt caching is not treated as retention and is therefore allowed. So do not treat zdr: true as a switch that removes logs, caches and tools across your whole system. [3]
A no-training policy is also not the same as a no-retention policy. The OpenRouter docs distinguish routes that do not train on data but do retain it for reasons such as abuse detection. zdr: false in a request does not turn off ZDR that is enabled in account settings or administrative rules. If either side requires it, the restriction applies. [3]
5. How to check the actual route and response
After reviewing the configuration, check what actually happened. The official Router Metadata doc says you can receive routing information by sending the request header X-OpenRouter-Metadata: enabled. The openrouter_metadata field in the response shows the requested model, the candidate providers, the selected provider and details of each attempt. [4]
| Field | Meaning in the docs | What to watch in production |
|---|---|---|
requested | The model identifier the client sent | Compare it with the actual model in the response |
endpoints | The candidates considered, and whether each was selected | Whether the provider you expected was selected |
attempt | In a successful response, the number of the attempt that succeeded | If it is greater than 1, check whether earlier attempts failed and the request fell back |
attempts | On fallback, a record of provider, model and status. An optional field | When present, log it along with the earlier failed routes |
The metadata is not present in every response. The docs say the field is stripped when a cached response is replayed, so that stale routing information is not exposed. It can also be missing for some errors that occur before the request reaches the router, and for internal errors. In streaming responses it arrives in the final chunk, so if you read only the first part and close the connection, you may never see it. Do not assume that missing metadata means no fallback occurred. [4]
Separately from the routing record, your application needs its own conditions for a valid result. The operator's post describes cases where the response was HTTP 200 but had nothing to show the user. Rather than turning that into a general failure rate, we suggest setting success conditions that fit your own task, as follows. [5]
- For a call that answers a user, check that the expected answer is there. With streaming, judge only after assembling everything up to the final result.
- In a tool-calling step, an empty body can be normal if there is a valid tool call. Check the tool name and the argument format before executing it.
- If you need structured output, check not just the JSON syntax but also the required fields and business rules.
- Even if the result is incomplete, do not blindly rerun external tool actions. Distinguish between re-requesting a model response and external actions that may already have run.
Preventing duplicate execution of external actions is covered in our report on agent retry design. This report focuses on confirming which response came back over which route.
6. Pre-production checklist
Below is the order of checks our editors derived from the official rules and the operator's account. It is not a procedure for ranking new models by performance; it is a procedure for confirming that actual behavior matches the scope you decided to allow.
- Write the model list and the provider list separately. Record the model IDs you use, the actual providers, and whether you require a specific region or variant route.
- Make the priority order and the allowed scope explicit. Check whether you have only
order, or whether you needonlyor a fallback restriction. Look at how this combines with your account-wide settings too. - Define required features and data conditions. Express non-negotiable conditions such as tool calling, structured output and ZDR as filters, and confirm that some candidates still meet them.
- Test the case where even the last allowed route fails. Use harmless test requests or mock responses to check error handling, queuing and alerting. Make sure unreviewed routes are not added automatically.
- Run comparisons from the same location as production. Match the network location and tool configuration, and check normal tasks, empty responses and tool-argument errors together. Do not judge stability from a request that succeeded once.
- Log the final model, selected provider, number of attempts and result validity together. Record missing metadata as a separate state, and do not copy raw inputs or credentials into logs unnecessarily.
provider settings of one current request and explain which providers it can go to if the first provider fails. Once you check whether the settings match the actual routing record, the scope you should restrict next becomes concrete.7. What this is not yet
- We did not measure per-provider performance ourselves. The operator's experience is a record about that service, that time and those models. We did not turn the numbers in that post into a current provider ranking or a general failure rate.
- We keep the docs' description of features separate from how an actual account behaves. We checked the official docs on 2026-09-12 but made no paid API calls and changed no account settings. Candidate providers and supported features can change.
- We did not calculate how much availability improves. We described the structural relationship that more restriction leaves fewer fallback candidates; we give no figures for improvements in failure probability or response latency.
- This report does not treat ZDR as a retention guarantee for the whole system. It describes OpenRouter's policy categories and where they apply. Plugins, external tools and your own logs need to be checked separately.
- A successful HTTP status alone does not decide task success. Some valid responses contain only a tool call, so we do not make an empty body the failure condition for every task.
- The interest signal is a limited observation. We looked at the HN response and at visibility in Korean search results; we did not confirm overall user search volume or that this was the top topic of interest in Korea.
8. Sources
| Source | What we checked | Type and date |
|---|---|---|
| [1] Provider Routing | order, only, ignore and fallbacks; slugs; parameter and data filters | OpenRouter official docs · checked 2026-09-12 |
| [2] Model Fallbacks | Switching between models; the response's model field and billing | Official docs · checked 2026-09-12 |
| [3] Zero Data Retention | Scope, exclusion of plugins and tools, in-memory caching, account settings | Official docs · checked 2026-09-12 |
| [4] Router Metadata | Request header, response fields, and the exceptions for caching, errors and streaming | Official docs · checked 2026-09-12 |
| [5] So you want to use OpenRouter? | The Olly operator's provider-specific problems and outage experience with restricted routes | Operator's first-hand account · published 2026-09-07 |
| [6] HN discussion | 663 points and 182 comments when we chose the topic | Community response · observed 2026-09-12 (KST) |
Product behavior is attributed to the official docs, and the operating case to its author. The hypothetical-provider examples and the checklist are our editors' explanations and suggestions, not results of our own performance measurements.