改一下 base URL,再换成 OrcaRouter 密钥。你的模型、SDK 和其余代码完全不用动——只有 openrouter/ 开头的路由器 ID 需要改名。
OrcaRouter 原生支持 OpenAI、Anthropic 和 Gemini 的 API,你可以继续使用现有的 SDK。每段代码中,以 - 开头的行是要删除的,以 + 开头的行是要添加的。
client = OpenAI(
- base_url="https://openrouter.ai/api/v1",
+ base_url="https://api.orcarouter.ai/v1",
api_key=ORCAROUTER_API_KEY,
)代码上就改这一处。另外把密钥换成 OrcaRouter 的——你的模型名、消息和流式输出都不用变,除非你调用的是 openrouter/ 开头的路由器 ID。
client = Anthropic(
+ base_url="https://api.orcarouter.ai",
api_key=ORCAROUTER_API_KEY,
)我们直接支持 Anthropic 的 API,而 OpenRouter 不支持。如果你此前为了适配 OpenRouter 而用 OpenAI SDK 调用 Claude,现在可以不用了。
const ai = new GoogleGenAI({
apiKey: ORCAROUTER_API_KEY,
+ httpOptions: { baseUrl: "https://api.orcarouter.ai" },
});我们同样直接支持 Gemini 的 API,Google SDK 无需改动即可使用。
包含导入、客户端初始化和一次真实调用。只要环境变量 ORCAROUTER_API_KEY 已设置,这段代码可以直接运行。
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.orcarouter.ai/v1",
api_key=os.environ["ORCAROUTER_API_KEY"],
)
response = client.chat.completions.create(
model="anthropic/claude-sonnet-4",
messages=[{"role": "user", "content": "Hello"}],
)
print(response.choices[0].message.content)import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.orcarouter.ai/v1",
apiKey: process.env.ORCAROUTER_API_KEY,
});
const response = await client.chat.completions.create({
model: "anthropic/claude-sonnet-4",
messages: [{ role: "user", content: "Hello" }],
});
console.log(response.choices[0].message.content);curl https://api.orcarouter.ai/v1/chat/completions \
-H "Authorization: Bearer $ORCAROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-sonnet-4",
"messages": [{"role": "user", "content": "Hello"}]
}'import os
from anthropic import Anthropic
client = Anthropic(
base_url="https://api.orcarouter.ai",
api_key=os.environ["ORCAROUTER_API_KEY"],
)
message = client.messages.create(
model="anthropic/claude-sonnet-4",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello"}],
)
print(message.content[0].text)import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
baseURL: "https://api.orcarouter.ai",
apiKey: process.env.ORCAROUTER_API_KEY,
});
const message = await client.messages.create({
model: "anthropic/claude-sonnet-4",
max_tokens: 1024,
messages: [{ role: "user", content: "Hello" }],
});
console.log(message.content[0].text);curl https://api.orcarouter.ai/v1/messages \
-H "x-api-key: $ORCAROUTER_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-sonnet-4",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Hello"}]
}'import os
from google import genai
client = genai.Client(
api_key=os.environ["ORCAROUTER_API_KEY"],
http_options={"base_url": "https://api.orcarouter.ai"},
)
response = client.models.generate_content(
model="google/gemini-2.5-pro",
contents="Hello",
)
print(response.text)import { GoogleGenAI } from "@google/genai";
const ai = new GoogleGenAI({
apiKey: process.env.ORCAROUTER_API_KEY,
httpOptions: { baseUrl: "https://api.orcarouter.ai" },
});
const response = await ai.models.generateContent({
model: "google/gemini-2.5-pro",
contents: "Hello",
});
console.log(response.text);curl "https://api.orcarouter.ai/v1beta/models/google/gemini-2.5-pro:generateContent" \
-H "x-goog-api-key: $ORCAROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [{"parts": [{"text": "Hello"}]}]
}'我们使用同样的 vendor/model 命名,所以 anthropic/claude-sonnet-4 可直接使用。例外是 OpenRouter 自己的 openrouter/ 路由器 ID,那些需要改名。
| 在 OpenRouter 上 | 在 OrcaRouter 上 |
|---|---|
openrouter/auto | orcarouter/auto |
openrouter/free | orcarouter/free |
| 其他 openrouter/ 路由器 | 没有对应项——请直接写一个具体模型 |
| 任何 vendor/model 形式的 ID,例如 anthropic/claude-sonnet-4 | 同一个 ID,无需改动 |
与其上线后才发现,不如现在就知道。
对大多数集成来说可以。改一下 base URL,再换成 OrcaRouter 密钥;你的 SDK、模型名称、消息和流式输出都保持不变。例外是 OpenRouter 自己的 openrouter/ 路由器 ID 需要改名,以及上面列出的 OrcaRouter 刻意不做的四件事。
OpenAI SDK 需要 https://api.orcarouter.ai/v1,另外两个只要 https://api.orcarouter.ai —— 它们各自会补上自己的路径。
值要换——OpenRouter 的密钥在这里无法通过认证——但位置不变:你的 SDK 原来用哪个请求头发送,我们就从哪个读取。
OrcaRouter 的路由器是 orcarouter/ 这一组。其中两个和他们的直接对应:用 orcarouter/auto 代替 openrouter/auto,用 orcarouter/free 代替 openrouter/free——思路一样,我们在请求时为你挑选模型,后者还能让你留在零成本档位。他们其余的路由器在这里没有对应,请直接写一个具体模型。
把 models 和 route 移到 extra_body 里面。其余用法完全一致:按优先级列出模型,我们会依次尝试。最少 2 个模型,最多 5 个。值得认真改。留在顶层我们不会读取,于是你的 fallback 会悄无声息地失效;而在启用了请求体原样转发的部署上,模型会收到这些多余字段,并可能直接拒绝这次调用。
从响应头读取 X-Orca-Request-Id,再调用 /v1/generation。返回 501 表示本部署关闭了费用查询。
发送 X-Title,你的应用在分析数据里就会保留原来的名字,无需任何改动;我们同样会读取 OpenRouter 自己的请求头名称。仅发送 HTTP-Referer 时,只有当其域名在我们已识别的名单中,才会标出你的应用名,所以想稳妥就带上标题请求头。列出这一条,是为了提醒你不要误删。
这两个字段我们都不使用。普通通道上,它们在请求到达模型之前就被丢弃;配置为原样转发请求体的通道会把它们传下去,严格的上游可能因此拒绝请求。无论哪种情况,去掉它们都是稳妥的做法。
你预期的都有,另外还有几个 OpenRouter 没有的。这里有而 OpenRouter 没有的:/v1/messages、/v1beta/models … generateContent、/v1/rerank 和 /v1/realtime。不提供的:/v1/fine-tunes、GET /v1/files 和 /v1/images/variations。
错误的返回形状和你现在处理的一样。按 HTTP 状态码来处理:带 Retry-After 的 429 可以重试;5xx 退避后重试,但 501 例外——它表示这个调用我们根本不提供;中继调用返回 4xx 则应当去改你的请求。例外是 /v1/generation 的 404:它可能只是这笔请求还没结算完,可以短暂重试几次。不要把 error.type 当作来源判断:orcarouter_api_error 一定是我们这边的,但我们会刻意用服务商自己的说法来标注我们自己的某些故障,好让你的 SDK 走它原本的分支——我们施加的限流和模型施加的限流都写作 rate_limit_error。需要我们查某一次调用时,请附上 X-Orca-Request-Id。