Migrar desde OpenRouter cuesta una línea

Cambie su base URL y ponga una clave de OrcaRouter. Sus modelos, su SDK y el resto de su código se quedan exactamente como están; lo único que se renombra son los identificadores de router openrouter/.

Tres cosas que comprobar

  1. Use la base URL correcta para su SDK — El SDK de OpenAI espera https://api.orcarouter.ai/v1. Los otros dos esperan https://api.orcarouter.ai: cada uno añade su propia ruta.
  2. Sustituya su clave de API por la de OrcaRouter — El valor cambia — una clave de OpenRouter no se autentica aquí —, pero el lugar no: leemos la misma cabecera que su SDK ya envía.
  3. Mantenga sus nombres de modelo — Usamos los mismos nombres vendor/model, así que anthropic/claude-sonnet-4 funciona tal cual. La excepción son los identificadores de router openrouter/ propios de OpenRouter: esos se renombran.

Antes y después: la línea que cambia

OrcaRouter habla de forma nativa las API de OpenAI, Anthropic y Gemini, así que usted conserva el SDK que ya usa. En cada fragmento, las líneas que empiezan por - son las que se eliminan y las que empiezan por + son las que se añaden.

OpenAI — Python

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

Ese es el único cambio de código. Ponga además una clave de OrcaRouter: sus nombres de modelo, sus mensajes y el streaming se quedan igual, salvo que llame a un identificador de router openrouter/.

Anthropic — Python

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

Hablamos la API de Anthropic de forma nativa, cosa que OpenRouter no hace. Si venía llamando a Claude con el SDK de OpenAI para encajar con OpenRouter, ya no hace falta.

Gemini — TypeScript

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

También hablamos la API de Gemini de forma nativa, así que el SDK de Google funciona sin cambios.

Ejemplos completos para cada SDK

Importaciones, cliente y una llamada real. Se ejecuta tal cual en cuanto ORCAROUTER_API_KEY esté definida en tu entorno.

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

Identificadores de modelo: qué hay que renombrar

Usamos los mismos nombres vendor/model, así que anthropic/claude-sonnet-4 funciona tal cual. La excepción son los identificadores de router openrouter/ propios de OpenRouter: esos se renombran.

En OpenRouterEn OrcaRouter
openrouter/autoorcarouter/auto
openrouter/freeorcarouter/free
Cualquier otro router openrouter/Sin equivalente: indique un modelo en su lugar
Cualquier identificador vendor/model, como anthropic/claude-sonnet-4El mismo identificador, sin cambios

Diferencias de facturación

Cuatro cosas que no hacemos

Mejor saberlo ahora que descubrirlo en producción.

Preguntas frecuentes

¿Puede OrcaRouter sustituir a OpenRouter sin más cambios?

En la mayoría de las integraciones, sí. Cambie la base URL y sustituya su clave por una de OrcaRouter; su SDK, los nombres de modelo, los mensajes y el streaming siguen igual. Las excepciones son los identificadores de router openrouter/ propios de OpenRouter, que se renombran, y las cuatro cosas que OrcaRouter no hace a propósito, enumeradas más arriba.

¿Qué base URL necesita cada SDK?

El SDK de OpenAI espera https://api.orcarouter.ai/v1. Los otros dos esperan https://api.orcarouter.ai: cada uno añade su propia ruta.

¿Puedo seguir usando mi clave de API de OpenRouter?

El valor cambia — una clave de OpenRouter no se autentica aquí —, pero el lugar no: leemos la misma cabecera que su SDK ya envía.

¿Qué sustituye a openrouter/auto y openrouter/free?

Los routers de OrcaRouter son los de orcarouter/. Dos se corresponden directamente con los suyos: use orcarouter/auto en lugar de openrouter/auto, y orcarouter/free en lugar de openrouter/free; la idea es la misma en ambos casos, elegimos un modelo por usted en el momento de la petición, y el segundo le mantiene en el nivel sin coste. Sus demás routers no tienen contrapartida aquí, así que indique un modelo concreto.

¿El enrutado de respaldo funciona igual?

Mueva models y route dentro de extra_body. Todo lo demás es igual: enumere sus modelos por orden de preferencia y los probamos uno tras otro. Al menos 2 modelos, como máximo 5. Merece la pena hacerlo bien. En el nivel superior no los leemos, así que sus respaldos dejan de funcionar en silencio; y en despliegues que reenvían el cuerpo de la petición tal cual, el modelo recibe esos campos de más y puede rechazar la llamada.

¿Cómo consulto lo que costó una petición?

Lee X-Orca-Request-Id de la respuesta y luego llama a /v1/generation. Un 501 significa que las consultas de coste están desactivadas en este despliegue.

¿X-Title y HTTP-Referer siguen identificando mi aplicación?

Envíe X-Title y su aplicación conservará su nombre en sus analíticas sin ningún cambio; también leemos los nombres de cabecera propios de OpenRouter. HTTP-Referer por sí solo únicamente nombra su aplicación si su dominio es uno de los que ya reconocemos, así que envíe una cabecera de título si quiere asegurarse. Esta fila está aquí para que no las quite por error.

¿Qué pasa con provider y transforms en mis peticiones?

No usamos ninguno de los dos. En un canal normal se descartan antes de que la petición llegue al modelo; en un canal configurado para reenviar el cuerpo en bruto se transmiten, y un proveedor estricto puede rechazar la petición. Quitarlos es lo seguro en ambos casos.

¿Qué endpoints ofrece OrcaRouter?

Todo lo que espera, y algunos que OpenRouter no tiene. Disponibles aquí y no en OpenRouter: /v1/messages, /v1beta/models … generateContent, /v1/rerank y /v1/realtime. No disponibles: /v1/fine-tunes, GET /v1/files y /v1/images/variations.

¿Los errores llegan con el mismo formato?

Los errores vuelven con la misma forma que ya maneja. Actúe según el estado HTTP: reintente un 429 cuando enviamos Retry-After, espere y reintente un 5xx salvo 501 — que significa que no servimos esa llamada en absoluto — y trate un 4xx en una llamada de relé como algo que corregir en su petición. La excepción es un 404 de /v1/generation: puede significar simplemente que la petición aún no ha liquidado, así que reinténtelo brevemente. No lea error.type como el origen: orcarouter_api_error siempre es nuestro, pero para algunos fallos propios enviamos deliberadamente el vocabulario del proveedor para que su SDK tome su rama habitual: un límite de tasa que aplicamos nosotros y uno que aplica el modelo dicen ambos rate_limit_error. Cite X-Orca-Request-Id cuando necesite que busquemos una llamada concreta.