OpenRouter
OpenRouter aggregates models from many providers behind one API and credential. AISIX adds stable model aliases, caller access controls, rate limits, and usage accounting while keeping the OpenRouter credential at the gateway.
Prerequisites
Before starting, prepare the following:
- One AISIX setup:
- For AISIX Cloud, an environment with an attached gateway and a write-scoped admin token. For On-Premises, follow the AISIX Cloud Quickstart. To request Hybrid Cloud access, contact API7.
- For the open-source AISIX gateway, prepare either a local AISIX installation or the Docker setup from the Open-Source AISIX Gateway Quickstart. Configure the gateway to load a declarative resources file.
- An OpenRouter API key from the OpenRouter keys page. OpenRouter key values begin with
sk-or-. curlandjq.
Configure with AISIX Cloud
Export the AISIX Cloud connection details:
# AISIX_CP is the Admin API base URL; include /api and omit a trailing slash
# The local On-Premises quickstart uses http://localhost:8080/api
export AISIX_CP="YOUR_AISIX_CLOUD_ADMIN_API_URL"
export AISIX_TOKEN="YOUR_ADMIN_TOKEN"
export ENV_ID="YOUR_ENVIRONMENT_ID"
Create a provider key, model alias, and caller API key for the OpenRouter-backed chat-completions route.
Because OpenRouter exposes an OpenAI-compatible API, AISIX connects through the openai adapter and uses the OpenRouter API root as api_base.
Create a Provider Key
Create the provider key that stores the OpenRouter credential and API root:
# Replace with your values
export OPENROUTER_API_KEY="YOUR_PROVIDER_API_KEY"
PROVIDER_KEY_ID=$(curl -sS -X POST "$AISIX_CP/provider_keys" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"display_name": "openrouter-prod",
"provider": "openrouter",
"api_key": "'"${OPENROUTER_API_KEY}"'",
"api_base": "https://openrouter.ai/api/v1",
"allowed_environments": ["'"${ENV_ID}"'"]
}' | jq -r '.provider_key.id')
echo "$PROVIDER_KEY_ID"
❶ provider is openrouter. The AISIX Cloud Admin API derives the adapter from the catalog provider; the adapter field is only accepted on BYO provider keys.
❷ api_key stores the OpenRouter API key. The value is encrypted before storage and never returned by read endpoints. It follows the credential-handling behavior in Provider Keys.
❸ api_base is https://openrouter.ai/api/v1. OpenRouter serves its API under /api on its main host, so the root carries both segments and is not https://openrouter.ai/v1. AISIX appends the endpoint path, for example /chat/completions, to this value.
Always set api_base explicitly for OpenRouter. Unlike most featured catalog providers, OpenRouter has no curated default base URL in AISIX, so an omitted api_base leaves the AISIX Cloud Admin API dependent on synced catalog metadata and the create can fail with 400 INVALID_REQUEST.
The gateway enforces the same rule at request time. When a provider key for a non-OpenAI vendor reaches the gateway with an empty api_base, the OpenAI-family bridge refuses to fall back to the public OpenAI host and returns an upstream configuration error instead. An OpenRouter credential is therefore never sent to api.openai.com.
The command captures the returned provider key ID in PROVIDER_KEY_ID.
Create a Model
OpenRouter model IDs are namespaced. The upstream ID is vendor/model, and the vendor prefix is part of the ID rather than a routing hint. Check the OpenRouter models list for a current ID before creating a model alias.
The naming convention has four forms:
vendor/modelis the base form, for exampleanthropic/claude-sonnet-5,openai/gpt-5.2-pro, ordeepseek/deepseek-v4-pro.- A variant suffix is appended to the slug, for example
:freeor:thinking. - A
~before the vendor resolves to the newest version in a family, for example~anthropic/claude-sonnet-latest. openrouter/autoselects OpenRouter's own Auto Router instead of a named model.
The model alias and upstream model ID are different names. display_name is the AISIX alias that callers put in the request model field, while model_name is the OpenRouter model ID. AISIX forwards model_name to the upstream verbatim, including the / in the vendor prefix. It does not split the ID or strip the vendor segment.
Create the model alias callers will send in requests:
MODEL_ID=$(curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/models" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"display_name": "openrouter-sonnet-prod",
"model_name": "anthropic/claude-sonnet-5",
"provider_key_id": "'"${PROVIDER_KEY_ID}"'"
}' | jq -r '.model.id')
echo "$MODEL_ID"
❶ display_name is the alias callers send in model. Keep it a short flat name. Copying the namespaced upstream ID into the alias makes client code harder to read and hides which alias is in use.
❷ model_name is the OpenRouter model ID, for example anthropic/claude-sonnet-5 or openai/gpt-5.2-pro.
❸ provider_key_id attaches the alias to the OpenRouter provider key.
Create one alias per OpenRouter model you intend to expose. A single OpenRouter provider key can back any number of aliases, which is how one credential fans out to several vendors while each alias keeps its own allowlist entry and rate limits.
Create a Caller API Key
Create the caller API key resource that can access the model alias. The gateway generates the key value; the plaintext is returned once in the create response, so capture it now:
AISIX_API_KEY=$(curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/api_keys" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"display_name": "openrouter-caller",
"allowed_models": ["'"${MODEL_ID}"'"]
}' | jq -r '.plaintext')
echo "$AISIX_API_KEY"
The allowed_models value references the model by its ID, so the key can only access the alias you created. After the write, the configuration projects to attached gateways automatically.
Configure with the Open-Source AISIX Gateway
Export the upstream credential and choose the caller API key that applications will send to the gateway:
export OPENROUTER_API_KEY="YOUR_PROVIDER_API_KEY"
export CALLER_API_KEY="YOUR_CALLER_API_KEY"
Create a complete declarative resources file for this provider:
_format_version: "1"
provider_keys:
- display_name: "openrouter-prod"
provider: "openrouter"
adapter: "openai"
api_key: ${OPENROUTER_API_KEY}
api_base: "https://openrouter.ai/api/v1"
models:
- display_name: "openrouter-sonnet-prod"
provider: "openrouter"
model_name: "anthropic/claude-sonnet-5"
provider_key: "openrouter-prod"
api_keys:
- display_name: "openrouter-caller"
key_env: CALLER_API_KEY
allowed_models:
- "openrouter-sonnet-prod"
If AISIX is installed locally, validate the file before loading it:
aisix validate --resources resources.yaml
After validation, start the gateway with the referenced environment variables in its process environment. Reload an existing gateway only if those variables are already available to the process; otherwise, restart it with the updated environment.
If you use Docker, adapt the validation and startup commands in the Open-Source AISIX Gateway Quickstart. Mount this resources.yaml file and pass every environment variable it references with -e in both commands. After the resources load, prepare the shared verification request below:
export AISIX_API_KEY="$CALLER_API_KEY"
Verify the Provider Connection
Export the AISIX gateway origin:
# The local quickstarts use http://127.0.0.1:3000
export AISIX_PROXY="YOUR_AISIX_GATEWAY_ORIGIN"
Send a chat-completions request through the AISIX proxy:
curl -sS -X POST "$AISIX_PROXY/v1/chat/completions" \
-H "Authorization: Bearer ${AISIX_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "openrouter-sonnet-prod",
"messages": [
{
"role": "user",
"content": "Say hello from OpenRouter."
}
]
}'
The gateway returns an OpenAI-compatible response that echoes the caller-facing alias openrouter-sonnet-prod, not the namespaced upstream ID.
If the request fails, check these OpenRouter-specific causes first:
- A
404from the upstream usually means the vendor prefix is missing or misspelled inmodel_name.claude-sonnet-5is not a valid OpenRouter ID;anthropic/claude-sonnet-5is. - A
401from the upstream usually meansapi_keydoes not hold an OpenRouter key. Keys issued by the model's original vendor are not accepted by OpenRouter. - A connection error to an unexpected host usually means
api_baseis missing the/apisegment.
Pass OpenRouter Routing and Reasoning Controls
AISIX does not strip top-level chat-completions fields it does not model. Unmodeled fields are forwarded to the upstream verbatim, so OpenRouter's own request-level controls reach OpenRouter unchanged.
Two OpenRouter control objects are commonly used through the gateway:
providerselects which upstream vendor serves the request. It accepts fields such asorder,allow_fallbacks, andrequire_parameters. See Provider Routing.reasoningcontrols chain-of-thought behavior withenabled,effort, andmax_tokens, and the top-levelreasoning_effortfield is an alias for the effort setting. See Reasoning Tokens.
The following request pins the serving vendor and disables OpenRouter fallbacks while asking for high reasoning effort:
curl -sS -X POST "$AISIX_PROXY/v1/chat/completions" \
-H "Authorization: Bearer ${AISIX_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "openrouter-sonnet-prod",
"messages": [
{
"role": "user",
"content": "Summarize the CAP theorem in two sentences."
}
],
"provider": {
"order": ["anthropic"],
"allow_fallbacks": false
},
"reasoning": {
"effort": "high"
}
}'
Read Reasoning Output
When a model exposes reasoning text, OpenRouter returns it at message.reasoning on the non-streaming path and delta.reasoning on the streaming path, rather than the reasoning_content field that other OpenAI-compatible upstreams use. Some models do not expose their reasoning text.
AISIX normalizes both into the canonical reasoning_content field, so clients read choices[0].message.reasoning_content and choices[0].delta.reasoning_content regardless of which spelling the upstream used. When an upstream sends both fields, reasoning_content takes precedence.
This normalization is built into the openai adapter for OpenRouter. Do not set a response.reasoning_field override on an OpenRouter provider key. That override exists for upstreams whose reasoning path AISIX does not already recognize.
OpenRouter can also return a structured reasoning_details array that must be replayed unchanged for some multi-turn reasoning and tool-calling flows. The normalized AISIX chat path does not retain this array. Use an OpenRouter-native endpoint through a passthrough route when the application must preserve structured reasoning state.
Provider and reasoning controls are OpenRouter-specific request fields. If you later repoint the alias at another provider, or place it behind a multi-target routing model, AISIX forwards those fields to whichever upstream serves the request, and a non-OpenRouter upstream may ignore or reject fields it does not recognize.
Endpoint Support for OpenRouter Models
An OpenRouter model alias does not reach every proxy route. Several routes gate on the configured provider value rather than on the adapter family.
| Route | OpenRouter support |
|---|---|
/v1/chat/completions, including stream: true | Supported through the openai adapter. |
/v1/completions | Supported for models that accept OpenRouter's legacy prompt-based completions format. |
/v1/responses | Supported through the Responses bridge, which translates the request into the chat adapter path. It does not call OpenRouter's native Responses API, so fields without a chat equivalent are ignored. Use /passthrough/openrouter/responses when native Responses semantics are required. |
/v1/messages | Supported through translation to chat completions, not OpenRouter's native Anthropic Messages API. Fields and response blocks without a chat equivalent do not round-trip. Use /passthrough/openrouter/messages for the native contract. |
/v1/messages/count_tokens | Not available. This AISIX route requires an Anthropic-protocol provider key, while the OpenRouter integration uses the openai adapter. |
/v1/embeddings | Supported when the alias points at an OpenRouter embedding model. AISIX forwards the OpenAI embeddings request shape to https://openrouter.ai/api/v1/embeddings. |
/v1/audio/speech | Supported when the alias points at an OpenRouter speech model because the JSON request and upstream path are compatible. |
/v1/audio/transcriptions and /v1/audio/translations | Not supported through these normalized routes. AISIX accepts OpenAI-style multipart uploads, while OpenRouter's transcription endpoint accepts a JSON input_audio object and OpenRouter does not document a matching translations route. Use /passthrough/openrouter/audio/transcriptions with OpenRouter's native JSON shape. |
/v1/images/generations | Not available. The route accepts only models whose provider value is openai, and OpenRouter's native image endpoint is /images, not /images/generations. Use /passthrough/openrouter/images with the OpenRouter image request. |
/v1/rerank | Not available. The route accepts only the openai, cohere, and jina provider values. Use /passthrough/openrouter/rerank with an OpenRouter rerank model ID for OpenRouter's native route. |
/v1/videos and its status and content routes | Not available. The openrouter provider value returns 501 not_implemented. For OpenRouter's native asynchronous video API, submit through /passthrough/openrouter/videos, then use the returned job ID with /passthrough/openrouter/videos/{jobId} and /passthrough/openrouter/videos/{jobId}/content. |
/v1/files | Do not use the normalized file routes for OpenRouter-native file references. AISIX wraps returned file IDs for its job-routing contract and does not unwrap those IDs inside native OpenRouter Messages or Responses bodies. Use /passthrough/openrouter/files to preserve OpenRouter's raw file IDs. |
/v1/batches and /v1/fine_tuning/jobs | Not available because OpenRouter does not publish matching routes. |
/v1/models | Returns caller-accessible AISIX model aliases, not OpenRouter's model catalog. Use /passthrough/openrouter/models for the native list. |
/passthrough/openrouter/*rest | Available through a configured passthrough route. |
For routes AISIX does not normalize, use a passthrough route. The /passthrough/openrouter paths on this page assume such a route claiming that prefix with https://openrouter.ai/api/v1 as its target_url; grant the route on the caller key's allowed_routes. The gateway appends the remaining path to the route's target_url and removes one leading v1 segment when it duplicates the trailing /v1 of the target, so both /passthrough/openrouter/models and /passthrough/openrouter/v1/models reach https://openrouter.ai/api/v1/models.
A passthrough route forwards the request body without model-alias rewriting. Send the namespaced OpenRouter model ID, such as anthropic/claude-sonnet-5, rather than openrouter-sonnet-prod. The route relays SSE responses incrementally. AISIX detects chat, completions, and Responses envelopes and records supported usage fields. Requests without a recognized carrier field remain opaque: buffered responses record zero tokens, while opaque SSE can still record top-level supported usage fields. Prefer normalized endpoints when their contract is sufficient and you need AISIX token and cost accounting.
Next Steps
You have now connected AISIX to OpenRouter and verified the model alias. Continue with these guides:
- Model Aliases: configure routing, retry behavior, or cost metadata for this alias.
- Routing and Failover: fail over between OpenRouter and a direct vendor account.
- Passthrough Routes: reach OpenRouter routes that AISIX does not normalize.
- Provider Compatibility: review supported proxy endpoints and provider-specific boundaries.