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
awaitoncreate()returns a promise, not the completion. - Mixing
requirewith ESM-only OpenAI package; preferimport. - Hardcoding a model that a given provider doesn’t serve; the gateway will 404, not substitute.
- Ignoring
stream.controllerand 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
npm startafter writing a script that callscompleteorclient.chat.completions.create.- Expect console output of model text and a usage object with positive token counts.
- Swap in a bad key or unreachable
baseURL: confirm yourcatchblock logs401/ENOTFOUNDwithout crashing the process. - Toggle
stream: trueand confirm tokens appear incrementally rather than all at once. - 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.