Migrate to the Responses API
import { CheckCircleFilled, XCircle, } from "@components/react/oai/platform/ui/Icon.react";
The Responses API is our new API primitive, an evolution of Chat Completions which brings added simplicity and powerful agentic primitives to your integrations.
While Chat Completions remains supported, Responses is recommended for all new projects.
About the Responses API
The Responses API is a unified interface for building powerful, agent-like applications. It contains:
- Built-in tools like web search, file search , computer use, code interpreter, and remote MCPs.
- Seamless multi-turn interactions that allow you to pass previous responses for higher accuracy reasoning results.
- Native multimodal support for text and images.
Responses benefits
The Responses API contains several benefits over Chat Completions:
- Better performance: Using reasoning models, like GPT-5, with Responses will result in better model intelligence when compared to Chat Completions. Our internal evals reveal a 3% improvement in SWE-bench with same prompt and setup.
- Agentic by default: The Responses API is an agentic loop, allowing the model to call multiple tools, like
web_search,image_generation,file_search,code_interpreter, remote MCP servers, as well as your own custom functions, within the span of one API request. - Lower costs: Results in lower costs due to improved cache utilization (40% to 80% improvement when compared to Chat Completions in internal tests).
- Stateful context: Use
store: trueto maintain state from turn to turn, preserving reasoning and tool context from turn-to-turn. - Flexible inputs: Pass a string with input or a list of messages; use instructions for system-level guidance.
- Encrypted reasoning: Opt-out of statefulness while still benefiting from advanced reasoning.
- Future-proof: Future-proofed for upcoming models.
| Capabilities | Chat Completions API | Responses API |
|---|---|---|
| Text generation | ||
| Audio | Coming soon | |
| Vision | ||
| Structured Outputs | ||
| Function calling | ||
| Web search | ||
| File search | ||
| Computer use | ||
| Code interpreter | ||
| MCP | ||
| Image generation | ||
| Reasoning summaries |
Examples
See how the Responses API compares to the Chat Completions API in specific scenarios.
Messages vs. Items
Both APIs make it easy to generate output from our models. The input to, and result of, a call to Chat completions is an array of Messages, while
the Responses API uses Items. An Item is a union of many types, representing the range of possibilities
of model actions. A message is a type of Item, as is a function_call or function_call_output. Unlike a Chat Completions Message, where
many concerns are glued together into one object, Items are distinct from one another and better represent the basic unit of model context.
Additionally, Chat Completions can return multiple parallel generations as choices, using the n param. In Responses, we've removed this param, leaving only one generation.
When you get a response back from the Responses API, the fields differ slightly.
Instead of a message, you receive a typed response object with its own id.
Responses are stored by default. Chat completions are stored by default for new accounts.
To disable storage when using either API, set store: false.
The objects you receive back from these APIs will differ slightly. In Chat Completions, you receive an array of
choices, each containing a message. In Responses, you receive an array of Items labeled output.
Additional differences
- Responses are stored by default. Chat completions are stored by default for new accounts. To disable storage in either API, set
store: false. - Reasoning models have a richer experience in the Responses API with improved tool usage. Starting with GPT-5.4, tool calling is not supported in Chat Completions with
reasoning: none. - Structured Outputs API shape is different. Instead of
response_format, usetext.formatin Responses. Learn more in the Structured Outputs guide. - The function-calling API shape is different, both for the function config on the request, and function calls sent back in the response. See the full difference in the function calling guide.
- The Responses SDK has an
output_texthelper, which the Chat Completions SDK does not have. - In Chat Completions, conversation state must be managed manually. The Responses API has compatibility with the Conversations API for persistent conversations, or the ability to pass a
previous_response_idto easily chain Responses together.
Migrating from Chat Completions
1. Update generation endpoints
Start by updating your generation endpoints from post /v1/chat/completions to post /v1/responses.
If you are not using functions or multimodal inputs, then you're done! Simple message inputs are compatible from one API to the other:
Web search tool
INPUT='[
{ "role": "system", "content": "You are a helpful assistant." },
{ "role": "user", "content": "Hello!" }
]'
curl -s https://api.openai.com/v1/chat/completions \\
-H "Content-Type: application/json" \\
-H "Authorization: Bearer $OPENAI_API_KEY" \\
-d "{
\\"model\\": \\"gpt-5.5\\",
\\"messages\\": $INPUT
}"
curl -s https://api.openai.com/v1/responses \\
-H "Content-Type: application/json" \\
-H "Authorization: Bearer $OPENAI_API_KEY" \\
-d "{
\\"model\\": \\"gpt-5.5\\",
\\"input\\": $INPUT
}"
const context = [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Hello!' }
];
const completion = await client.chat.completions.create({
model: 'gpt-5.5',
messages: context
});
const response = await client.responses.create({
model: "gpt-5.5",
input: context
});
context = [
{ "role": "system", "content": "You are a helpful assistant." },
{ "role": "user", "content": "Hello!" }
]
completion = client.chat.completions.create(
model="gpt-5.5",
messages=context
)
response = client.responses.create(
model="gpt-5.5",
input=context
)
Generate text from a model
import OpenAI from 'openai';
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const completion = await client.chat.completions.create({
model: 'gpt-5.5',
messages: [
{ 'role': 'system', 'content': 'You are a helpful assistant.' },
{ 'role': 'user', 'content': 'Hello!' }
]
});
console.log(completion.choices[0].message.content);
from openai import OpenAI
client = OpenAI()
completion = client.chat.completions.create(
model="gpt-5.5",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"}
]
)
print(completion.choices[0].message.content)
curl https://api.openai.com/v1/chat/completions \\
-H "Content-Type: application/json" \\
-H "Authorization: Bearer $OPENAI_API_KEY" \\
-d '{
"model": "gpt-5.5",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"}
]
}'
</>
Generate text from a model
import OpenAI from 'openai';
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const response = await client.responses.create({
model: 'gpt-5.5',
instructions: 'You are a helpful assistant.',
input: 'Hello!'
});
console.log(response.output_text);
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-5.5",
instructions="You are a helpful assistant.",
input="Hello!"
)
print(response.output_text)
curl https://api.openai.com/v1/responses \\
-H "Content-Type: application/json" \\
-H "Authorization: Bearer $OPENAI_API_KEY" \\
-d '{
"model": "gpt-5.5",
"instructions": "You are a helpful assistant.",
"input": "Hello!"
}'
</>
2. Update item definitions
Generate text from a model
import OpenAI from 'openai';
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const completion = await client.chat.completions.create({
model: 'gpt-5.5',
messages: [
{ 'role': 'system', 'content': 'You are a helpful assistant.' },
{ 'role': 'user', 'content': 'Hello!' }
]
});
console.log(completion.choices[0].message.content);
from openai import OpenAI
client = OpenAI()
completion = client.chat.completions.create(
model="gpt-5.5",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"}
]
)
print(completion.choices[0].message.content)
curl https://api.openai.com/v1/chat/completions \\
-H "Content-Type: application/json" \\
-H "Authorization: Bearer $OPENAI_API_KEY" \\
-d '{
"model": "gpt-5.5",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"}
]
}'
</>
Generate text from a model
import OpenAI from 'openai';
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const response = await client.responses.create({
model: 'gpt-5.5',
instructions: 'You are a helpful assistant.',
input: 'Hello!'
});
console.log(response.output_text);
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-5.5",
instructions="You are a helpful assistant.",
input="Hello!"
)
print(response.output_text)
curl https://api.openai.com/v1/responses \\
-H "Content-Type: application/json" \\
-H "Authorization: Bearer $OPENAI_API_KEY" \\
-d '{
"model": "gpt-5.5",
"instructions": "You are a helpful assistant.",
"input": "Hello!"
}'
</>
3. Update multi-turn conversations
If you have multi-turn conversations in your application, update your context logic.
Multi-turn conversation
let messages = [
{ 'role': 'system', 'content': 'You are a helpful assistant.' },
{ 'role': 'user', 'content': 'What is the capital of France?' }
];
const res1 = await client.chat.completions.create({
model: 'gpt-5.5',
messages
});
messages = messages.concat([res1.choices[0].message]);
messages.push({ 'role': 'user', 'content': 'And its population?' });
const res2 = await client.chat.completions.create({
model: 'gpt-5.5',
messages
});
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is the capital of France?"}
]
res1 = client.chat.completions.create(model="gpt-5.5", messages=messages)
messages += [res1.choices[0].message]
messages += [{"role": "user", "content": "And its population?"}]
res2 = client.chat.completions.create(model="gpt-5.5", messages=messages)
</>
Multi-turn conversation
context = [
{ "role": "user", "content": "What is the capital of France?" }
]
res1 = client.responses.create(
model="gpt-5.5",
input=context,
)
# Append the first response's output to context
context += res1.output
# Add the next user message
context += [
{ "role": "user", "content": "And its population?" }
]
res2 = client.responses.create(
model="gpt-5.5",
input=context,
)
let context = [
{ role: "user", content: "What is the capital of France?" }
];
const res1 = await client.responses.create({
model: "gpt-5.5",
input: context,
});
// Append the first response’s output to context
context = context.concat(res1.output);
// Add the next user message
context.push({ role: "user", content: "And its population?" });
const res2 = await client.responses.create({
model: "gpt-5.5",
input: context,
});
As a simplification, we've also built a way to simply reference inputs and outputs from a previous response by passing its id.
You can use `previous_response_id` to form chains of responses that build upon one other or create forks in a history.
Multi-turn conversation
const res1 = await client.responses.create({
model: 'gpt-5.5',
input: 'What is the capital of France?',
store: true
});
const res2 = await client.responses.create({
model: 'gpt-5.5',
input: 'And its population?',
previous_response_id: res1.id,
store: true
});
res1 = client.responses.create(
model="gpt-5.5",
input="What is the capital of France?",
store=True
)
res2 = client.responses.create(
model="gpt-5.5",
input="And its population?",
previous_response_id=res1.id,
store=True
)
</>
### 4. Decide when to use statefulness
Some organizations—such as those with Zero Data Retention (ZDR) requirements—cannot use the Responses API in a stateful way due to compliance or data retention policies. To support these cases, OpenAI offers encrypted reasoning items, allowing you to keep your workflow stateless while still benefiting from reasoning items.
To disable statefulness, but still take advantage of reasoning:
- set `store: false` in the [store field](https://developers.openai.com/api/docs/api-reference/responses/create#responses_create-store)
- add `["reasoning.encrypted_content"]` to the [include field](https://developers.openai.com/api/docs/api-reference/responses/create#responses_create-include)
The API will then return an encrypted version of the reasoning tokens, which you can pass back in future requests just like regular reasoning items.
For ZDR organizations, OpenAI enforces store=false automatically. When a request includes encrypted_content, it is decrypted in-memory (never written to disk), used for generating the next response, and then securely discarded. Any new reasoning tokens are immediately encrypted and returned to you, ensuring no intermediate state is ever persisted.
### 5. Update function definitions
There are two minor, but notable, differences in how functions are defined between Chat Completions and Responses.
1. In Chat Completions, functions are defined using externally tagged polymorphism, whereas in Responses, they are internally-tagged.
2. In Chat Completions, functions are non-strict by default, whereas in the Responses API, functions _are_ strict by default.
The Responses API function example on the right is functionally equivalent to the Chat Completions example on the left.
#### Follow function-calling best practices
In Responses, tool calls and their outputs are two distinct types of Items that are correlated using a `call_id`. See
the [tool calling docs](https://developers.openai.com/api/docs/guides/function-calling#function-tool-example) for more detail on how function calling works in Responses.
### 6. Update Structured Outputs definition
In the Responses API, defining structured outputs have moved from `response_format` to `text.format`:
curl https://api.openai.com/v1/chat/completions \\
-H "Content-Type: application/json" \\
-H "Authorization: Bearer $OPENAI_API_KEY" \\
-d '{
"model": "gpt-5.5",
"messages": [
{
"role": "user",
"content": "Jane, 54 years old"
}
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "person",
"strict": true,
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"age": {
"type": "number",
"minimum": 0,
"maximum": 130
}
},
"required": [
"name",
"age"
],
"additionalProperties": false
}
}
},
"reasoning_effort": "medium"
}'
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-5.5",
messages=[
{
"role": "user",
"content": "Jane, 54 years old",
}
],
response_format={
"type": "json_schema",
"json_schema": {
"name": "person",
"strict": True,
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"age": {
"type": "number",
"minimum": 0,
"maximum": 130
}
},
"required": [
"name",
"age"
],
"additionalProperties": False
}
}
},
reasoning_effort="medium"
)
const completion = await openai.chat.completions.create({
model: "gpt-5.5",
messages: [
{
"role": "user",
"content": "Jane, 54 years old",
}
],
response_format: {
type: "json_schema",
json_schema: {
name: "person",
strict: true,
schema: {
type: "object",
properties: {
name: {
type: "string",
minLength: 1
},
age: {
type: "number",
minimum: 0,
maximum: 130
}
},
required: [
"name",
"age"
],
additionalProperties: false
}
}
},
reasoning_effort: "medium"
});
curl https://api.openai.com/v1/responses \\
-H "Content-Type: application/json" \\
-H "Authorization: Bearer $OPENAI_API_KEY" \\
-d '{
"model": "gpt-5.5",
"input": "Jane, 54 years old",
"text": {
"format": {
"type": "json_schema",
"name": "person",
"strict": true,
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"age": {
"type": "number",
"minimum": 0,
"maximum": 130
}
},
"required": [
"name",
"age"
],
"additionalProperties": false
}
}
}
}'
response = client.responses.create(
model="gpt-5.5",
input="Jane, 54 years old",
text={
"format": {
"type": "json_schema",
"name": "person",
"strict": True,
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"age": {
"type": "number",
"minimum": 0,
"maximum": 130
}
},
"required": [
"name",
"age"
],
"additionalProperties": False
}
}
}
)
const response = await openai.responses.create({
model: "gpt-5.5",
input: "Jane, 54 years old",
text: {
format: {
type: "json_schema",
name: "person",
strict: true,
schema: {
type: "object",
properties: {
name: {
type: "string",
minLength: 1
},
age: {
type: "number",
minimum: 0,
maximum: 130
}
},
required: [
"name",
"age"
],
additionalProperties: false
}
},
}
});
### 7. Upgrade to native tools
If your application has use cases that would benefit from OpenAI's native [tools](https://developers.openai.com/api/docs/guides/tools), you can update your tool calls to use OpenAI's tools out of the box.
async function web_search(query) {
const fetch = (await import('node-fetch')).default;
const res = await fetch(\`https://api.example.com/search?q=\${query}\`);
const data = await res.json();
return data.results;
}
const completion = await client.chat.completions.create({
model: 'gpt-5.5',
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Who is the current president of France?' }
],
functions: [
{
name: 'web_search',
description: 'Search the web for information',
parameters: {
type: 'object',
properties: { query: { type: 'string' } },
required: ['query']
}
}
]
});
import requests
def web_search(query):
r = requests.get(f"https://api.example.com/search?q={query}")
return r.json().get("results", [])
completion = client.chat.completions.create(
model="gpt-5.5",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Who is the current president of France?"}
],
functions=[
{
"name": "web_search",
"description": "Search the web for information",
"parameters": {
"type": "object",
"properties": {"query": {"type": "string"}},
"required": ["query"]
}
}
]
)
curl https://api.example.com/search \\
-G \\
--data-urlencode "q=your+search+term" \\
--data-urlencode "key=$SEARCH_API_KEY"\
</>
Web search tool
const answer = await client.responses.create({
model: 'gpt-5.5',
input: 'Who is the current president of France?',
tools: [{ type: 'web_search' }]
});
console.log(answer.output_text);
answer = client.responses.create(
model="gpt-5.5",
input="Who is the current president of France?",
tools=[{"type": "web_search"}]
)
print(answer.output_text)
curl https://api.openai.com/v1/responses \\
-H "Content-Type: application/json" \\
-H "Authorization: Bearer $OPENAI_API_KEY" \\
-d '{
"model": "gpt-5.5",
"input": "Who is the current president of France?",
"tools": [{"type": "web_search"}]
}'
</>
Incremental migration
The Responses API is a superset of the Chat Completions API, and Chat Completions remains supported. You can migrate one user flow at a time:
- Start with a simple text-generation flow and update the endpoint, input, and output handling.
- Update multi-turn state management, then migrate function calling and Structured Outputs.
- For streaming flows, update consumers to handle typed Responses events such as
response.output_text.delta. See the streaming Responses guide. - Compare behavior, latency, and errors before routing more traffic to Responses.
We recommend migrating all flows to the Responses API over time to take advantage of the latest OpenAI features and improvements.
Assistants API
Based on developer feedback from the Assistants API beta, we've incorporated key improvements into the Responses API to make it more flexible, faster, and easier to use. The Responses API represents the future direction for building agents on OpenAI.
We now have Assistant-like and Thread-like objects in the Responses API. Learn more in the migration guide. As of August 26th, 2025, we're deprecating the Assistants API, with a sunset date of August 26, 2026.