The OpenAI API is often the first AI API a developer integrates, and its patterns — API keys, streaming responses, function/tool calling, structured outputs — end up as the mental template most developers carry into every other provider's API, for better or worse.
The OpenAI API provides programmatic access to OpenAI's models for text generation, structured outputs, function calling, embeddings, and more, through a REST API and official SDKs — the core integration points are authentication, request/response handling, streaming, and increasingly, agentic patterns like tool use and multi-step reasoning.
Why Understanding the API Directly Matters (and When a Higher-Level SDK Suffices)
Understanding the API directly matters when you need fine control over request parameters, are debugging unexpected behavior, or are building patterns (custom streaming handling, specific retry logic) not covered by a higher-level abstraction — knowing what's actually happening under an SDK's abstraction is what lets you debug effectively when something doesn't behave as expected.
A higher-level SDK or framework (the Vercel AI SDK, LangChain) suffices for standard integration patterns — most applications don't need direct API knowledge beyond what a well-designed abstraction already handles, and reaching for the raw API adds implementation work a good abstraction would have saved.
Getting Started with the OpenAI API
Basic authenticated request using the official Node SDK:
import OpenAI from "openai";
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const response = await client.responses.create({
model: "gpt-5",
input: "Summarize the key differences between REST and GraphQL.",
});
console.log(response.output_text);
Streaming a response:
const stream = await client.responses.create({
model: "gpt-5",
input: "Write a short explanation of event loops in Node.js.",
stream: true,
});
for await (const event of stream) {
if (event.type === "response.output_text.delta") {
process.stdout.write(event.delta);
}
}
Core OpenAI API Concepts Every Developer Should Know
API keys need to be treated as sensitive credentials, never exposed client-side — all requests should route through your own backend, which holds the key server-side, since a client-exposed key can be extracted and used by anyone who inspects your frontend's network requests or bundled code.
Function/tool calling lets the model request that your code execute a specific function, returning the result for the model to incorporate into its response — this is the core mechanism behind most agentic patterns built on the OpenAI API, letting the model take real actions rather than just generating text.
Streaming responses improve perceived latency for user-facing applications by delivering output incrementally as it's generated rather than waiting for the full response — implementing streaming correctly means handling partial state on the client and gracefully managing connection interruptions mid-stream.
Rate limits and usage costs scale with both token volume and model choice, and production applications need explicit handling for rate-limit errors (backoff and retry) plus deliberate model selection — using a more capable, expensive model for every request regardless of task complexity is a common and avoidable cost driver.
Common Mistakes With the OpenAI API and How to Fix Them
Mistake 1: exposing the API key in client-side code, letting it be extracted and misused by anyone inspecting network requests. Fix: route all API calls through your own backend, keeping the key server-side only.
Mistake 2: no retry/backoff handling for rate-limit or transient errors, causing user-facing failures for what should be a transparently retried request. Fix: implement exponential backoff retry logic for rate-limit and transient error responses.
Mistake 3: using the most capable model uniformly regardless of task complexity, driving unnecessary cost. Fix: tier model selection by task complexity, reserving the most capable model for tasks that genuinely need it.
When Should You Use the Raw OpenAI API Instead of a Higher-Level SDK?
Use the raw API when you need fine control over request behavior, are implementing patterns not covered by a higher-level abstraction, or are debugging issues where understanding the exact request/response is necessary. Use a higher-level SDK for standard integration patterns where a well-designed abstraction already handles the complexity you'd otherwise implement yourself.
The OpenAI API in Production
Keep API keys server-side only, implement retry/backoff for transient errors, and tier model selection by actual task complexity to control cost. Use streaming for user-facing latency-sensitive interactions, and use function calling deliberately for cases genuinely needing the model to trigger real actions in your system.
If you're integrating the OpenAI API for the first time, start with server-side key handling and basic error handling before adding streaming or function calling — getting the foundational request/response pattern solid first makes the more advanced patterns easier to layer on correctly.