Browse documentation

Python (OpenAI client)

Use nRouter as a drop-in replacement with the OpenAI Python SDK

Last updated

If your codebase already uses the OpenAI Python client, you don't need to switch SDKs. Set base_url to https://api.nrouter.ai/v1 and use your sk-nrouter-... key as the api_key — no other changes.

Already using the OpenAI Python client elsewhere? This page is the minimal base-URL swap; the Python SDK guide walks through the same client in more depth.

Installation

pip install openai

Setup

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["NROUTER_API_KEY"],
    base_url="https://api.nrouter.ai/v1",
)

Chat Completion

response = client.chat.completions.create(
    model="gpt-5.4-mini",
    messages=[{"role": "user", "content": "Hello!"}],
)
print(response.choices[0].message.content)

Switching Providers

You don't need new credentials, new SDKs, or new endpoints to change models — just change the model string:

# OpenAI
client.chat.completions.create(model="gpt-5.4-mini", messages=[...])

# Google
client.chat.completions.create(model="gemini-2.5-flash", messages=[...])

Anthropic Claude Models: To call Anthropic Claude models on nRouter, use the native Anthropic Messages wire format (/v1/messages) via the official nrouter-sdk or standard Anthropic client library pointed at https://api.nrouter.ai.

Per-Request Overrides

The OpenAI SDK supports extra_body to forward nRouter-specific fields:

response = client.chat.completions.create(
    model="gpt-5.5",
    messages=[{"role": "user", "content": "Summarize Q1 earnings..."}],
    extra_body={
        "nrouter_prompt_template_id": "your-summarizer-id",
        "nrouter_prompt_variables": {"language": "Spanish"},
        "nrouter_cache": False,
    },
)

Guardrails are not one of these fields. You assign them in the dashboard at key, team, or organization scope — the narrowest scope that mentions a guardrail wins — and they run automatically on every request that scope covers.

Streaming

stream = client.chat.completions.create(
    model="gpt-5.5",
    messages=[{"role": "user", "content": "Write a short poem."}],
    stream=True,
)

for chunk in stream:
    content = chunk.choices[0].delta.content
    if content is not None:
        print(content, end="", flush=True)

Response Headers

Every successful response carries:

  • x-nr-request-id — id for this call, and the join key for its spend row
  • x-nr-model — the model that actually served the request
  • x-nr-cost-statusexact when we priced the call, unpriced when we could not
  • x-nr-request-cost — USD spend for this call. Absent when x-nr-cost-status is unpriced: nRouter never reports a cost of 0 for a call it could not price
  • x-nr-input-tokens, x-nr-output-tokens, x-nr-total-tokens — token counts as reported by the provider

Read them off response._response.headers (synchronous client) or via the with_raw_response accessor.

Next Steps

Was this page helpful?