从 OpenRouter 迁移只需改一行

改一下 base URL,再换成 OrcaRouter 密钥。你的模型、SDK 和其余代码完全不用动——只有 openrouter/ 开头的路由器 ID 需要改名。

需要确认的三件事

  1. 为你的 SDK 选对 base URL — OpenAI SDK 需要 https://api.orcarouter.ai/v1,另外两个只要 https://api.orcarouter.ai —— 它们各自会补上自己的路径。
  2. 换成 OrcaRouter 密钥 — 值要换——OpenRouter 的密钥在这里无法通过认证——但位置不变:你的 SDK 原来用哪个请求头发送,我们就从哪个读取。
  3. 模型名称保持不变 — 我们使用同样的 vendor/model 命名,所以 anthropic/claude-sonnet-4 可直接使用。例外是 OpenRouter 自己的 openrouter/ 路由器 ID,那些需要改名。

改动前后对比:要改的那一行

OrcaRouter 原生支持 OpenAI、Anthropic 和 Gemini 的 API,你可以继续使用现有的 SDK。每段代码中,以 - 开头的行是要删除的,以 + 开头的行是要添加的。

OpenAI — Python

  client = OpenAI(
-     base_url="https://openrouter.ai/api/v1",
+     base_url="https://api.orcarouter.ai/v1",
      api_key=ORCAROUTER_API_KEY,
  )

代码上就改这一处。另外把密钥换成 OrcaRouter 的——你的模型名、消息和流式输出都不用变,除非你调用的是 openrouter/ 开头的路由器 ID。

Anthropic — Python

  client = Anthropic(
+     base_url="https://api.orcarouter.ai",
      api_key=ORCAROUTER_API_KEY,
  )

我们直接支持 Anthropic 的 API,而 OpenRouter 不支持。如果你此前为了适配 OpenRouter 而用 OpenAI SDK 调用 Claude,现在可以不用了。

Gemini — TypeScript

  const ai = new GoogleGenAI({
    apiKey: ORCAROUTER_API_KEY,
+   httpOptions: { baseUrl: "https://api.orcarouter.ai" },
  });

我们同样直接支持 Gemini 的 API,Google SDK 无需改动即可使用。

各 SDK 的完整示例

包含导入、客户端初始化和一次真实调用。只要环境变量 ORCAROUTER_API_KEY 已设置,这段代码可以直接运行。

OpenAI — Python

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)

OpenAI — TypeScript

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);

OpenAI — cURL

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"}]
  }'

Anthropic — Python

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)

Anthropic — TypeScript

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);

Anthropic — cURL

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"}]
  }'

Gemini — Python

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)

Gemini — TypeScript

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);

Gemini — cURL

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"}]}]
  }'

模型 ID:哪些需要改名

我们使用同样的 vendor/model 命名,所以 anthropic/claude-sonnet-4 可直接使用。例外是 OpenRouter 自己的 openrouter/ 路由器 ID,那些需要改名。

在 OpenRouter 上在 OrcaRouter 上
openrouter/autoorcarouter/auto
openrouter/freeorcarouter/free
其他 openrouter/ 路由器没有对应项——请直接写一个具体模型
任何 vendor/model 形式的 ID,例如 anthropic/claude-sonnet-4同一个 ID,无需改动

计费方面的差异

我们不做的四件事

与其上线后才发现,不如现在就知道。

常见问题

OrcaRouter 能直接替代 OpenRouter 吗?

对大多数集成来说可以。改一下 base URL,再换成 OrcaRouter 密钥;你的 SDK、模型名称、消息和流式输出都保持不变。例外是 OpenRouter 自己的 openrouter/ 路由器 ID 需要改名,以及上面列出的 OrcaRouter 刻意不做的四件事。

每个 SDK 需要哪个 base URL?

OpenAI SDK 需要 https://api.orcarouter.ai/v1,另外两个只要 https://api.orcarouter.ai —— 它们各自会补上自己的路径。

还能继续用我的 OpenRouter API 密钥吗?

值要换——OpenRouter 的密钥在这里无法通过认证——但位置不变:你的 SDK 原来用哪个请求头发送,我们就从哪个读取。

用什么代替 openrouter/auto 和 openrouter/free?

OrcaRouter 的路由器是 orcarouter/ 这一组。其中两个和他们的直接对应:用 orcarouter/auto 代替 openrouter/auto,用 orcarouter/free 代替 openrouter/free——思路一样,我们在请求时为你挑选模型,后者还能让你留在零成本档位。他们其余的路由器在这里没有对应,请直接写一个具体模型。

fallback 路由的用法一样吗?

把 models 和 route 移到 extra_body 里面。其余用法完全一致:按优先级列出模型,我们会依次尝试。最少 2 个模型,最多 5 个。值得认真改。留在顶层我们不会读取,于是你的 fallback 会悄无声息地失效;而在启用了请求体原样转发的部署上,模型会收到这些多余字段,并可能直接拒绝这次调用。

怎么查询某个请求花了多少钱?

从响应头读取 X-Orca-Request-Id,再调用 /v1/generation。返回 501 表示本部署关闭了费用查询。

X-Title 和 HTTP-Referer 还能标识我的应用吗?

发送 X-Title,你的应用在分析数据里就会保留原来的名字,无需任何改动;我们同样会读取 OpenRouter 自己的请求头名称。仅发送 HTTP-Referer 时,只有当其域名在我们已识别的名单中,才会标出你的应用名,所以想稳妥就带上标题请求头。列出这一条,是为了提醒你不要误删。

请求里的 provider 和 transforms 会怎么处理?

这两个字段我们都不使用。普通通道上,它们在请求到达模型之前就被丢弃;配置为原样转发请求体的通道会把它们传下去,严格的上游可能因此拒绝请求。无论哪种情况,去掉它们都是稳妥的做法。

OrcaRouter 提供哪些接口?

你预期的都有,另外还有几个 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。