A Deep Dive into OpenAI’s Responses API
While the v1/chat/completions endpoint has been the standard for building conversational AI, OpenAI has introduced a more powerful…
A Deep Dive into OpenAI’s Responses API
While the v1/chat/completions endpoint has been the standard for building conversational AI, OpenAI has introduced a more powerful interface: the Responses API (/v1/responses). The Responses API is the new recommended standard for interacting with OpenAI's models, offering a more structured, transparent, and robust way to work with them.
This technical blog provides a deep dive into the Responses API, comparing it to the Chat Completions API and exploring its advanced features for reasoning and structured data output.
Core Differences: Responses vs. Chat Completions
The two APIs have different design philosophies and capabilities.
The two APIs have different design philosophies and capabilities.
System Prompt
- Chat Completions API: Part of the
messagesarray:{"role": "system", ...} - Responses API: A dedicated top-level
instructionsparameter.
User Input
- Chat Completions API: A list of
messageswithroleandcontent. - Responses API: A list of
inputobjects, allowing more complex, multi-part inputs.
Output Format
- Chat Completions API: A
choicesarray containing amessageobject. - Responses API: A top-level
outputarray designed for structured, multi-part responses.
Reasoning
- Chat Completions API: No explicit support. Requires parsing
logprobs. - Responses API: Built-in support via a dedicated
reasoningparameter.
JSON Output
- Chat Completions API: Supported via
response_format = {"type": "json_object"}. - Responses API: Supported via the
textparameter andresponse.parse()for schema-based parsing.
Here is a comparison of the request structure.
Chat Completions Request:
response = client.chat.completions.create(
model="gpt-4-turbo",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"}
]
)
Responses API Request:
# Note: This uses the newer .responses endpoint
response = client.responses.create(
model="gpt-4-turbo",
instructions="You are a helpful assistant.",
input=[
{"role":"user","content": "Hello!"}
]
)
The separation of instructions from input in the Responses API results in a cleaner request structure.
🚀 Top Remote Tech Jobs — $50–$120/hr
🔥 Multiple Roles Open Hiring Experienced Talent (3+ years) Only.
- Frontend / Backend / Full Stack
- Mobile (iOS/Android)
- AI / ML
- DevOps & Cloud
⏳ Opportunities Fill FAST — Early Applicants Get Priority! 👉 **Apply Here**
Managing Multi-Turn Conversations
With the Responses API, the client is responsible for maintaining the conversational context. This is done by constructing an ordered input list that includes both the user's prompts and the model's previous outputs.
The flow is:
- Make an API call with the user’s first message.
- Take the
outputfrom the response and append it to your context list. - Append the next user message to the context list.
- Make the next API call with the updated context list.
Here is a practical example:
# Initialize conversation context. The 'input' is a list of content blocks.
context = [
{"role": "user", "content": "What is the capital of France?"}
]
# First API call
res1 = client.responses.create(
model="gpt-5-mini",
instructions="You are a helpful travel guide.",
input=context,
)
# The model's response is in the 'output' attribute, which is a list.
assistant_response_1 = res1.output_text
print(f"User: {context[-1]['content']}")
print(f"Assistant: {assistant_response_1}")
# Append the first response's output to the context
context.extend(res1.output)
# Add the next user message
context.append(
{"role": "user","content": "What is its population?"}
)
# Second API call with the full context
res2 = client.responses.create(
model="gpt-5-mini",
instructions="You are a helpful travel guide.",
input=context,
)
assistant_response_2 = res2.output_text
print(f"User: {context[-1]['content']}")
print(f"Assistant: {assistant_response_2}")
This gives you full control over the context the model sees in each turn.
Harnessing Reasoning Models with the Responses API
A key feature of the Responses API is its first-class support for model reasoning. You can ask the model to explain its thought process using the reasoning parameter.
Controlling Reasoning Effort
The effort setting within the reasoning object manages the trade-off between reasoning depth and performance. Reducing reasoning effort can lead to faster responses and fewer tokens used.
Supported values for effort are:
none: (Default) Disables reasoning output.minimal: Provides the least detailed reasoning.low: Offers a basic overview of reasoning steps.medium: A balance between detail and performance.high: Generates a detailed reasoning trace.xhigh: Provides maximum reasoning detail. Use this for complex analyses where understanding the model's thought process is critical.
Reasoning summary
You can also request a summary of the reasoning using the summary key within the reasoning object.
Supported values are:
auto: The model determines the summary detail.concise: A brief summary of the reasoning.detailed: A thorough summary of the steps taken.
Note: The
conciseoption is supported forcomputer-use-previewmodels and all reasoning models aftergpt-5.
Example: Requesting High-Effort Reasoning and a Concise Summary
from typing import List
import os
# from openai import OpenAI
# client = OpenAI()
def get_high_effort_reasoning(client):
"""
Makes a request to the Responses API for high-effort reasoning and a concise summary.
"""
response = client.responses.create(
model="gpt-5.1",
instructions="You are a world-class financial analyst.",
input=[
{"content": "A stock portfolio started at $10,000 and grew 15% in year one, then fell 5% in year two. What is its final value and the net percentage change?"}
],
reasoning={"effort": "high", "summary": "concise"}
)
return response
def get_reasoning_summary(response_output: List[dict]) -> str:
"""
Extracts the reasoning summary text from the model's output.
"""
texts: List[str] = []
for output_item in response_output:
if output_item.type == "reasoning" and hasattr(output_item, 'summary'):
for content in output_item.summary:
if content.type == "summary_text":
texts.append(content.text)
return "".join(texts)
#In a real scenario, you would call get_high_effort_reasoning(client)
response = get_high_effort_reasoning(client)
#To demonstrate, we'll show how to print the details from a mock response.
print(f"Usage: {response.usage}")
print(f"Output Text: {response.output_text}")
print(f"Reasoning Summary: {get_reasoning_summary(response.output)}")
print(f"Instructions: {response.instructions}")
Achieving Structured JSON Output
The Responses API provides two methods for generating JSON output.
Arbitrary JSON
For arbitrary key-value JSON, you can instruct the model to generate JSON and parse it manually. Use client.responses.create with text={ "format": { "type": "json_object"} }.
from pydantic import BaseModel
response = client.responses.create(
model="gpt-4-turbo",
instructions="Extract the user's information from the following text and format it as json ",
input=[
{"role":"system","content":"format the output as json"},
{"role":"user","content": "The user is John Doe, ID 123. He is an active member."}
],
text={ "format": { "type": "json_object"} }
)
print(response.output_text)
Schema-Based JSON
If you need JSON that conforms to a specific schema (e.g., a Pydantic model), use the client.responses.parse() method. This is the recommended approach for structured JSON.
from pydantic import BaseModel
class UserModel(BaseModel):
user_name: str
user_id: str
is_active: bool
response = client.responses.parse(
model="gpt-5-mini",
instructions="Extract the user's information from the following text and format it as JSON.",
input=[
{"content": "The user is John Doe, ID 123. He is an active member."}
],
text_format=UserModel
)
# The response object is an instance of the UserModel
print(response.output_parsed)
Other Important Parameters
store
- Type:
boolean - Optional: Yes
- Defaults to:
true
Set this to false to prevent storing the response for later retrieval. For ZDR organizations, OpenAI enforces store=false.
safety_identifier
- Type:
string - Optional: Yes
A stable, hashed identifier for your end-users to help detect violations of OpenAI’s usage policies. It is recommended to hash a user’s ID or email to avoid sending personally identifying information.
Example: Using store and safety_identifier
import hashlib
def use_store_and_safety_id():
user_email = "example_user@email.com"
hashed_user_id = hashlib.sha256(user_email.encode('utf-8')).hexdigest()
response = client.responses.create(
model="gpt-5-mini",
instructions="You are a helpful assistant.",
input=[
{"content": "Translate 'hello' to French."}
],
store=False,
safety_identifier=hashed_user_id
)
return response
# response = use_store_and_safety_id()
Conclusion
The Responses API is a significant step forward from the Chat Completions API. It provides a more structured and powerful interface for interacting with OpenAI models. For new projects, the Responses API should be your default choice.
Further Reading
If you found this helpful, consider following my profile and signing up for the newsletter. Have thoughts or questions? Share them in the comments below.
Thank you for being a part of the community
Before you go:

👉 Be sure to clap and follow the writer ️👏️️
👉 Follow us: **Linkedin| [Medium](https://medium.com/codetodeploy)**
👉 CodeToDeploy Tech Community is live on Discord — **Join now!**
Note: This Post may contain affiliate links.
메타데이터
- post_id
- d3bc1e6f79d8
- slug
- a-deep-dive-into-openais-responses-api-d3bc1e6f79d8
- url
- https://medium.com/codetodeploy/a-deep-dive-into-openais-responses-api-d3bc1e6f79d8
- canonical_url
- https://medium.com/codetodeploy/a-deep-dive-into-openais-responses-api-d3bc1e6f79d8
- author_url
- https://medium.com/@pi45757
- status
- ok
- fetched_at
- 2026-06-23 17:05:31