Python integration guide
OpenRouter Python quickstart: OpenAI SDK, base URL, and first request
To call OpenRouter with the OpenAI Python SDK, install openai, set OPENROUTER_API_KEY, and use base_url="https://openrouter.ai/api/v1". Choose an exact chat model ID from OpenRouter’s current catalog, then call client.chat.completions.create. The SDK appends /chat/completions; attribution headers are optional. The native openrouter package is a separate option for OpenRouter-specific resources.
Last reviewed 2026-09-27 · Editorial review: KeepRouter Editorial
Run the first request with the OpenAI Python SDK
- Install the package in the Python environment that will run the script:
python -m pip install openai. - Set
OPENROUTER_API_KEYin that process's environment or deployment secret store. Use an OpenRouter key, not a key issued by another gateway. Do not print it. - Choose a chat model from the OpenRouter catalog and set
OPENROUTER_MODELto its exact ID. Check that model's price and account access before running the request. - Save the following as
openrouter_test.pyand runpython openrouter_test.pyin the same environment.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.environ["OPENROUTER_API_KEY"],
timeout=30.0,
max_retries=0,
)
response = client.chat.completions.create(
model=os.environ["OPENROUTER_MODEL"],
messages=[{"role": "user", "content": "Return only the word ready"}],
max_tokens=64,
)
print(response.choices[0].message.content)
print(response.usage.model_dump() if response.usage else "usage missing")The first test disables automatic SDK retries and limits the response to 64 output tokens, so one script run does not silently become several attempts. It can incur a charge at the selected model's rate. A local KeyError means the Python process cannot read a required environment variable; it is not an API authentication response. Check the variable name and the environment used by your terminal, container, or deployment without printing its value.
OpenRouter documents HTTP-Referer and X-OpenRouter-Title as optional app-attribution headers. The minimal example omits them. Add them through extra_headers only when you want to identify your app, and never put an API secret in their values.
When to use the native OpenRouter SDK
| Python option | Install | Client and method | Use it when |
|---|---|---|---|
| OpenAI Python SDK | python -m pip install openai | OpenAI(base_url=...).chat.completions.create(...) | You already use OpenAI-shaped chat requests |
| Native OpenRouter SDK | python -m pip install openrouter | OpenRouter(...).chat.send(...) | You want typed OpenRouter-specific resources |
| Raw HTTP | Your HTTP client | POST /api/v1/chat/completions | You want to manage request and response handling directly |
The native package has a different client and method. After installing openrouter, reuse the same environment variables:
import os
from openrouter import OpenRouter
with OpenRouter(api_key=os.environ["OPENROUTER_API_KEY"]) as client:
response = client.chat.send(
model=os.environ["OPENROUTER_MODEL"],
messages=[{"role": "user", "content": "Return only the word ready"}],
max_tokens=64,
stream=False,
)
print(response)Pin the package version you test. The native SDK's resource methods are not interchangeable with the OpenAI SDK, and the first text response does not validate async, streaming, tool calls, or error handling.
How the final URL is formed
| Part | Value |
|---|---|
| SDK base URL | https://openrouter.ai/api/v1 |
| Chat operation appended by the SDK | /chat/completions |
| Final request URL | https://openrouter.ai/api/v1/chat/completions |
If the base URL is missing /api/v1, the SDK calls a route that is not the documented API surface. If application code appends /chat/completions itself and the SDK appends it again, the path is duplicated. Log the host and path without the credential when diagnosing a 404.
OpenRouter-specific fields do not migrate automatically
OpenRouter can accept provider preferences, fallback model lists, routing variants, attribution headers, and other extensions. With the OpenAI SDK, some are passed through extra_body or extra_headers. Those fields are not part of a generic OpenAI-compatible contract.
| Field or behavior | Portable across compatible gateways? | Migration action |
|---|---|---|
messages, basic chat roles | Often, for an implemented chat route | Replay a representative request |
| Base URL and API key | No | Replace both |
| Model slug | No | Map to the target catalog's exact ID |
| Provider order, only, ZDR, route sorting | No | Remove or rebuild from the target product's public controls |
| OpenRouter attribution headers | No | Remove unless the target documents them |
| Streaming and tools | Syntax may match, behavior may differ | Test event order, arguments, continuation, errors, and cancellation |
Minimal migration to KeepRouter
Check your credential-free configuration with the browser-local migration checker, then download the Python and Node starter pack. Start with dry-run; live compatibility requires testing your exact route and workload.
KeepRouter does not support the native openrouter package as its client contract. Keep the OpenAI SDK path and change the base URL, credential, and model to a compatible entry from the live KeepRouter catalog. Set KEEPROUTER_MODEL to that ID and KEEPROUTER_KEY to a KeepRouter key that permits it; paid models also require sufficient credit:
import os
from openai import OpenAI
client = OpenAI(
base_url="https://keeprouter.com/v1",
api_key=os.environ["KEEPROUTER_KEY"],
timeout=30.0,
max_retries=0,
)
response = client.chat.completions.create(
model=os.environ["KEEPROUTER_MODEL"],
messages=[{"role": "user", "content": "Return only the word ready"}],
max_tokens=64,
)
print(response.choices[0].message.content)Remove OpenRouter-only extra_body and attribution headers unless a target API explicitly documents an equivalent. Confirm that the selected KeepRouter model supports Chat Completions. Current model availability and prices belong to /models, not this tutorial. The OpenAI SDK base URL guide covers Python and Node troubleshooting on the KeepRouter side.
Before moving paid traffic, use the migration checklist to compare one fixed workload. The API cost calculator estimates usage at current KeepRouter catalog rates; calculate the OpenRouter baseline separately from its own rates and billed usage. Follow the free-to-paid key setup when your existing key only permits free models.
Diagnose common failures
| Symptom | Check first |
|---|---|
| 401 or authentication error | Environment variable exists, key has no quotes or whitespace, and the request reaches the intended host |
| 404 | Base URL includes exactly /api/v1 for OpenRouter and the operation path is not duplicated |
| Model not found | Use a current OpenRouter model slug or a current target-gateway ID; namespaces are not shared |
| Request works without provider rules but fails with them | Eligible provider set, data policy, ZDR, maximum price, and fallback constraints |
| Stream stops after a tool call | Tool-result continuation, event parsing, model support, and SDK version |
| Migration compiles but output changes | Model revision, route, system prompt, tool schema, sampling settings, and fallback path |
Production check
Run a deterministic non-streaming request, then streaming, then one real tool round trip. Record the returned model or route evidence, token usage, error body, and billed amount. Keep retry attempts bounded and do not automatically replay requests that can trigger external side effects.
Frequently asked questions
Is there an official OpenRouter Python SDK?
Yes. The current package is named openrouter and its typed client includes synchronous and asynchronous resources. OpenRouter also documents the OpenAI Python SDK as a separate integration.
What is the OpenRouter base URL for the OpenAI SDK?
Use https://openrouter.ai/api/v1. The OpenAI SDK appends the operation path, such as /chat/completions.
Are HTTP-Referer and X-OpenRouter-Title required?
No. OpenRouter's quickstart marks them as optional attribution headers. Never place an API secret in either value.
Can the native OpenRouter SDK call KeepRouter?
It is not a KeepRouter client contract. Use an OpenAI-compatible client or a route-specific HTTP client and follow KeepRouter's published endpoint for the selected model.
Why does a model work in one gateway but not another?
Catalog namespaces, model revisions, eligible providers, endpoint support, policy filters, and account access are product-specific. Map the exact ID and route instead of copying a slug.
Sources reviewed
Sources last reviewed 2026-09-23
- [1] OpenRouter quickstart and client SDK examples
- [2] OpenRouter Python SDK
- [3] OpenRouter OpenAI SDK integration
- [4] OpenRouter provider routing
- [5] OpenAI Python SDK
- [6] KeepRouter OpenAPI
Related guides
- api cost calculator
- OpenRouter to KeepRouter migration: map URLs, model IDs and routing fields
- KeepRouter API key setup: from the free model to a controlled paid request
- openai sdk
- What is an OpenAI-compatible API?
- KeepRouter vs OpenRouter
- Vercel AI Gateway vs OpenRouter
- OpenAI-compatible API migration checklist
- errors
- models