Skip to content

OpenAI SDK

Use the official OpenAI SDKs for Python and Node.js with Nodul Router, including router-only fields.

The router speaks the OpenAI Chat Completions API: point the official SDK at its base URL and use your Router key.

Install

pip install openai
npm install openai

Configure the client

import os
from openai import OpenAI

client = OpenAI(
    base_url="https://router.nodul.ru/api/v1",
    api_key=os.environ["NODUL_ROUTER_API_KEY"],
)
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://router.nodul.ru/api/v1",
  apiKey: process.env.NODUL_ROUTER_API_KEY,
});

Many libraries built on the SDK read the same settings from the environment: OPENAI_BASE_URL=https://router.nodul.ru/api/v1 and OPENAI_API_KEY=$NODUL_ROUTER_API_KEY.

Router fields

provider, models and other fields outside the OpenAI types go in extra_body in Python; in Node.js add them to the request object.

completion = client.chat.completions.create(
    model="openai/gpt-4o-mini",
    messages=[{"role": "user", "content": "Hello"}],
    max_tokens=200,
    extra_body={
        "models": ["google/gemma-3-4b-it"],
        "provider": {"zdr": True},
    },
)
print(completion.choices[0].message.content)
print("cost, PnP:", completion.usage.cost)
const completion = await client.chat.completions.create({
  model: "openai/gpt-4o-mini",
  messages: [{ role: "user", content: "Hello" }],
  max_tokens: 200,
  // @ts-expect-error: router fields, not part of the OpenAI types
  models: ["google/gemma-3-4b-it"],
  provider: { zdr: true },
});
console.log(completion.choices[0].message.content);

usage.cost is not in the SDK types either: in Python it is still an attribute of usage; in TypeScript read it as (completion.usage as any).cost.

Streaming

stream = client.chat.completions.create(
    model="google/gemma-3-4b-it",
    messages=[{"role": "user", "content": "Write a haiku."}],
    stream=True,
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
const stream = await client.chat.completions.create({
  model: "google/gemma-3-4b-it",
  messages: [{ role: "user", content: "Write a haiku." }],
  stream: true,
});
for await (const chunk of stream) process.stdout.write(chunk.choices[0]?.delta?.content ?? "");

Errors and retries

The SDK raises openai.APIStatusError (Python) or OpenAI.APIError (Node.js) with status and the router's message. The SDKs retry 408, 409, 429 and 5xx twice by default; set max_retries / maxRetries to change it. Remember that every retry of a POST is a new, separately billed request. See Errors.

What is not supported

Only chat completions are available: the Responses API, embeddings, images, audio and the Assistants API of the SDK are not. client.models.list() works and returns the catalog.

Nodul Router — one API for every model