Why Responses Replaced Chat Completions
The Endpoint You're Actually Calling
Every request you send to OpenAI through the Python SDK ends up as an HTTP call to one specific URL. For the code in this course, that URL is:
POST https://api.openai.com/v1/responses
That endpoint — /v1/responses — is the Responses API. It is the interface this entire course is built on, and it is what OpenAI now recommends for every new project. But if you search Stack Overflow, read a two-year-old blog post, or open an older codebase, you will run into a different pattern built around a different endpoint:
POST https://api.openai.com/v1/chat/completions
That is the Chat Completions API — for a long time, the default way developers talked to OpenAI's models. It still exists, it still works, and OpenAI has not shut it off. But it is no longer the interface OpenAI designs new features around, and understanding why matters more than memorizing syntax. If you understand the "why," the "how" you already half-know, because the Responses API is not a random redesign — it is Chat Completions with the rough edges specifically identified and fixed.
What Chat Completions Got Right, and Where It Started to Strain
Chat Completions modeled a conversation as exactly one thing: a flat list of messages, each with a role (system, user, or assistant) and content. You sent the whole list on every call, the model looked at the last message, and it replied with one new assistant message. That mental model — a growing transcript, replayed in full each time — is simple, and simplicity is why it became the standard so quickly.
The strain showed up as OpenAI's models grew more capable. Three specific pressures pushed the design in a new direction:
Models started doing more than talking. A model that can search the web, run code, look through your files, or call multiple tools in sequence before answering isn't producing one message anymore — it's producing a sequence of actions, some of which are tool calls, some of which are intermediate reasoning, and only the last of which might be user-facing text. Chat Completions had a single content string per assistant message and bolted tool_calls onto the side of it. That works for one tool call. It gets awkward fast when the model needs to reason, call a tool, look at the result, call another tool, and then answer — because "one message equals one API turn" was never designed to describe a multi-step process happening inside a single request.
State management was entirely your problem. Chat Completions is stateless by design (a property covered in Unit 1) — every call resends the full message history, and OpenAI's servers remember nothing about you between requests. That's a defensible design, but it means every application independently reinvents the same plumbing: store messages somewhere, reassemble the array, resend it, repeat. There was no server-side option to say "continue this conversation" without doing that reassembly yourself.
Reasoning models didn't fit the shape. OpenAI's reasoning models (the o-series, and now the reasoning-capable models in the gpt-5.6/gpt-6 families) do internal reasoning before producing a visible answer. Chat Completions had nowhere well-defined to put that — no structured place to say "here is what the model thought through" as distinct from "here is what it's telling the user." Retrofitting that onto a content string is exactly the kind of shape mismatch that produces messy, backward-compatibility-driven API design.
What the Responses API Changes
The Responses API is OpenAI's answer to all three pressures, and each design decision maps directly onto one of them.
A typed output array instead of a flat message. Instead of returning one assistant message, a Response returns an output array — an ordered list of typed items. An item might be a message (text meant for the user), a function_call (the model requesting a tool run), a reasoning item, a web search call, or several other types. This is the direct fix for the "models do more than talk" problem: the API can now represent everything a model did during a turn — including several tool calls in sequence — as a structured list, instead of squeezing it into one message with extra fields hanging off the side. Lesson 3 of this unit is dedicated entirely to walking through this array.
instructions and input instead of one messages list. The Responses API separates the standing behavioral guidance you give a model (instructions) from the actual conversational content (input). This isn't just cosmetic — it maps cleanly onto how developers actually think about a prompt: "here are the rules" versus "here is what's being asked right now." Lesson 2 covers this anatomy in full.
Built-in state, opt-in. With store: true and previous_response_id, the Responses API can keep a response on OpenAI's servers and let your next call reference it by ID instead of resending the whole transcript. You are not forced to use this — Unit 4 covers both the manual (Chat-Completions-style) approach and this newer chained approach — but the option exists natively, where before it did not.
Reasoning has a home. Reasoning items can appear in the output array as their own typed entry, and previous_response_id can carry a model's internal reasoning context forward between turns for reasoning models — something Chat Completions has no equivalent for.
OpenAI has also published internal benchmark numbers behind this shift: reasoning models tend to score measurably better on agentic coding benchmarks (OpenAI has cited roughly a 3% SWE-bench improvement) when called through Responses instead of Chat Completions with an equivalent prompt, and prompt caching hit rates improve substantially — OpenAI's own tests report roughly 40–80% better cache utilization with Responses. Caching matters directly to your wallet: a cached input token is billed at a steep discount (see the pricing table in Unit 1, Lesson 1), so a design that makes caching work better isn't a minor implementation detail — it changes what your application costs to run at scale.
Is Chat Completions Deprecated?
No — and this is worth being precise about, because "deprecated" and "no longer recommended" get used interchangeably online and they are not the same thing. As of this writing, OpenAI's own documentation states plainly that Chat Completions remains a supported API and continues to receive new model support. It has not been announced as end-of-life, and no shutoff date has been published.
What has changed is default recommendation, not availability. OpenAI is explicit that the Responses API is the recommended starting point for new projects, and that new agentic and multimodal capabilities are designed Responses-first. In practice this means:
- New features sometimes land in the Responses API before, or instead of, Chat Completions.
- OpenAI's own documentation, quickstarts, and cookbook examples default to Responses.
- Chat Completions is positioned as a stable, familiar option for existing integrations — not as a dead end, but not as where new capability shows up first either.
When You'll Still Run Into Chat Completions
Given all of that, here's where you should actually expect to see chat/completions-style code, so you recognize it instead of being confused by it:
Existing production codebases. Any application built before the Responses API existed, or built by a team that simply hasn't migrated, will use messages arrays and client.chat.completions.create(). This is an enormous share of real-world OpenAI code today, and it isn't going anywhere on any fixed timeline.
Framework and library integrations. Some third-party libraries, agent frameworks, and older LangChain-style tooling were built directly against the messages/choices shape of Chat Completions and haven't all finished updating their internals. You'll see this especially in tutorials and packages published before Responses existed.
Tutorials, Stack Overflow answers, and blog posts from before the shift. Search results skew toward whatever was popular when the content was written, not what's current. A two-year-old blog post showing openai.ChatCompletion.create(...) (an even older, pre-1.0 SDK syntax) or client.chat.completions.create(...) is not wrong for its time, but it is not the pattern this course teaches.
Fine-tuning workflows and some evaluation tooling. Certain workflows — particularly around fine-tuning and some legacy evaluation pipelines — were built around the Chat Completions message format and haven't fully moved over.
Deliberate compatibility needs. A team supporting multiple LLM providers behind one interface sometimes standardizes on the messages/choices shape specifically because it's become a de facto industry format that other providers (and OpenAI-compatible APIs) also implement. That's a legitimate engineering trade-off, not a mistake.
How to Tell Which API a Piece of Code Is Using
Since you'll encounter both, here is the fast way to tell them apart at a glance:
| Signal | Chat Completions | Responses |
|---|---|---|
| SDK call | client.chat.completions.create(...) | client.responses.create(...) |
| Conversation parameter | messages=[{"role": ..., "content": ...}] | input=... (string or item list) |
| System-level guidance | A {"role": "system", ...} entry inside messages | A separate instructions=... parameter |
| Reading the reply | response.choices[0].message.content | response.output_text (or walking response.output) |
| Endpoint | /v1/chat/completions | /v1/responses |
That last row is the ground truth if you're ever unsure — check which URL the code (or the error message, if something fails) is actually hitting.
Common Mistakes
Assuming Chat Completions code will "just work" with the Responses client. The two are not interchangeable by swapping the method name. client.responses.create(messages=[...]) will fail, because the Responses API doesn't accept a messages parameter — it wants input and, separately, instructions. Lesson 2 covers exactly how to translate one shape into the other.
Assuming Chat Completions is being shut down imminently. Nothing in OpenAI's current documentation announces a retirement date. Don't panic-migrate a stable production system on that basis — but do default to the Responses API for anything new, since that's where new capability lands first.
Reading response.choices[0].message.content on a Responses API result. That structure doesn't exist on a Response object — you'll get an AttributeError. The Responses API has its own reply shape, output_text and the typed output array, covered in Lesson 3.
Best Practices
Default to the Responses API — client.responses.create() — for everything you build going forward, which is exactly what the rest of this course does. Keep this lesson's comparison table nearby as a translation reference for the times you inherit, read, or need to understand Chat Completions code someone else wrote; being fluent in both shapes, even while you build in one, is a realistic and valuable skill for a working Python developer integrating OpenAI's API.