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 openai

Chat 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))  # 1536

Environment-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 automatically

3. JavaScript / TypeScript

npm install openai

Chat 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 models
  • client.embeddings.create() — text-embedding-3-small / -large
  • client.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 like X-Gateway-Routing: explicit per 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/model form — use anthropic/claude-sonnet-4-6, not claude-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 is baseURL (camelCase). Case matters.