# 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](https://keeprouter.com/editorial-policy#editorial-team)_

## 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

```python
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

```python
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](/models):

```python
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](/models), not this tutorial. The [OpenAI SDK base URL guide](/use-cases/openai-sdk) 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](https://openrouter.ai/docs/quickstart)
2. [OpenRouter Python SDK](https://openrouter.ai/docs/client-sdks/python/overview)
3. [OpenRouter OpenAI SDK integration](https://openrouter.ai/docs/guides/community/openai-sdk)
4. [OpenRouter provider routing](https://openrouter.ai/docs/guides/routing/provider-selection)
5. [OpenAI Python SDK](https://github.com/openai/openai-python)
6. [KeepRouter OpenAPI](https://keeprouter.com/api/openapi.json)

## Related guides

- [openai sdk](https://keeprouter.com/use-cases/openai-sdk.md)
- [What is an OpenAI-compatible API?](https://keeprouter.com/answers/what-is-an-openai-compatible-api.md)
- [KeepRouter vs OpenRouter](https://keeprouter.com/compare/openrouter.md)
- [Vercel AI Gateway vs OpenRouter](https://keeprouter.com/compare/vercel-ai-gateway-vs-openrouter.md)
- [OpenAI-compatible API migration checklist](https://keeprouter.com/blog/openai-compatible-api-migration-checklist.md)
- [errors](https://keeprouter.com/docs/errors.md)
- [models](https://keeprouter.com/models.md)

## Test the portable path

Start with a bounded OpenAI-shaped chat request, remove product-specific routing fields, map one exact target model, and compare response, usage, errors, and charge.

[Create a free key](https://keeprouter.com/login?returnTo=%2Fconsole%2Fkeys%3Fmodel%3Dfree) · [Live models and pricing](https://keeprouter.com/models.md)
