OpenAI SDK · Python + JS
OpenAI SDK + Leanroute
The official OpenAI Python and Node.js SDKs both accept a base_url / baseURL override. Point that at https://api.leanroute.dev/v1 and every endpoint you use — chat completions, embeddings, images, moderations — goes through Leanroute with zero other code changes.
Why this matters.
You can migrate from direct OpenAI to Leanroute by changing two lines. No SDK swap. No prompt reformat. No conversation-history reshape. Your Python or Node app looks identical — but now you can hit Anthropic, Google, DeepSeek, Kimi, GLM, and eight more providers by changing the model string.
1. Get a gateway key
From /dashboard/keys create a key. Copy the gw_live_* value — shown only once.
2. Python
pip install openaiChat completion:
from openai import OpenAI
client = OpenAI(
api_key="gw_live_YOUR_KEY",
base_url="https://api.leanroute.dev/v1",
)
resp = client.chat.completions.create(
model="anthropic/claude-sonnet-4-6",
messages=[{"role": "user", "content": "Hello in one sentence."}],
)
print(resp.choices[0].message.content)Streaming:
stream = client.chat.completions.create(
model="anthropic/claude-sonnet-4-6",
messages=[{"role": "user", "content": "Write a haiku about caching."}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta.content or ""
print(delta, end="", flush=True)Embeddings:
resp = client.embeddings.create(
model="openai/text-embedding-3-small",
input="What is prompt caching?",
)
print(len(resp.data[0].embedding)) # 1536Environment-variable setup: the SDK reads both OPENAI_API_KEY and OPENAI_BASE_URL automatically — put them in .env and drop the explicit constructor args:
# .env
OPENAI_API_KEY=gw_live_YOUR_KEY
OPENAI_BASE_URL=https://api.leanroute.dev/v1
# Then in Python — no explicit args needed:
from openai import OpenAI
client = OpenAI() # picks up both env vars automatically3. JavaScript / TypeScript
npm install openaiChat completion:
import OpenAI from "openai";
const client = new OpenAI({
apiKey: "gw_live_YOUR_KEY",
baseURL: "https://api.leanroute.dev/v1",
});
const resp = await client.chat.completions.create({
model: "anthropic/claude-sonnet-4-6",
messages: [{ role: "user", content: "Hello in one sentence." }],
});
console.log(resp.choices[0].message.content);Streaming (async iterator):
const stream = await client.chat.completions.create({
model: "anthropic/claude-sonnet-4-6",
messages: [{ role: "user", content: "Write a haiku about caching." }],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}What else works out of the box
The SDK doesn't know it's talking to Leanroute — it thinks it's talking to OpenAI. Every endpoint the SDK exposes is proxied:
client.chat.completions.create()— all modelsclient.embeddings.create()— text-embedding-3-small / -largeclient.models.list()— returns the full Leanroute model catalog (populates OpenAI-compatible tool pickers)- Function calling / tool use / structured output — forwarded to the upstream provider transparently
extra_headers=(Python) /defaultHeaders: { ... }(JS) — use these to send Leanroute-specific headers likeX-Gateway-Routing: explicitper request
Troubleshooting
- 401 unauthenticated: issue a new key at /dashboard/keys.
- 400 unknown_model: the SDK forwards the string as-is. Use the canonical
provider/modelform — useanthropic/claude-sonnet-4-6, notclaude-sonnet-4-6. Full list at /dashboard/models. - The SDK still hits api.openai.com: the explicit constructor args override the env vars, but only if you spelled them exactly — Python is
base_url(underscore), JS isbaseURL(camelCase). Case matters.