OpenRouter's EU route from configuration
OpenRouter serves the same account on two endpoints: https://openrouter.ai/api/v1 (global) and
https://eu.openrouter.ai/api/v1, where requests are decrypted and served in the EU only and a
model with no EU provider answers 404. The key is account-level, so the EU endpoint is a second
route to the same account, never a second account.
What the configuration says
The OpenAI provider module registers an OpenRouterEU catalog source next to OpenRouter. It is
configured like the OpenRouter section:
| Key | Meaning |
|---|---|
OpenRouterEU:Models:N |
The model ids to seed under Provider/OpenRouterEU |
OpenRouterEU:Endpoint |
An override of the EU default https://eu.openrouter.ai/api/v1 |
There is no OpenRouterEU:ApiKey. The seeded Provider/OpenRouterEU node carries
credentialFrom: Provider/OpenRouter and no key: the resolver follows that reference one hop, root
catalog only, to whatever key the instance binds on Provider/OpenRouter (vault-seeded or set in
Settings → Models). There is one key to rotate.
The route ranks at Order 7, after the global route's 6, so a bare wire id both routes carry keeps
resolving where it did; a tier that means the EU node names it by path (below). There is no
OpenRouterEU:Order and no Features:Ai:Providers:OpenRouterEU switch: providers are gated by
their MODULE being loaded, and nothing reads a per-provider feature flag.
On a Hosting record the same keys come from the ai.openRouterEU block (models, endpoint),
rendered to OpenRouterEU__Models__N and OpenRouterEU__Endpoint (an order or enabled on that
block renders nothing);
ai.requiredDataResidency renders AI__RequiredDataResidency, and each section's
dataResidency / dataRetention renders {Section}__DataResidency / __DataRetention.
Two ways a route differs from an ordinary source
A route is a LanguageModelCatalogSource with CredentialFrom set.
- It is seeded only where it is configured —
OpenRouterEU:ModelsorOpenRouterEU:Endpointset. An ordinary source always seeds its provider node so an admin can add a key later; a route has no key of its own to wait for, so an unconfigured one would be an empty duplicate of the account on every instance. - Its model ids are de-duplicated within the route only. The catalog otherwise lets the first
source win a shared wire id. For a route the shared id is the point:
z-ai/glm-5.3exists asProvider/OpenRouter/z-ai/glm-5.3ANDProvider/OpenRouterEU/z-ai/glm-5.3, told apart by node path.
Naming an EU model in a tier
With the same wire id on both routes, a bare id does not say which endpoint is meant. A tier
(ModelTier:Heavy, i.e. the record's ai.tiers.heavy) may therefore name the model by node path:
ModelTier__Heavy = Provider/OpenRouterEU/z-ai/glm-5.3
Tier resolution matches the configured value against each candidate's node path first, then its wire id, and answers the matched candidate's selection: the path when the id is shared, the bare id when it is not. A bare shared id is answered with the path of the lowest-ranked node carrying it (order, then path), never with the ambiguous id.
A route's model never falls back to the global route
A node path selects one node, and its credential is that node's bound provider. When the exact
node yields no key, a node that pins nothing may fall through to the same-id walk (the keyless
catalog entry against a user's keyed copy). A node on a route may not: the same id on the other
route is the same model on a DIFFERENT endpoint, so falling through would send an EU selection to
the global endpoint with the global key and nothing to say so. A route's node resolves through its
reference or not at all. OpenRouterEURouteMeshTest.ARouteWhoseReferencedKeyIsMissing_FailsClosed_NeverOnTheGlobalRoute
pins it (removing the guard turns it red with the global endpoint).
The OpenRouter prompt-cache policy applies to the route as to any *.openrouter.ai host. The
upstream-routing guard (OpenRouterProviderRoutingPolicy) applies to any node on it that pins
providerRouting — the governed review model does; the config-seeded models pin nothing.
Which Provider/OpenRouterEU wins
Two things can create the node: the governed standard pr.review-provider-eu.create (the PR
steward's setup) and a deployment's OpenRouterEU configuration. Both write the same meaning —
the EU endpoint and credentialFrom: Provider/OpenRouter.
The authored node wins. The static import skips a target whose syncBehavior is not Include,
so the standard creates its node CLAIMED (syncBehavior: ExcludeThisOnly, a CreateNode executor
argument). A deployment that later configures the route then imports the models UNDER the governed
node and leaves the node itself alone. An unclaimed authored node would be overwritten on the next
import whose fingerprint changed; AnUnclaimedAuthoredRouteNode_IsOverwritten_WhichIsWhyTheStandardClaimsIt
shows it.
In the other order, the configuration seeds the node first (claimed the same way, as every seeded provider is), and the standard's create is refused as an existing node — there the standard is not needed.
Recycling after a deploy
The catalog is served from Provider; after the AI module reaches an instance, recycle
Provider/OpenRouterEU (and Provider/OpenRouter when its models changed) so a live activation
re-reads.