Guides

How to Integrate the OpenAI API With Next.js

This covers calling the OpenAI API from a Route Handler, streaming the response back to the client for a responsive UI, and the error handling and cost controls worth having from the start.

Prerequisites

  • arrow_rightAn OpenAI API key
  • arrow_rightA Next.js App Router project
  • arrow_rightThe openai npm package installed

Step 1: Create a Route Handler

app/api/chat/route.ts

import OpenAI from 'openai';
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

export async function POST(request: Request) {
  const { message } = await request.json();
  const completion = await openai.chat.completions.create({
    model: 'gpt-4o-mini',
    messages: [{ role: 'user', content: message }],
  });
  return Response.json({ reply: completion.choices[0].message.content });
}

Step 2: Stream the Response

const stream = await openai.chat.completions.create({
  model: 'gpt-4o-mini',
  messages: [{ role: 'user', content: message }],
  stream: true,
});

const encoder = new TextEncoder();
const readable = new ReadableStream({
  async start(controller) {
    for await (const chunk of stream) {
      const text = chunk.choices[0]?.delta?.content ?? '';
      controller.enqueue(encoder.encode(text));
    }
    controller.close();
  },
});
return new Response(readable);

Streaming shows the response as it's generated instead of waiting for the full completion, which meaningfully improves perceived speed for longer responses.

Step 3: Handle Errors and Rate Limits

Wrap the API call in a try/catch, handle rate limit (429) responses with a retry-with-backoff strategy, and set a reasonable timeout so a slow or hanging request doesn't leave the user waiting indefinitely.

Common Errors

  • arrow_rightAPI key exposed in client-side code — the OpenAI API must only ever be called from server code (Route Handlers, server components), never directly from the browser
  • arrow_rightNo error handling around the API call, so a transient failure crashes the request instead of degrading gracefully
  • arrow_rightNo cost monitoring, leading to a surprise bill if usage spikes unexpectedly

Security & Cost Considerations

  • arrow_rightKeep the API key server-side only, in an environment variable never exposed to the client
  • arrow_rightSet per-user or per-session usage limits to control cost
  • arrow_rightChoose the smallest model that reliably handles the task — cost scales directly with tokens processed

Frequently Asked Questions

Can I call the OpenAI API directly from a client component?add

No — this would expose your API key in the browser, where anyone could extract and misuse it. Always route the call through a server-side Route Handler.

How do I stream a response to a React component?add

The Route Handler returns a ReadableStream response, which the client reads incrementally (via fetch's response.body reader, or a library like the Vercel AI SDK that wraps this pattern) to update the UI as text arrives.

Which model should I default to?add

A smaller, faster model (like gpt-4o-mini) is often sufficient and considerably cheaper for most tasks; reserve larger models for genuinely complex reasoning tasks where the smaller model's output quality falls short.

BUILDING SOMETHING SIMILAR?

If you'd rather have this built and shipped than build it yourself, I'm available for freelance and contract work.