# Use the OpenAI SDK for Python and Node.js with BigModel.io

> Call GLM, Kimi, DeepSeek and MiniMax models from the official OpenAI Python and Node.js SDKs by setting base_url to https://bigmodel.io/v1. Streaming, tools and fixes.

Web version: https://bigmodel.io/docs/openai-sdk-langchain · Updated 2026-10-18

BigModel.io speaks the OpenAI Chat Completions protocol, so the official OpenAI SDKs work after you change two values: the base URL and the API key.

| Setting | Value |
|---|---|
| Base URL | `https://bigmodel.io/v1` |
| API key | your BigModel.io key (`sk-...`), from an environment variable |
| Model | a model ID from the [model catalog](https://bigmodel.io/models), e.g. `glm-5.3` |

Which models a key can call depends on the key's group. All examples read the key from `BIGMODEL_API_KEY`:

```bash
export BIGMODEL_API_KEY="sk-..."
```

## Install

```bash [Python]
pip install openai
```

```bash [Node.js]
npm install openai
```

## Minimal call

```python [Python]
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://bigmodel.io/v1",
    api_key=os.environ["BIGMODEL_API_KEY"],
)

completion = client.chat.completions.create(
    model="glm-5.3",
    messages=[{"role": "user", "content": "Explain vector databases in three sentences."}],
)
print(completion.choices[0].message.content)
```

```js [Node.js]
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://bigmodel.io/v1",
  apiKey: process.env.BIGMODEL_API_KEY,
});

const completion = await client.chat.completions.create({
  model: "glm-5.3",
  messages: [{ role: "user", content: "Explain vector databases in three sentences." }],
});
console.log(completion.choices[0].message.content);
```

Both SDKs also read `OPENAI_BASE_URL` and `OPENAI_API_KEY` when you pass no arguments. That moves existing code without edits, but it also redirects every other OpenAI client in the same process.

## Streaming

```python [Python]
stream = client.chat.completions.create(
    model="glm-5.3",
    messages=[{"role": "user", "content": "Write a haiku about latency."}],
    stream=True,
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
```

```js [Node.js]
const stream = await client.chat.completions.create({
  model: "glm-5.3",
  messages: [{ role: "user", content: "Write a haiku about latency." }],
  stream: true,
});
for await (const part of stream) {
  process.stdout.write(part.choices[0]?.delta?.content || "");
}
```

For GLM and DeepSeek groups the gateway turns on `stream_options.include_usage`, so the last chunk carries `usage` and has an empty `choices` list. Guard for that, as the examples do. An error after the stream has started arrives as an SSE `error` event.

## Tool calling

`tools` and `tool_choice` are forwarded to the model. Whether a model returns tool calls depends on the model, so test the one you plan to use. See [Tool calling](https://bigmodel.io/docs/tool-calling) for the full loop.

```python [Python]
tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get the current weather for a city",
        "parameters": {
            "type": "object",
            "properties": {"city": {"type": "string"}},
            "required": ["city"],
        },
    },
}]

completion = client.chat.completions.create(
    model="glm-5.3",
    messages=[{"role": "user", "content": "What's the weather in Hangzhou?"}],
    tools=tools,
)
print(completion.choices[0].message.tool_calls)
```

```js [Node.js]
const tools = [{
  type: "function",
  function: {
    name: "get_weather",
    description: "Get the current weather for a city",
    parameters: {
      type: "object",
      properties: { city: { type: "string" } },
      required: ["city"],
    },
  },
}];

const completion = await client.chat.completions.create({
  model: "glm-5.3",
  messages: [{ role: "user", content: "What's the weather in Hangzhou?" }],
  tools,
});
console.log(completion.choices[0].message.tool_calls);
```

## Reasoning output

On GLM and DeepSeek groups the response body is passed through unchanged, so a thinking model's `reasoning_content` field reaches the SDK. It is not a typed attribute; read it as an extra field:

```python [Python]
message = completion.choices[0].message
print(getattr(message, "reasoning_content", None))
```

```js [Node.js]
console.log(completion.choices[0].message.reasoning_content);
```

See [Reasoning & thinking](https://bigmodel.io/docs/reasoning) for which parameters control thinking.

## Responses API

`client.responses.create(...)` calls `https://bigmodel.io/v1/responses`. Only some groups serve it; GLM and DeepSeek groups return 404 there. Chat Completions works for every text model. Over HTTP, `previous_response_id` is rejected with 400, so send the full input each time.

```python [Python]
response = client.responses.create(model="YOUR_MODEL_ID", input="ping")
print(response.output_text)
```

```js [Node.js]
const response = await client.responses.create({ model: "YOUR_MODEL_ID", input: "ping" });
console.log(response.output_text);
```

## Verify the setup

List the models your key can call. A list (possibly short) means the base URL and key are correct:

```python [Python]
for model in client.models.list():
    print(model.id)
```

```js [Node.js]
for await (const model of client.models.list()) {
  console.log(model.id);
}
```

Then send one request and confirm it appears in [Usage](https://bigmodel.io/usage).

## LangChain

LangChain's `ChatOpenAI` uses the same base URL:

```python
import os
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="glm-5.3", base_url="https://bigmodel.io/v1", api_key=os.environ["BIGMODEL_API_KEY"])
```

Streaming usage, `ChatAnthropic` and the `reasoning_content` caveat are covered in [LangChain](https://bigmodel.io/docs/langchain).

## OpenRouter-style requests

The same endpoints accept `provider/model` names such as `z-ai/glm-5.3`, a `models` fallback array, and `HTTP-Referer` / `X-Title` headers. Pass extra body fields with `extra_body` (Python) or as plain properties (Node.js). See [OpenRouter compatibility](https://bigmodel.io/docs/openrouter-compat) and [Migrate from OpenRouter](https://bigmodel.io/docs/migrate-from-openrouter).

## Troubleshooting

**404 on every request.** The base URL is missing `/v1` or already contains `/chat/completions`. Use exactly `https://bigmodel.io/v1`; the SDK adds the path.

**401 `INVALID_API_KEY` or `API_KEY_REQUIRED`.** The environment variable is empty in the process that runs your code. Print its first few characters, not the whole key.

**503 `No available accounts: no available accounts supporting model: ...`.** The model ID is misspelled or your key's group does not serve it. IDs are lowercase with dots kept; copy one from `client.models.list()` or the [model catalog](https://bigmodel.io/models).

**404 `... only supports /v1/chat/completions`.** You called the Responses API with a key whose group only serves Chat Completions. Use `chat.completions.create`.

**`response_format` seems ignored.** On groups that are not GLM or DeepSeek, Chat Completions requests are converted, and `response_format`, `n`, `seed`, `user` and `logprobs` are dropped. See [Structured output](https://bigmodel.io/docs/structured-output).

**403 `INSUFFICIENT_BALANCE`.** Your balance is at or below zero; top up in [Billing](https://bigmodel.io/purchase). `models.list()` also needs a positive balance.

**429 `API_KEY_QUOTA_EXHAUSTED` or `rate_limit_exceeded`.** The key's quota or a 5h/1d/7d spend limit is used up, or you hit a request-per-minute limit. See [Limits & rate limits](https://bigmodel.io/docs/rate-limits). Keep the SDK's built-in retries for plain 429s.

**Timeouts on long outputs.** Use streaming, or raise the client timeout (`timeout=` in Python, `timeout:` in Node.js).

## Related

- [LangChain](https://bigmodel.io/docs/langchain), [LlamaIndex](https://bigmodel.io/docs/llamaindex) and [Vercel AI SDK](https://bigmodel.io/docs/vercel-ai-sdk)
- [Anthropic SDK](https://bigmodel.io/docs/anthropic-sdk) for the Messages API
- [OpenAI SDK compatible API: Base URL, model IDs and errors](https://bigmodel.io/blog/openai-sdk-compatible-api)
- [API quickstart](https://bigmodel.io/docs/quickstart) and [Errors](https://bigmodel.io/docs/errors)
