Integrations
Any client that speaks the Anthropic Messages, OpenAI Chat Completions or OpenAI Responses API works. Change the base URL, set the key, and use a tier as the model.
Every example reads the key from ROUTERLANE_API_KEY. Leave reasoning and thinking settings at their defaults: the router replaces them per task.
Claude Code
Set these in your shell, then run claude. The [1m] suffix tells Claude Code the context window is 1M tokens; the router ignores it.
export ANTHROPIC_BASE_URL=https://api.routerlane.com
export ANTHROPIC_AUTH_TOKEN=$ROUTERLANE_API_KEY
export ANTHROPIC_MODEL='smart[1m]'
export ANTHROPIC_DEFAULT_OPUS_MODEL='smart[1m]'
export ANTHROPIC_DEFAULT_SONNET_MODEL='normal[1m]'
export ANTHROPIC_DEFAULT_HAIKU_MODEL=fast
claudeTo keep the setup with Claude Code instead, put the same variables under "env" in ~/.claude/settings.json, and keep ANTHROPIC_AUTH_TOKEN in your shell so the key stays out of the file.
{
"env": {
"ANTHROPIC_BASE_URL": "https://api.routerlane.com",
"ANTHROPIC_MODEL": "smart[1m]",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "smart[1m]",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "normal[1m]",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "fast"
}
}Claude Code's background calls use the Haiku slot, so they run on Fast. To run a session as Smart+, start it with ANTHROPIC_MODEL=smart-plus claude.
Codex
Codex uses the Responses API. Add a provider to its config, export ROUTERLANE_API_KEY in the shell that runs Codex, and pick a tier with model or codex -m smart.
model = "normal"
model_provider = "routerlane"
[model_providers.routerlane]
name = "RouterLane"
base_url = "https://api.routerlane.com/v1"
env_key = "ROUTERLANE_API_KEY"
wire_api = "responses"For scripted runs, close stdin: codex exec "run the tests and fix what fails" < /dev/null.
pi
Add RouterLane as a provider in pi's models file, then choose Fast, Normal, Smart or Smart+ in pi's model picker. pi expands $ROUTERLANE_API_KEY from the environment, so the key stays out of the file.
{
"providers": {
"routerlane": {
"baseUrl": "https://api.routerlane.com",
"api": "anthropic-messages",
"apiKey": "$ROUTERLANE_API_KEY",
"models": [
{"id": "fast", "name": "Fast", "reasoning": false, "input": ["text", "image"], "contextWindow": 1048576, "maxTokens": 131072},
{"id": "normal", "name": "Normal", "reasoning": false, "input": ["text", "image"], "contextWindow": 1048576, "maxTokens": 131072},
{"id": "smart", "name": "Smart", "reasoning": false, "input": ["text", "image"], "contextWindow": 1048576, "maxTokens": 131072},
{"id": "smart-plus", "name": "Smart+", "reasoning": false, "input": ["text", "image"], "contextWindow": 1048576, "maxTokens": 131072}
]
}
}
}OpenAI SDK
Point the client at https://api.routerlane.com/v1. Chat Completions and Responses both work.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.routerlane.com/v1",
api_key=os.environ["ROUTERLANE_API_KEY"],
)
# Read the routing decision from the headers
raw = client.chat.completions.with_raw_response.create(
model="normal",
messages=[{"role": "user", "content": "Write a unit test for slugify()."}],
)
print(raw.headers.get("x-router-model"), raw.headers.get("x-router-effort"))
completion = raw.parse()
print(completion.choices[0].message.content)import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.routerlane.com/v1",
apiKey: process.env.ROUTERLANE_API_KEY,
});
// Read the routing decision from the headers
const { data, response } = await client.chat.completions
.create({
model: "normal",
messages: [{ role: "user", content: "Write a unit test for slugify()." }],
})
.withResponse();
console.log(response.headers.get("x-router-model"), response.headers.get("x-router-effort"));
console.log(data.choices[0].message.content);Anthropic SDK
Point the client at https://api.routerlane.com, without /v1.
import os
import anthropic
client = anthropic.Anthropic(
base_url="https://api.routerlane.com",
api_key=os.environ["ROUTERLANE_API_KEY"],
)
with client.messages.stream(
model="smart",
max_tokens=8192,
messages=[{"role": "user", "content": "Design a retry policy for a flaky payment API."}],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
baseURL: "https://api.routerlane.com",
apiKey: process.env.ROUTERLANE_API_KEY,
});
const stream = client.messages.stream({
model: "smart",
max_tokens: 8192,
messages: [{ role: "user", content: "Design a retry policy for a flaky payment API." }],
});
stream.on("text", (text) => process.stdout.write(text));
await stream.finalMessage();Vercel AI SDK
Use the OpenAI-compatible provider.
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
import { generateText } from "ai";
const routerlane = createOpenAICompatible({
name: "routerlane",
baseURL: "https://api.routerlane.com/v1",
apiKey: process.env.ROUTERLANE_API_KEY,
});
const { text } = await generateText({
model: routerlane("normal"),
prompt: "Write a commit message for: rename getUser to fetchUser.",
});
console.log(text);LangChain
Use ChatOpenAI with RouterLane's base URL.
import os
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="smart",
base_url="https://api.routerlane.com/v1",
api_key=os.environ["ROUTERLANE_API_KEY"],
)
print(llm.invoke("Plan a zero-downtime schema migration.").content)curl
curl -i https://api.routerlane.com/v1/messages \
-H "x-api-key: $ROUTERLANE_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{"model": "fast", "max_tokens": 1024, "messages": [{"role": "user", "content": "hello"}]}'-i prints the headers, so you can see the tier, model and effort the router chose.