
# OpenAI SDK (TypeScript)

## Install

```bash
npm install openai
```

## A non-streaming completion

```ts
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

```ts
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:

```ts
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:

```ts
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:

```ts
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.
