Migrate from OpenRouter to TeamoRouter
Moving from OpenRouter takes three changes: the base URL, the API key, and the model ID (drop the vendor/ prefix). The rest of your OpenAI SDK, Anthropic SDK, Claude Code or Codex setup stays the same.
New accounts start with a $0 balance — top up before your first request. Top up from $5. If a request returns 402 (400 on the OpenAI format) with "wallet balance is insufficient", your balance is empty — your base URL and key are fine. Top up and retry.
No international card? Top up with USDT: click Pay with crypto in the top-up dialog and pay with USDT, USDC or ETH from Binance, OKX or any exchange app — the checkout shows which networks your amount supports (BEP20 works from $5). No wallet extension needed (guide).
1. What to change
| OpenRouter | TeamoRouter | |
|---|---|---|
| Base URL (OpenAI format) | https://openrouter.ai/api/v1 |
https://api.teamorouter.com/v1 |
| Base URL (Anthropic format: Claude Code, Anthropic SDK) | https://openrouter.ai/api |
https://api.teamorouter.com (no /v1) |
| API key | sk-or-v1-... |
sk-teamo-..., created in the dashboard |
| Auth header | Authorization: Bearer <key> |
OpenAI format: Authorization: Bearer <key>; Anthropic format: x-api-key: <key> (Claude Code's ANTHROPIC_AUTH_TOKEN also works) |
| Model ID | vendor/model, e.g. deepseek/deepseek-v4-pro |
No vendor prefix, e.g. deepseek-v4-pro |
2. Model ID mapping
Drop the vendor/ prefix. Claude IDs also swap dots for hyphens: anthropic/claude-opus-5.5 becomes claude-opus-5-5. A vendor-prefixed ID returns 400 model_not_available.
| OpenRouter model ID | TeamoRouter model ID |
|---|---|
anthropic/claude-sonnet-5.5 |
claude-sonnet-5-5 |
anthropic/claude-haiku-5.5 |
claude-haiku-5-5 |
anthropic/claude-opus-5.5 |
claude-opus-5-5 |
anthropic/claude-opus-5 |
claude-opus-5 |
anthropic/claude-fable-5.1 |
claude-fable-5-1 |
anthropic/claude-fable-5 |
claude-fable-5 |
anthropic/claude-sonnet-5 |
claude-sonnet-5 |
anthropic/claude-opus-4.8 |
claude-opus-4-8 |
anthropic/claude-opus-4.7 |
claude-opus-4-7 |
anthropic/claude-sonnet-4.6 |
claude-sonnet-4-6 |
anthropic/claude-opus-4.6 |
claude-opus-4-6 |
anthropic/claude-haiku-4.5 |
claude-haiku-4-5 |
openai/gpt-6.1-terra |
gpt-6.1-terra |
openai/gpt-6.1-sol |
gpt-6.1-sol |
openai/gpt-6-sol |
gpt-6-sol |
openai/gpt-6-luna |
gpt-6-luna |
openai/gpt-6-astra |
gpt-6-astra |
openai/gpt-5.6-sol |
gpt-5.6-sol |
openai/gpt-5.6-terra |
gpt-5.6-terra |
openai/gpt-5.6-luna |
gpt-5.6-luna |
openai/gpt-5.5 |
gpt-5.5 |
openai/gpt-5.4-mini |
gpt-5.4-mini |
openai/gpt-5.4 |
gpt-5.4 |
google/gemini-4-argon |
gemini-4-argon |
google/gemini-3.8-flash |
gemini-3.8-flash |
google/gemini-3.7-flash |
gemini-3.7-flash |
google/gemini-3.6-flash |
gemini-3.6-flash |
google/gemini-3.5-flash |
gemini-3.5-flash |
google/gemini-3.5-flash-lite |
gemini-3.5-flash-lite |
google/gemini-3.1-pro-preview |
gemini-3.1-pro-preview |
| OpenRouter model ID | TeamoRouter model ID |
|---|---|
deepseek/deepseek-v4.1-flash-1017 |
deepseek-flash-1017 |
deepseek/deepseek-v4.1-flash |
deepseek-flash |
deepseek/deepseek-v4-flash-vision-exp |
deepseek-v4-flash-vision-exp |
deepseek/deepseek-v4-pro |
deepseek-v4-pro |
deepseek/deepseek-v4-flash |
deepseek-v4-flash |
moonshotai/kimi-k3.1-pro |
kimi-k3.1-pro |
moonshotai/kimi-k3 |
kimi-k3 |
qwen/qwen3.8-flash |
qwen3.8-flash |
qwen/qwen3.7-max |
qwen3.7-max |
qwen/qwen3.7-flash |
qwen3.7-flash |
z-ai/glm-5.3-flash |
glm-5.3-flash |
z-ai/glm-5.3 |
glm-5.3 |
z-ai/glm-5.2 |
glm-5.2 |
The table lists the main models both services offer, generated from both public model lists on 2026-11-04. For everything else and for live prices, see the model directory or GET /v1/models.
openrouter/autoand~vendor/...-latestaliases have no equivalent. Pick a model ID from the table.- Variant suffixes such as
:nitro,:floor,:onlineand:batcharen't supported. Remove the suffix. Free models are separate IDs ending in-free; they're marked in the model directory. - Claude Code's
[1m]suffix (claude-opus-5-5[1m]) isn't needed. Useclaude-opus-5-5.
3. Headers you can delete
OpenRouter reads HTTP-Referer, X-OpenRouter-Title (formerly X-Title), X-OpenRouter-Categories and X-OpenRouter-App-Visibility only to list your app in its public rankings. TeamoRouter doesn't use them. Delete them when you switch.
4. Code changes
Python (OpenAI SDK)
Before:
from openai import OpenAI
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key="sk-or-v1-xxxxxx",
)
resp = client.chat.completions.create(
model="deepseek/deepseek-v4-pro",
messages=[{"role": "user", "content": "Hello"}],
extra_headers={"HTTP-Referer": "https://example.com", "X-OpenRouter-Title": "My App"},
extra_body={"provider": {"order": ["deepseek"]}},
)
print(resp.choices[0].message.content)
After:
from openai import OpenAI
client = OpenAI(
base_url="https://api.teamorouter.com/v1",
api_key="sk-teamo-xxxxxx",
)
resp = client.chat.completions.create(
model="deepseek-v4-pro",
messages=[{"role": "user", "content": "Hello"}],
)
print(resp.choices[0].message.content)
JavaScript / TypeScript (OpenAI SDK)
Before:
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://openrouter.ai/api/v1",
apiKey: process.env.OPENROUTER_API_KEY,
defaultHeaders: { "HTTP-Referer": "https://example.com", "X-OpenRouter-Title": "My App" },
});
const resp = await client.chat.completions.create({
model: "deepseek/deepseek-v4-pro",
messages: [{ role: "user", content: "Hello" }],
});
After:
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.teamorouter.com/v1",
apiKey: process.env.TEAMOROUTER_API_KEY,
});
const resp = await client.chat.completions.create({
model: "deepseek-v4-pro",
messages: [{ role: "user", content: "Hello" }],
});
Claude models: use the Anthropic format
On OpenRouter you may call Claude through the OpenAI SDK as anthropic/claude-.... Use the Anthropic native protocol (/v1/messages) for Claude models whenever possible. Calling Claude through the OpenAI-compatible format can lose prompt cache, thinking, and other capabilities, increasing cost and reducing quality. It is only suitable for simple chat scenarios.
from anthropic import Anthropic
client = Anthropic(
api_key="sk-teamo-xxxxxx",
base_url="https://api.teamorouter.com",
)
resp = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello"}],
)
print(resp.content[0].text)
Caching has to be enabled by the caller with cache_control. See the FAQ in the API integration guide.
Claude Code
Before:
export ANTHROPIC_BASE_URL="https://openrouter.ai/api"
export ANTHROPIC_AUTH_TOKEN="sk-or-v1-xxxxxx"
export ANTHROPIC_API_KEY=""
export ANTHROPIC_DEFAULT_OPUS_MODEL="~anthropic/claude-opus-latest[1m]"
export CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1
After:
export ANTHROPIC_BASE_URL="https://api.teamorouter.com"
export ANTHROPIC_AUTH_TOKEN="sk-teamo-xxxxxx"
export ANTHROPIC_API_KEY=""
export ANTHROPIC_DEFAULT_OPUS_MODEL="claude-opus-5-5"
- Keep
ANTHROPIC_API_KEYempty, as on OpenRouter. If it's set, Claude Code asks whether to use that key, defaults to No, and pressing Enter takes you to the official Anthropic login. - Change every model variable (
ANTHROPIC_MODEL,ANTHROPIC_DEFAULT_*_MODEL,CLAUDE_CODE_SUBAGENT_MODEL) to a TeamoRouter ID, or delete it. - Delete
CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERYand choose models with the variables above. - If you set these in
.claude/settings.local.jsonunderenv, make the same changes there. Then restartclaude;/statusshould showhttps://api.teamorouter.comas the base URL.
Full steps: Claude Code setup.
Codex
Codex reads ~/.codex/config.toml, not OPENAI_BASE_URL.
Before:
model_provider = "openrouter"
model = "~openai/gpt-sol-latest"
[model_providers.openrouter]
name = "openrouter"
base_url = "https://openrouter.ai/api/v1"
[model_providers.openrouter.auth]
command = "sh"
args = ["-c", "echo $OPENROUTER_API_KEY"]
After:
model_provider = "teamorouter"
model = "gpt-6-sol"
model_reasoning_effort = "high"
[model_providers.teamorouter]
name = "TeamoRouter"
base_url = "https://api.teamorouter.com/v1"
env_key = "OPENAI_API_KEY"
wire_api = "responses"
Then set the key with export OPENAI_API_KEY="sk-teamo-xxxxxx". Codex uses the Responses API, which on TeamoRouter serves GPT models only (Claude and Gemini return 400), so pick a GPT model here. Full steps, including Windows: Codex CLI setup.
5. What TeamoRouter doesn't have
| OpenRouter feature | On TeamoRouter |
|---|---|
Auto Router (openrouter/auto) and ~...-latest aliases |
Not available. Set a specific model ID. |
models fallback list |
Not available. Catch the error in your code and retry with another model. For a given model, TeamoRouter switches between its upstream lines on its own; you can't pick one. |
provider preferences (order, only, ignore, sort, allow_fallbacks, data_collection, zdr, max_price, quantizations) |
Not available. Delete the provider field. |
Variant suffixes (:nitro, :floor, :online, :batch) |
Not available. Remove the suffix. |
plugins (web search, file parsing) and transforms |
Not available. Delete these fields. |
Cost in the response (usage.cost) |
Responses carry token counts in usage. Per-request charges are in the dashboard. |
/api/v1/credits, /api/v1/key, /api/v1/generation |
No public equivalent. Check balance and usage in the dashboard. |
| Bring your own provider key (BYOK) | Not available. |
| Responses API for every model | /v1/responses serves GPT models only. Use /v1/messages for Claude and the Gemini native format for Gemini. |
6. Check the switch
curl https://api.teamorouter.com/v1/chat/completions \
-H "Authorization: Bearer sk-teamo-xxxxxx" \
-H "Content-Type: application/json" \
-d '{"model":"deepseek-v4-pro","messages":[{"role":"user","content":"Hello"}]}'
- 401: the key is wrong. It should start with
sk-teamo-, notsk-or-. - 402 (400 on the OpenAI format) with "wallet balance is insufficient": the balance is $0. Top up and retry.
- 400
model_not_available: the model ID still has avendor/prefix or isn't in our catalog. Check the table above.
More error codes and limits: API integration guide and Rate limits.