OpenAI SDK (TypeScript)
Install
Bash
npm install openaiA non-streaming completion
TypeScript
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://lowrouter.ai/api/v1",
apiKey: process.env.LOWROUTER_API_KEY,
});
const response = await client.chat.completions.create({
model: "lowrouter/auto",
messages: [
{ role: "user", content: "In one sentence, what is a vector database?" },
],
});
console.log(response.choices[0].message.content);A streaming completion
TypeScript
const stream = await client.chat.completions.create({
model: "lowrouter/auto",
stream: true,
messages: [{ role: "user", content: "Count to 5 slowly" }],
});
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta?.content;
if (delta) process.stdout.write(delta);
}Reading the eco metadata
The TypeScript types do not include LowRouter’s extra fields. Cast or narrow when you read them:
TypeScript
type LowRouterMeta = {
generation_id: string;
provider: string;
region: string;
eco?: {
energy_wh: number;
carbon_g: number;
carbon_per_1k_tokens_g: number;
accuracy: "accurate" | "medium" | "gross";
};
};
const r = await client.chat.completions.create({ /* ... */ });
const meta = (r as unknown as { lowrouter?: LowRouterMeta }).lowrouter;
if (meta?.eco) {
console.log(
`${meta.eco.carbon_per_1k_tokens_g.toFixed(3)} gCO2e/1k (${meta.eco.accuracy})`,
);
}Pinning a region
The SDK forwards unknown fields:
TypeScript
const response = await client.chat.completions.create({
model: "openai/gpt-4o-mini",
messages: [{ role: "user", content: "hi" }],
// @ts-expect-error: extra fields not in the OpenAI schema
route: { region: "eu-west" },
});Or, if you prefer not to silence the type error, send the field as a header:
TypeScript
const client = new OpenAI({
baseURL: "https://lowrouter.ai/api/v1",
apiKey: process.env.LOWROUTER_API_KEY,
defaultHeaders: { "X-LowRouter-Region": "eu-west" },
});Browser usage
The OpenAI SDK warns against running with an API key in the browser
because the key is then exposed to every page visitor. The same
applies to LowRouter: keep your LOWROUTER_API_KEY server-side and
proxy requests from a backend you control. If you need a signed,
short-lived token for a browser client, server-side endpoint that
mints one is the right shape.