---
title: SDKs
description: The official OpenAI and Anthropic SDKs, Python and Node: install, a client with the gateway's base URL and the key from the environment, one call. Your code stays your code.
keywords: sdk, openai, anthropic, python, node, base_url, langchain, llamaindex
group: integrations
---

## Quick {#quick keywords="install, client, base url, key"}

You do not change SDKs. Install the same official package you always would; two constructor arguments change — the base URL and the key.

```bash title=Install
# The OpenAI-compatible dialect
pip install openai
npm install openai

# The native Anthropic dialect
pip install anthropic
npm install @anthropic-ai/sdk
```

Keep the key in an environment variable. None of the examples below writes a secret into source — they all read `KUMO_API_KEY`, so export it first in the shell you run the code from.

```bash title=Key
export KUMO_API_KEY="kumo_sk_..."
```

A new organization's wallet is empty: a first call without a top-up answers `402` ([billing](/en/billing)).

## The OpenAI SDK {#openai-sdk keywords="openai, chat completions, python, node, base_url"}

The base URL is `https://api.kumorouter.com/v1`, including the `/v1`. The SDK appends the operation path itself.

:::code-group
```python title=Python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.kumorouter.com/v1",
    api_key=os.environ["KUMO_API_KEY"],
)

answer = client.chat.completions.create(
    model="<model>",
    max_tokens=128,
    messages=[{"role": "user", "content": "Explain tokens in one line."}],
)
print(answer.choices[0].message.content)
```
```javascript title=Node
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.kumorouter.com/v1",
  apiKey: process.env.KUMO_API_KEY,
});

const answer = await client.chat.completions.create({
  model: "<model>",
  max_tokens: 128,
  messages: [{ role: "user", content: "Explain tokens in one line." }],
});

const reply = answer.choices[0].message.content;
process.stdout.write((reply ?? "") + "\n");
```
:::

The output ceiling is required: a request without `max_tokens` (equivalently `max_completion_tokens`) is refused rather than left unbounded.

## The Anthropic SDK {#anthropic-sdk keywords="anthropic, messages, python, node, x-api-key"}

The base URL is `https://api.kumorouter.com`, the **bare origin, with no `/v1`**: the SDK appends `/v1/messages` itself. The key travels in the `x-api-key` header, and the SDK puts it there without your help.

:::code-group
```python title=Python
import os
from anthropic import Anthropic

client = Anthropic(
    base_url="https://api.kumorouter.com",
    api_key=os.environ["KUMO_API_KEY"],
)

answer = client.messages.create(
    model="<model>",
    max_tokens=128,
    messages=[{"role": "user", "content": "Explain tokens in one line."}],
)
print(answer.content[0].text)
```
```javascript title=Node
import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({
  baseURL: "https://api.kumorouter.com",
  apiKey: process.env.KUMO_API_KEY,
});

const answer = await client.messages.create({
  model: "<model>",
  max_tokens: 128,
  messages: [{ role: "user", content: "Explain tokens in one line." }],
});

const reply = answer.content[0].text;
process.stdout.write((reply ?? "") + "\n");
```
:::

:::note
Not every model answers on both dialects. Which protocols a given model supports is stated on its card in the catalog, beside its capabilities. Read the card before you pick an SDK.
:::

> [How the key header is written →](/en/authentication) [What a model can do →](/en/models)

## Streaming {#streaming keywords="streaming, stream, sse"}

Both SDKs stream, and the gateway answers each in the shape of its own protocol: events in arrival order, then a terminating frame. There is one difference from a unary call — a failure after the stream has begun cuts it off with no terminating frame, and such an answer counts as a failed call, not a short one.

> [Streaming in full →](/en/streaming)

## Libraries built on the OpenAI client {#compatible-libraries keywords="langchain, llamaindex, framework, openai-compatible"}

Frameworks such as LangChain or LlamaIndex usually reach models through that same OpenAI client. If a library lets you configure the OpenAI client's base URL, it works with the gateway exactly as a direct call does: set `https://api.kumorouter.com/v1` and the key, and leave everything else alone.

The exact parameter name differs per library, and it is deliberately not named here: names are renamed between releases, and a wrong name looks like a setting that was silently ignored. Check your library's own documentation — what you are looking for is the place where the OpenAI client's base URL is set.

The easiest proof that the setting took effect is the console log: the call is there, so the library went through the gateway.

:::cards
- [Quickstart](/en/quickstart) — the first call, from key to answer.
- [Every recipe](/en/integrations) — the overview and the agent prompt.
- [API reference](/en/api-reference) — every operation, field by field.
:::
