This OpenRouter OpenAI SDK guide connects your Python application by changing the base URL and API key, then selecting an OpenRouter model ID. This guide covers setup, usage logs, streaming, and routing options.

A drop-in migration with important differences

If your application already uses the OpenAI Python SDK, point its base URL at OpenRouter and provide an OpenRouter key. Your conversation code can stay familiar, while model choice and provider routing move behind the gateway.

Checked October 15, 2026: confirm example model slugs and prices in the current catalog.

Smallest working setup

python -m venv .venv
. .venv/bin/activate
pip install --upgrade openai
export OPENROUTER_API_KEY='your-key'
export OPENROUTER_MODEL='openai/gpt-5.2'
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=2,
)
response=client.chat.completions.create(
 model=os.environ["OPENROUTER_MODEL"],
 messages=[{"role":"user","content":"Reply exactly: SDK connected"}],
 max_tokens=32,
)
print(response.choices[0].message.content)
print(response.usage)

The critical pair is the OpenRouter base URL plus an OpenRouter API key. Do not accidentally combine an OpenRouter key with another vendor’s URL.

Add attribution headers

response=client.chat.completions.create(
 model=os.environ["OPENROUTER_MODEL"],
 extra_headers={
  "HTTP-Referer":"https://productivityvision.com",
  "X-OpenRouter-Title":"ProductivityVision assistant",
 },
 messages=[{"role":"user","content":"Give one focus tip."}],
 max_tokens=100,
)

These headers identify the app; they are not secrets and do not replace Bearer authentication.

Log usage safely

record={
 "id":response.id,
 "model":response.model,
 "prompt_tokens":getattr(response.usage,"prompt_tokens",None),
 "completion_tokens":getattr(response.usage,"completion_tokens",None),
 "total_tokens":getattr(response.usage,"total_tokens",None),
}
print(record)

Log request ID, returned model, timing, usage, and outcome—not Authorization headers or user prompts. Usage and cost fields can evolve, so make logging tolerant of missing properties.

Choose one retry owner

The SDK can retry selected failures. If an outer queue also retries, calculate the combined maximum: three queue attempts times three SDK attempts can become nine paid requests. Either set SDK retries deliberately or make the outer worker own retry policy.

client=OpenAI(
 base_url="https://openrouter.ai/api/v1",
 api_key=os.environ["OPENROUTER_API_KEY"],
 timeout=30.0,
 max_retries=0, # outer worker owns retries
)

Provider routing and fallbacks

Pass OpenRouter-specific request options through the SDK’s extra-body mechanism when necessary. Keep fallbacks reviewed: a replacement model may differ in quality, tool support, context, latency, and cost. Always record the returned model.

response=client.chat.completions.create(
 model="anthropic/claude-sonnet-4",
 messages=[{"role":"user","content":"Summarize this incident."}],
 extra_body={
  "models":["openai/gpt-5.2","google/gemini-2.5-pro"],
  "provider":{"allow_fallbacks":True},
 },
)

Verify the current schema in official routing docs before deployment.

Streaming

stream=client.chat.completions.create(
 model=os.environ["OPENROUTER_MODEL"],
 messages=[{"role":"user","content":"Explain backoff briefly."}],
 stream=True,
)
for chunk in stream:
    delta=chunk.choices[0].delta.content if chunk.choices else None
    if delta: print(delta,end="",flush=True)

A stream can fail after HTTP 200. Preserve partial text separately, surface an incomplete state, and read the final usage/error event.

Common migration mistakes

  • Changing the key but not the base URL.
  • Using a vendor model name that is not an OpenRouter catalog slug.
  • Leaving unlimited SDK retries under another retry loop.
  • Assuming every model supports the same tools or JSON schema.
  • Parsing only answer text and discarding model, finish reason, usage, and errors.

OpenRouter OpenAI SDK FAQ

Is OpenRouter fully OpenAI-compatible?

It supports the familiar SDK pattern, but model capabilities and OpenRouter routing options still require deliberate testing.

Can I keep my existing types?

Often yes for chat completions. Add validation around OpenRouter-specific metadata and any model-specific response differences.

Read next

Use the direct Python tutorial, fallback guide, and complete guide.

Test compatibility before switching traffic

Use a small set of real application prompts to compare the old and new route. Include an empty input, a long conversation, a tool request, and a schema-constrained extraction. Check the finish reason and validate fields your application consumes; receiving text alone is not a passing result.

Record the installed SDK version, requested model, returned model, latency, and token usage. Pin the dependency version you tested and keep a rollback configuration for the base URL and model. Introduce one change at a time so an SDK upgrade, prompt edit, and model switch do not obscure the cause of a regression.

Official references

Documentation reviewed 15 October 2026. Examples illustrate the request pattern; confirm model availability and account settings before use. No uptime or performance benchmark is claimed.

Similar Posts