從 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。