Tema
Idioma
·4 min de lectura

Responses API vs Chat Completions: qué diferencias hay y cuál usar

Las diferencias prácticas entre /v1/responses y /v1/chat/completions en una API compatible con OpenAI: estructura de la solicitud, historial de conversaciones, herramientas, eventos de streaming y cuál elegir. Todos los ejemplos se ejecutaron en vivo en GetVibe API.

Responses API vs Chat Completions: qué diferencias hay y cuál usar

Las API compatibles con OpenAI ahora tienen dos formatos de solicitud principales: el conocido /v1/chat/completions y el más reciente /v1/responses. GetVibe API acepta ambos con una sola clave y una sola URL base, https://getvibeapi.com/v1. Aquí te explicamos en qué se diferencian en la práctica, cuál elegir y cuál es la única trampa al cambiar de uno a otro.

La versión corta

Chat CompletionsResponses
EndpointPOST /v1/chat/completionsPOST /v1/responses
Entradaun array de messagesinput: una cadena o un array de elementos
Prompt del sistemaun mensaje con el rol systemel campo instructions
Respuestachoices[0].messageun array output: razonamiento, mensaje, llamadas a funciones
Límite de salidamax_tokensmax_output_tokens
Quién lo usala mayoría de los SDK, frameworks y apps de chatCodex CLI y los SDK de agentes más recientes

El formato no cambia el modelo, el precio ni el recuento de tokens: se te cobran los tokens de entrada y salida del modelo en ambos casos.

La misma solicitud en ambos formatos

Chat Completions:

curl https://getvibeapi.com/v1/chat/completions \
  -H "Authorization: Bearer $GETVIBE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-6-luna",
    "messages": [
      {"role": "system", "content": "Responde en una sola oración."},
      {"role": "user", "content": "¿Qué significa HTTP 429?"}
    ],
    "max_tokens": 300
  }'

Responses:

curl https://getvibeapi.com/v1/responses \
  -H "Authorization: Bearer $GETVIBE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-6-luna",
    "instructions": "Responde en una sola oración.",
    "input": "¿Qué significa HTTP 429?",
    "max_output_tokens": 300
  }'

En Chat Completions, el texto está en choices[0].message.content. En Responses se encuentra dentro de output: en los modelos de razonamiento, el primer elemento es un elemento reasoning y la respuesta es el elemento de tipo message. No tienes que recorrer el array manualmente; el SDK de Python tiene una propiedad output_text.

import os
from openai import OpenAI

client = OpenAI(base_url="https://getvibeapi.com/v1", api_key=os.environ["GETVIBE_API_KEY"])

chat = client.chat.completions.create(
    model="gpt-6-luna",
    messages=[{"role": "system", "content": "Responde en una sola oración."},
              {"role": "user", "content": "¿Qué significa HTTP 429?"}],
)
print(chat.choices[0].message.content)

resp = client.responses.create(
    model="gpt-6-luna",
    instructions="Responde en una sola oración.",
    input="¿Qué significa HTTP 429?",
)
print(resp.output_text)

Responses no está limitado a los modelos de OpenAI. Antes de publicar este artículo, enviamos la misma solicitud de Responses a gpt-6-luna, claude-sonnet-5.5 y deepseek-v4.1-flash, y los tres respondieron. DeepSeek devolvió un elemento reasoning antes de su elemento message, exactamente como se describió arriba.

Historial de la conversación: envíalo tú

Esto es lo único que debes saber antes de cambiar. La propia API de Responses de OpenAI puede mantener una conversación en el servidor, por lo que la siguiente solicitud apunta a la anterior mediante previous_response_id. GetVibe API no almacena tus conversaciones, así que previous_response_id no es compatible y store se ignora. Cuando lo probamos, la solicitud fue rechazada con un error 400.

El patrón que funciona es el mismo que con Chat Completions: envía todo el historial en input.

history = [{"role": "user", "content": "Me llamo Ana. Recuérdalo."}]
first = client.responses.create(model="gpt-6-luna", input=history)

history.append({"role": "assistant", "content": first.output_text})
history.append({"role": "user", "content": "¿Cómo me llamo? Una palabra."})
second = client.responses.create(model="gpt-6-luna", input=history)
print(second.output_text)  # Ana

Herramientas: una estructura diferente

Las llamadas a funciones funcionan en ambos formatos, pero la definición de la herramienta tiene un aspecto diferente. En Chat Completions, los campos de la función están anidados dentro de un objeto function; en Responses aparecen directamente en la herramienta. La llamada llega como un elemento function_call independiente, y devuelves el resultado como un elemento function_call_output con el mismo call_id.

import json

tools = [{
    "type": "function",
    "name": "get_weather",
    "description": "Current weather in a city",
    "parameters": {
        "type": "object",
        "properties": {"city": {"type": "string"}},
        "required": ["city"],
        "additionalProperties": False,
    },
}]

items = [{"role": "user", "content": "¿Qué tiempo hace en Denver?"}]
resp = client.responses.create(model="gpt-6-luna", input=items, tools=tools)

for item in resp.output:
    if item.type == "function_call":
        result = {"city": "Denver", "temp_f": 54, "sky": "overcast"}  # tu función
        items.append({"type": "function_call", "call_id": item.call_id,
                      "name": item.name, "arguments": item.arguments})
        items.append({"type": "function_call_output", "call_id": item.call_id,
                      "output": json.dumps(result)})

final = client.responses.create(model="gpt-6-luna", input=items, tools=tools)
print(final.output_text)

En nuestra prueba, el modelo llamó a get_weather con {"city":"Denver"}, y la segunda solicitud respondió que en Denver había 54 °F y estaba nublado. La versión del mismo ciclo con Chat Completions está en nuestra guía de llamadas a funciones.

Streaming

Ambos formatos admiten "stream": true, pero los eventos son diferentes. Chat Completions envía líneas data: uniformes, con cada nuevo fragmento de texto en choices[0].delta.content. Responses envía eventos con nombre: primero response.created, luego response.output_text.delta con los fragmentos de texto y, al final, response.completed. Si analizas el stream por tu cuenta en lugar de hacerlo mediante un SDK, necesitas un parser para el formato específico.

Cuál elegir

  • Chat Completions si ya tienes código que lo usa o si utilizas un framework, una app de chat o una plataforma no-code. Casi todas las herramientas lo admiten, y no hay razón para reescribir código que funciona solo para cambiar de formato.
  • Responses si una herramienta lo requiere. El ejemplo principal es Codex CLI, que se comunica con /v1/responses; la configuración está en la documentación de Codex CLI y en nuestra guía de Codex CLI.

En cualquier caso, la lista de modelos y los precios son los mismos. Consulta la referencia de la API para ver todos los campos y la página de modelos para conocer los precios actuales.

Responses API vs Chat CompletionsOpenAI Responses API/v1/responsesAPI de Chat Completionsprevious_response_idCodex CLI Responses API

Prueba GetVibe API gratis

GPT, Claude, Gemini y más a través de una única API compatible con OpenAI. Paga en USD con tarjeta o criptomonedas.

Artículos relacionados

Responses API vs Chat Completions: qué diferencias hay y cuál usar | GetVibe API