Python integration guide
How to use OpenRouter with Python: native SDK and OpenAI SDK
OpenRouter currently offers two straightforward Python paths. Install the native `openrouter` package for typed OpenRouter resources and call `client.chat.send`, or keep the official `openai` package and set `base_url` to `https://openrouter.ai/api/v1`. The second path is easier to migrate between OpenAI-compatible gateways, but OpenRouter-specific provider routing, model fallbacks, headers, and extensions still need product-specific code.
Last reviewed 2026-08-26 · Editorial review: KeepRouter Editorial
Pick the client before copying code
OpenRouter maintains a native Python SDK and documents the OpenAI Python SDK as a separate integration. Both can send a chat request. They are not the same abstraction.
| Python option | Install | Client and method | Use it when |
|---|---|---|---|
| Native OpenRouter SDK | pip install openrouter | OpenRouter(...).chat.send(...) | You want typed OpenRouter resources and plan to use its product-specific APIs |
| OpenAI Python SDK | pip install openai | OpenAI(base_url=...).chat.completions.create(...) | You already have OpenAI-shaped code or want a smaller compatibility boundary |
| Raw HTTP | pip install requests or an existing HTTP client | POST /api/v1/chat/completions | You want explicit request and response ownership without an SDK dependency |
Option 1: native OpenRouter Python SDK
import os
from openrouter import OpenRouter
with OpenRouter(api_key=os.environ["OPENROUTER_API_KEY"]) as client:
response = client.chat.send(
model="openai/gpt-4",
messages=[
{"role": "user", "content": "Return only the word ready"}
],
stream=False,
)
print(response)The official SDK also exposes resources beyond a single chat method. That is useful when the application is intentionally coupled to OpenRouter. Pin an SDK version, review its generated types during upgrades, and test async, streaming, tools, and error objects separately from the first text request.
Option 2: OpenAI Python SDK
import os
from openai import OpenAI
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.environ["OPENROUTER_API_KEY"],
)
response = client.chat.completions.create(
model="openai/gpt-4",
messages=[
{"role": "user", "content": "Return only the word ready"}
],
extra_headers={
"HTTP-Referer": "https://example.com",
"X-OpenRouter-Title": "Example app",
},
)
print(response.choices[0].message.content)The attribution headers are optional in OpenRouter's quickstart. Do not put a secret in either header. The API key belongs in an environment variable or secret manager, not in source control or browser code.
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
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:
client = OpenAI(
base_url="https://keeprouter.com/v1",
api_key=os.environ["KEEPROUTER_KEY"],
)
response = client.chat.completions.create(
model="deepseek-v4-pro",
messages=[{"role": "user", "content": "Return only the word ready"}],
)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.
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
- [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