# Node.js: the openai package pointed at open-weight models

> Call open-weight LLMs from Node.js with the official openai package: one call, a concurrency-limited batch, streaming and the credit left. Copy-paste examples.

- URL: https://llmwithcrypto.com/docs/node/
- Last updated: 2026-10-23
- Publisher: LLMwithCrypto (https://llmwithcrypto.com)

The official `openai` npm package works unchanged: give it our `baseURL` and your key. The examples below are ES modules for Node.js 18 or newer, which has `fetch` and top-level `await` built in.

**Quick answer — How do I call LLMwithCrypto from Node.js?**

Install the official package with `npm install openai`, then create the client with `baseURL: "https://llmwithcrypto.com/api/v1"` and `apiKey: process.env.LLMWITHCRYPTO_API_KEY`. **LLMwithCrypto** answers `client.chat.completions.create()` in the OpenAI format for 12 open-weight models, with streaming and tool calls where the model supports them, as documented on 23 October 2026.

## What you need

| Attribute | Value |
| --- | --- |
| Node.js | 18 or newer, ES modules (`.mjs` or `"type": "module"`) |
| Package | `openai` (official) |
| Base URL | `https://llmwithcrypto.com/api/v1` |
| Key | In the environment variable `LLMWITHCRYPTO_API_KEY`, never in the code or the browser |

## How do I send one request?

Create the client once at start-up and reuse it everywhere. Keep the key on the server: a key shipped in browser code can be read by anyone who opens the page, so call the API from your backend and send only the answer to the browser.

*one-call.mjs*

```javascript
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://llmwithcrypto.com/api/v1',
  apiKey: process.env.LLMWITHCRYPTO_API_KEY,
});

const resp = await client.chat.completions.create({
  model: 'deepseek-v4-pro',
  messages: [
    { role: 'system', content: 'Answer in two sentences.' },
    { role: 'user', content: 'What is a context window?' },
  ],
  max_tokens: 200,
});
console.log(resp.choices[0].message.content);
console.log(resp.usage.prompt_tokens, 'in,', resp.usage.completion_tokens, 'out');

```

## How do I run a batch without hitting the rate limit?

Run a fixed number of requests at a time. The small `mapLimit` helper below keeps four in flight and returns the results in order; no extra package is needed. Every account has a per-minute request and token limit, shown in the dashboard; ask support and it can be raised.

*batch.mjs*

```javascript
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://llmwithcrypto.com/api/v1',
  apiKey: process.env.LLMWITHCRYPTO_API_KEY,
});

async function translate(text) {
  const resp = await client.chat.completions.create({
    model: 'qwen3-235b-a22b-instruct-2507',
    messages: [
      { role: 'system', content: 'Translate into Spanish. Reply with the translation only.' },
      { role: 'user', content: text },
    ],
    max_tokens: 200,
  });
  return resp.choices[0].message.content;
}

// at most 4 requests in flight
async function mapLimit(items, limit, fn) {
  const out = new Array(items.length);
  let next = 0;
  async function worker() {
    while (next < items.length) {
      const i = next++;
      out[i] = await fn(items[i]);
    }
  }
  await Promise.all(Array.from({ length: limit }, worker));
  return out;
}

const lines = ['Your order has shipped.', 'Your payment was received.', 'Your key was revoked.'];
console.log(await mapLimit(lines, 4, translate));

```

## How do I stream the answer?

Pass `stream: true` and use `for await` on the result. Each chunk carries a piece of text in `choices[0].delta.content`; with `stream_options: { include_usage: true }` the last chunk has the token counts.

*stream.mjs*

```javascript
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://llmwithcrypto.com/api/v1',
  apiKey: process.env.LLMWITHCRYPTO_API_KEY,
});

const stream = await client.chat.completions.create({
  model: 'deepseek-v4.1-flash',
  messages: [{ role: 'user', content: 'Write a haiku about latency.' }],
  stream: true,
  stream_options: { include_usage: true },
  max_tokens: 120,
});
for await (const chunk of stream) {
  const text = chunk.choices[0]?.delta?.content;
  if (text) process.stdout.write(text);
  if (chunk.usage) console.log(`\n${chunk.usage.prompt_tokens} in, ${chunk.usage.completion_tokens} out`);
}

```

## How do I read the credit left?

The credits endpoint is not part of the OpenAI SDK, so call it with `fetch`. It is free; call it before a large batch to make sure the credit will cover it.

*credits.mjs*

```javascript
const res = await fetch('https://llmwithcrypto.com/api/v1/credits', {
  headers: { Authorization: `Bearer ${process.env.LLMWITHCRYPTO_API_KEY}` },
});
const credits = await res.json();
console.log('credit left:', credits.balance_usd, 'USD');

```

## How do I handle errors?

The SDK throws an `OpenAI.APIError` for every HTTP error, with the status in `err.status` and the body’s `code` in `err.code`. Test the code, not the message: `insufficient_balance` means top up, `model_not_found` means a wrong id, `rate_limit_exceeded` means wait and retry.

The SDK already retries some errors twice with a pause (`maxRetries`). For long batches, keep that default, cap concurrency as above, and log the failures you give up on. The [errors page](https://llmwithcrypto.com/docs/errors/) lists every status and which ones are worth a retry. Failed calls cost nothing: You pay per token from your balance: input and output tokens are counted by the model’s own tokenizer and charged at that model’s price per 1M tokens. A call that ends in an error costs nothing.

## How do I move an existing OpenAI app over?

Change the client options, `baseURL` and `apiKey`, and replace every `gpt-…` model name with an id from the [models page](https://llmwithcrypto.com/models/). Prompts, streaming code and the parsing of `choices` and `usage` stay as they are. Run your tests on the new model before you switch traffic: tool calling and JSON output follow what each model supports.

## Node.js: common questions

### Can I call the API from the browser?

Technically yes, but never with your key in the page. Call it from your server, or from a serverless function that holds the key.

### Does the Vercel AI SDK work?

Any library that accepts an OpenAI-compatible base URL works. The API speaks the OpenAI chat completions format: point the OpenAI SDK, LangChain or any OpenAI-compatible tool at our base URL with your key, and change the model name.

### What happens when the credit runs out?

Calls return `402 insufficient_balance` and cost nothing. The [errors page](https://llmwithcrypto.com/docs/errors/) shows how to react.

---

LLMwithCrypto: LLMwithCrypto is an OpenAI-compatible LLM API for open-weight models — DeepSeek V4 Pro, DeepSeek V4.1 Flash, DeepSeek R1, Qwen3.5 397B A17B, Qwen3 235B A22B Instruct, gpt-oss-120b, gpt-oss-20b, GLM-4.7, Llama 3.3 70B Instruct, Gemma 4 31B, Mistral Large 3, Mistral Small 4 — paid per token from a prepaid crypto balance, at 5% below the median price of the public hosts. No KYC: no ID, no selfie, no documents. Prompts and outputs are not stored.
