OpenAI SDK (Python)
The official OpenAI SDK works with LowRouter unchanged once you set
base_url and api_key.
Install
pip install openaiA non-streaming completion
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.lowrouter.ai/v1",
api_key=os.environ["LOWROUTER_API_KEY"],
)
response = client.chat.completions.create(
model="auto/mistralai/mistral-large-2512",
messages=[
{"role": "user", "content": "In one sentence, what is a vector database?"}
],
)
print(response.choices[0].message.content)A streaming completion
stream = client.chat.completions.create(
model="auto/mistralai/mistral-large-2512",
messages=[{"role": "user", "content": "Count to 5 slowly"}],
stream=True,
)
for chunk in stream:
if not chunk.choices:
# The final frame carries usage and lowrouter_metadata, no choices.
continue
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="", flush=True)The if not chunk.choices guard is required. The last frame
before [DONE] has an empty choices list: it carries usage (with
cost, currency and remaining_balance) and lowrouter_metadata,
the per-request receipt. Indexing choices[0] on it raises
IndexError after the answer has already printed. That frame is sent
whether or not you set stream_options.include_usage, because it is
the only place a streamed request can report what it cost; see
request parameters.
Read it from the same loop:
for chunk in stream:
if chunk.usage:
meta = (chunk.model_extra or {}).get("lowrouter_metadata", {})
print(f"\ncost {chunk.usage.cost} {chunk.usage.currency}, "
f"{meta.get('carbon_gco2e')} gCO2e via {meta.get('provider')}")Reading the eco metadata
LowRouter’s per-request metadata lives outside the OpenAI schema, so the typed SDK fields don’t surface it. Read it from the raw response:
response = client.chat.completions.create(
model="auto/mistralai/mistral-large-2512",
messages=[{"role": "user", "content": "hi"}],
)
extra = response.model_extra or {}
meta = extra.get("lowrouter_metadata", {})
if meta:
print(f"{meta['carbon_gco2e']:.4f} gCO2e via {meta['provider']} "
f"({meta['region']})")response.model_extra is the canonical Pydantic-v2 escape hatch for
non-schema fields. On older SDK versions the attribute is
response.__pydantic_extra__.
Pinning a region
There is no separate route field. Pin a region by appending a
UN/LOCODE as the fourth segment of the model ID
({provider}/{creator}/{model}/{locode}); omit it to use the default
region:
response = client.chat.completions.create(
model="aws-bedrock/mistralai/ministral-3-3b-instruct/br-gru",
messages=[{"role": "user", "content": "hi"}],
)Async
The async client follows the same pattern:
import asyncio
from openai import AsyncOpenAI
client = AsyncOpenAI(
base_url="https://api.lowrouter.ai/v1",
api_key=os.environ["LOWROUTER_API_KEY"],
)
async def main():
r = await client.chat.completions.create(
model="auto/mistralai/mistral-large-2512",
messages=[{"role": "user", "content": "hi"}],
)
print(r.choices[0].message.content)
asyncio.run(main())