OpenRouter Setup & Routing Basics
7 examples to get you from zero to a working OpenRouter call - 5 basic and 2 intermediate.
You will create a key, point an OpenAI-compatible client at OpenRouter, send a chat completion, swap model slugs, and stream a response.
Prerequisites
- Python 3.11+ recommended (TypeScript examples also shown)
- An OpenRouter account and the ability to create API keys at openrouter.ai/keys (verify URL at build)
- Credits on the account or a free-model path for smoke tests (verify free-model limits at build)
- Comfort with environment variables and JSON
python -m venv .venv && source .venv/bin/activate
pip install openai
export OPENROUTER_API_KEY="sk-or-..." # never commit real keysBasic Examples
1. Create an API Key and Store It Safely
- Sign in to OpenRouter.
- Open the keys page and create a named key.
- Optionally set a credit limit on the key (verify UI at build).
- Export the key only in shell, secret manager, or CI secrets - not in git.
- OpenRouter keys can be more powerful than a single-provider key because they unlock many models.
- Treat exposure as a revoke-and-rotate event immediately.
- Prefer one key per environment (dev / staging / prod).
Related: Authenticating and Configuring the OpenRouter Base URL - full client configuration
2. Point the OpenAI Python SDK at OpenRouter
import os
from openai import OpenAI
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.environ["OPENROUTER_API_KEY"],
)
resp = client.chat.completions.create(
model="openai/gpt-4o-mini", # illustrative slug; verify at build
messages=[{"role": "user", "content": "Reply with exactly: openrouter-ok"}],
extra_headers={
"HTTP-Referer": "https://localhost", # optional app attribution
"X-OpenRouter-Title": "setup-basics",
},
)
print(resp.choices[0].message.content)
print("resolved model:", resp.model)- Base URL is the entire migration for many OpenAI-shaped clients.
- Model ids use
provider/modelform, not baregpt-4o-mini. - Optional headers only affect rankings / attribution, not auth.
3. Same Call with curl
curl https://openrouter.ai/api/v1/chat/completions \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-4o-mini",
"messages": [{"role": "user", "content": "Say hi in five words"}]
}'- Proves network, auth, and billing without SDK issues.
- Save the JSON error body when status is not 200; message text is usually specific.
- Use this as a health check in ops runbooks.
4. Swap Models by Changing One String
MODELS = [
"openai/gpt-4o-mini",
"anthropic/claude-sonnet-4.5", # illustrative; verify at build
"openrouter/auto",
]
for model in MODELS:
r = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": "One-sentence definition of an agent."}],
)
print(model, "->", r.model, r.choices[0].message.content[:80])- Same client, different routing outcome.
- Always log the requested slug and the resolved
response.model. openrouter/autolets OpenRouter pick a model per prompt (see auto-router page).
5. Stream the First Tokens
stream = client.chat.completions.create(
model="openai/gpt-4o-mini", # verify at build
messages=[{"role": "user", "content": "Count from 1 to 5 slowly."}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta.content or ""
print(delta, end="", flush=True)
print()- Streaming uses the same base URL and auth.
- Provider differences are largely hidden behind SSE chunks.
- Handle mid-stream errors in real apps (see streaming page).
Intermediate Examples
6. Add a Model Fallback List via extra_body
resp = client.chat.completions.create(
model="anthropic/claude-sonnet-4.5", # primary; verify at build
messages=[{"role": "user", "content": "Name two agent stop conditions."}],
extra_body={
"models": ["openai/gpt-4o-mini", "google/gemini-2.5-flash"], # verify at build
},
)
print("used:", resp.model)
print(resp.choices[0].message.content)- Primary model is tried first; listed models are ordered backups on many failure classes.
- You are billed for the model that ultimately runs.
- Put fallbacks in config, not scattered call sites.
Related: Switching Models by Config, Not Code: A Routing Pattern
7. Prefer Throughput with the :nitro Variant
resp = client.chat.completions.create(
model="meta-llama/llama-3.3-70b-instruct:nitro", # verify slug at build
messages=[{"role": "user", "content": "Summarize provider routing in one line."}],
)
print(resp.choices[0].message.content):nitrois a shortcut for sorting providers by throughput.:flooris the cost-oriented counterpart.- Still log latency and cost; shortcuts are preferences, not guarantees.
Related
- How Model Routing Actually Works Under an OpenRouter Request - full request path
- Calling OpenRouter from Python and TypeScript SDKs - parallel recipes
- Streaming Responses Through OpenRouter - production stream handling
- Troubleshooting Common OpenRouter Setup Errors - first-integration checklist
- OpenRouter Setup & Routing Best Practices - day-one hygiene
Stack versions: Pins from the category manifest (verify at build): OpenRouter (~315+ models, July 2026 pricing/fees); LangGraph 1.0+; CrewAI 1.14+; Microsoft Agent Framework 1.0; Vercel AI SDK 6; Pydantic AI (latest); LlamaIndex (latest); OpenAI Agents SDK (latest + MCP); MCP (Linux Foundation governance); A2A (HTTP+SSE+JSON-RPC 2.0); Solana
@solana/web3.js+@solana/spl-token.