How to Use the OpenAI API with Node.js: Complete 2026 Guide
Quick answer: npm install openai, set OPENAI_API_KEY, call client.chat.completions.create(). This guide covers the full OpenAI Node.js SDK including TypeScript types, streaming, function calling, and async patterns for production.
Installation and setup
npm install openai
export OPENAI_API_KEY="sk-..."
For TypeScript projects:
npm install openai
npm install --save-dev @types/node
Basic chat completion
import OpenAI from 'openai';
const client = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
async function main() {
const completion = await client.chat.completions.create({
model: 'gpt-4o',
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'What is the capital of France?' }
],
max_tokens: 256,
});
console.log(completion.choices[0].message.content);
console.log(`Tokens used: ${completion.usage?.total_tokens}`);
}
main();
Streaming responses
async function streamChat(prompt: string) {
const stream = await client.chat.completions.create({
model: 'gpt-4-1',
messages: [{ role: 'user', content: prompt }],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content || '');
}
console.log();
}
Function calling (tools)
const tools: OpenAI.Chat.ChatCompletionTool[] = [
{
type: 'function',
function: {
name: 'get_stock_price',
description: 'Get current stock price for a ticker symbol',
parameters: {
type: 'object',
properties: {
ticker: { type: 'string', description: 'Stock ticker, e.g. AAPL' }
},
required: ['ticker']
}
}
}
];
const response = await client.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: 'What is Apple stock price?' }],
tools,
tool_choice: 'auto',
});
const toolCall = response.choices[0].message.tool_calls?.[0];
if (toolCall) {
const args = JSON.parse(toolCall.function.arguments);
console.log(`Calling ${toolCall.function.name} with:`, args);
}
Structured outputs (JSON mode)
const response = await client.chat.completions.create({
model: 'gpt-4o',
response_format: { type: 'json_object' },
messages: [
{
role: 'system',
content: 'Return responses as JSON with fields: answer (string), confidence (0-1)'
},
{ role: 'user', content: 'Is Paris the capital of France?' }
],
});
const data = JSON.parse(response.choices[0].message.content!);
console.log(data.answer, data.confidence);
Embeddings
async function getEmbedding(text: string): Promise<number[]> {
const response = await client.embeddings.create({
model: 'text-embedding-3-small',
input: text,
});
return response.data[0].embedding;
}
// Cosine similarity
function cosineSimilarity(a: number[], b: number[]): number {
const dot = a.reduce((sum, ai, i) => sum + ai * b[i], 0);
const magA = Math.sqrt(a.reduce((sum, ai) => sum + ai * ai, 0));
const magB = Math.sqrt(b.reduce((sum, bi) => sum + bi * bi, 0));
return dot / (magA * magB);
}
Handling rate limits and errors
import { RateLimitError, APIError } from 'openai';
async function callWithRetry(fn: () => Promise<any>, maxRetries = 5) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
if (error instanceof RateLimitError) {
const delay = Math.pow(2, attempt) * 1000 + Math.random() * 1000;
console.log(`Rate limited. Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
} else if (error instanceof APIError) {
throw error; // Don't retry non-rate-limit errors
} else {
throw error;
}
}
}
throw new Error('Max retries exceeded');
}
Cost-aware model routing
type TaskTier = 'complex' | 'standard' | 'simple';
const MODEL_MAP: Record<TaskTier, string> = {
complex: 'gpt-4o', // $2.50/1M input
standard: 'gpt-4-1', // $2.00/1M input
simple: 'gpt-4-1-nano', // $0.10/1M input
};
async function tieredCompletion(prompt: string, tier: TaskTier) {
return client.chat.completions.create({
model: MODEL_MAP[tier],
messages: [{ role: 'user', content: prompt }],
});
}
Compare OpenAI vs other providers at LLMversus and calculate costs for your workload with the cost calculator. See best LLM for developers for a full ranking.