n4nAI

Getting started with the OpenAI Node.js SDK and n4n.ai

Practical openai node.js sdk n4n.ai getting started walkthrough: install, configure base URL, stream, handle errors, route models, and verify token usage.

n4n Team3 min read680 words

Audio narration

Coming soon — every post will get a voice note here.

If you’re looking for openai node.js sdk n4n.ai getting started, the shortest path is to point the official SDK at a compatible endpoint and send a chat request. This article walks through a production-minded setup: installing the package, configuring the base URL, streaming tokens, and handling the failure modes you’ll actually hit.

Step 1: Install the SDK and scaffold a project

Use Node.js 18 or newer so you get native fetch and standard async iterators. Initialize and install:

mkdir n4n-client && cd n4n-client
npm init -y
npm install openai dotenv

Add "type": "module" to package.json to avoid CommonJS interop headaches. Keep credentials out of source control with dotenv:

echo "OPENAI_API_KEY=sk-your-gateway-key" > .env
echo "GATEWAY_BASE_URL=https://api.n4n.ai/v1" >> .env

The API key is issued by your gateway, not OpenAI. The SDK only cares that the endpoint speaks the OpenAI protocol and returns the expected JSON shapes.

Step 2: Configure the client to target the gateway

The OpenAI Node.js SDK accepts a baseURL override. This is the core of openai node.js sdk n4n.ai getting started—you reuse the familiar client while routing through a different backend.

import OpenAI from 'openai';
import dotenv from 'dotenv';
dotenv.config();

const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
  baseURL: process.env.GATEWAY_BASE_URL,
});

export default client;

For example, n4n.ai provides one OpenAI-compatible endpoint that addresses 240+ models and handles provider fallback, so you avoid writing your own retry logic. The TypeScript types for ChatCompletion and ChatCompletionChunk remain unchanged.

Step 3: Send your first chat completion

Model identifiers are just strings that the gateway routes. A minimal non-streaming call:

import client from './client.js';

const resp = await client.chat.completions.create({
  model: 'gpt-4o-mini',
  messages: [
    { role: 'system', content: 'You are a terse code reviewer.' },
    { role: 'user', content: 'Review: const x = await fetch(url).json()' },
  ],
  temperature: 0.2,
  max_tokens: 256,
});

console.log(resp.choices[0].message.content);
console.log(resp.usage);

Run node index.js. If the model name is unknown, the gateway returns a 404 with an OpenAI-style error object—the SDK throws, it does not silently return empty.

Step 4: Stream tokens to cut perceived latency

Full response buffering wastes round-trips. Enable stream: true and consume the async iterator:

const stream = await client.chat.completions.create({
  model: 'gpt-4o-mini',
  messages: [{ role: 'user', content: 'Explain Rust borrows in 3 lines.' }],
  stream: true,
});

for await (const chunk of stream) {
  const delta = chunk.choices[0]?.delta?.content || '';
  process.stdout.write(delta);
}

Each chunk is a ChatCompletionChunk. If you need to abort, call stream.controller.abort()—the underlying fetch is cancelled. Always flush stdout when piping to log collectors.

Step 5: Handle rate limits and provider errors

Gateway-level fallback does not eliminate the need for local error boundaries. The SDK throws OpenAI.APIError on non-2xx:

import OpenAI from 'openai';

try {
  const r = await client.chat.completions.create({ /* ... */ });
} catch (err) {
  if (err instanceof OpenAI.APIError) {
    console.error(err.status, err.message, err.headers);
    if (err.status === 429) {
      // degrade: return cached response or lower-cost model
    }
  } else {
    throw err;
  }
}

Set a client timeout if you want fast failure:

const client = new OpenAI({ apiKey, baseURL, timeout: 15_000 });

Use bounded exponential backoff with jitter only if you intend to retry on top of the gateway’s own retries.

Step 6: Pass routing directives and cache hints

Some gateways let you pin a provider or reuse prompt caches via headers. When you need fine-grained control, pass routing headers; n4n.ai honors client routing directives and forwards provider cache-control hints, letting you pin a provider or use cached prompts. The SDK forwards arbitrary headers through the second argument:

const resp = await client.chat.completions.create(
  {
    model: 'claude-3-5-sonnet',
    messages: [{ role: 'user', content: 'Cached prompt here' }],
  },
  {
    headers: {
      'x-provider-prefer': 'anthropic',
      'x-cache-control': 'ttl=3600',
    },
  }
);

Header names are gateway-specific and not part of the OpenAI spec. Validate them against your provider’s docs before shipping.

Step 7: Verify success and inspect metering

You know the integration works when you receive a 200 with choices[0].message.content non-empty and usage.total_tokens > 0. The response object matches OpenAI’s shape exactly:

assert(resp.usage.prompt_tokens > 0);
assert(resp.usage.completion_tokens > 0);

Per-token metering appears in the usage field on every completion. In streaming mode, the final chunk often carries usage if the gateway supports it; otherwise sum deltas yourself. Log usage in structured JSON for cost debugging.

Common pitfalls

  • Forgetting await on create() returns a promise, not the completion.
  • Mixing require with ESM-only OpenAI package; prefer import.
  • Hardcoding a model that a given provider doesn’t serve; the gateway will 404, not substitute.
  • Ignoring stream.controller and leaving orphaned connections open under load.

Step 8: Structure for production

Wrap the client in a small module so the openai node.js sdk n4n.ai getting started boilerplate stays out of business logic:

// llm.js
import OpenAI from 'openai';
import dotenv from 'dotenv';
dotenv.config();

const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
  baseURL: process.env.GATEWAY_BASE_URL,
});

export async function complete(system, user, opts = {}) {
  return client.chat.completions.create({
    model: opts.model ?? 'gpt-4o-mini',
    messages: [
      { role: 'system', content: system },
      { role: 'user', content: user },
    ],
    temperature: opts.temperature ?? 0.3,
    stream: opts.stream ?? false,
    max_tokens: opts.max_tokens ?? 512,
  });
}

Import complete from route handlers or workers. Centralizing the client makes it easy to swap baseURL per environment.

Step 9: List available models programmatically

The SDK exposes client.models.list() to fetch the gateway catalog. Use it at startup to validate configuration:

const models = await client.models.list();
const ids = models.data.map((m) => m.id);
console.log(`Gateway serves ${ids.length} models`);
if (!ids.includes('gpt-4o-mini')) {
  console.warn('Expected model missing from catalog');
}

Some gateways paginate; check models.has_more and loop with after if you need the full set. This catches typos in model strings before user traffic hits them.

Verify end-to-end

  1. npm start after writing a script that calls complete or client.chat.completions.create.
  2. Expect console output of model text and a usage object with positive token counts.
  3. Swap in a bad key or unreachable baseURL: confirm your catch block logs 401/ENOTFOUND without crashing the process.
  4. Toggle stream: true and confirm tokens appear incrementally rather than all at once.
  5. Run client.models.list() and confirm the expected model ID is present.

That is the full loop. You have a resilient OpenAI-compatible client that streams, surfaces usage, and delegates multi-provider routing to the gateway.

Tagsnodejsopenai-sdkn4n-aiintegration

Written by

n4n Team

The team building n4n — a single OpenAI-compatible API in front of 240+ models, with automatic fallback, load balancing and pay-per-token metering.

More from n4n Team →

All node.js openai-compatible sdk integration posts →