Al final de esta guía, podrás llamar a las salidas estructuradas de OpenAI desde tu propio código: pasar un esquema JSON al modelo, activar strict: true y recibir una respuesta que coincida con la forma solicitada. También verás cómo enviar la primera solicitud, leer la respuesta, manejar rechazos o truncamientos y generar colecciones de pruebas de API en Apidog para validar que la carga útil cumple el contrato.
Lo que necesitas antes de empezar
Las salidas estructuradas restringen la generación del modelo para que la respuesta se ajuste a un esquema JSON que tú defines. Cuando envías un esquema con strict: true, el modelo no puede devolver campos fuera de ese contrato: las claves requeridas están presentes, los tipos coinciden y los valores enumerados pertenecen a la lista permitida.
Esto evita depender de prompts como “responde solo con JSON”. Ese enfoque puede funcionar, pero también puede romperse con texto adicional, tipos incorrectos o campos faltantes. Con salidas estructuradas, el contrato pasa de ser una instrucción en lenguaje natural a una restricción aplicada durante la generación.
Para seguir los ejemplos necesitas:
- Una clave API de OpenAI configurada como
OPENAI_API_KEY. - Un modelo que admita aplicación estricta del esquema.
- Un esquema JSON con la forma exacta que esperas recibir.
Elige el modelo adecuado
Las salidas estructuradas están disponibles en modelos recientes de OpenAI, empezando por la familia GPT-4o y continuando con la serie GPT-5. La documentación de OpenAI recomienda iniciar nuevos proyectos con su modelo insignia actual (gpt-5.5 al momento de escribir esto).
Los modelos más antiguos, incluidos los de la era gpt-3.5, pueden admitir modo JSON, pero no necesariamente aplicación estricta del esquema. Si dependes de strict: true, confirma que el ID exacto del modelo lo soporta antes de llevarlo a producción.
Hay dos opciones relacionadas que conviene distinguir:
-
Modo JSON:
response_format: { "type": "json_object" }- Garantiza JSON sintácticamente válido.
- No valida campos, tipos ni claves requeridas.
-
Salidas estructuradas estrictas:
response_formatcontype: "json_schema"ystrict: true- Garantizan JSON válido.
- También garantizan que la salida coincida con tu esquema.
| Modo JSON | Salidas estructuradas estrictas | |
|---|---|---|
| Parámetro | response_format: {"type":"json_object"} |
response_format con type: "json_schema" y strict: true
|
| JSON válido | Sí | Sí |
| Coincide con tu esquema | No | Sí |
| Campos requeridos aplicados | No | Sí |
| Tipos y enumeraciones aplicados | No | Sí |
| Validación descendente | Siempre necesaria | Recomendable |
Nota: Chat Completions usa
response_format. La API de Responses expresa lo mismo bajotext.formatcontype: "json_schema". Las reglas del esquema son las mismas; cambia el envoltorio del endpoint.
Haz tu primera solicitud
Supongamos que quieres extraer un ticket de soporte desde texto libre y convertirlo en un registro tipado.
Ejemplo con Chat Completions:
curl https://api.openai.com/v1/chat/completions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.5",
"messages": [
{ "role": "system", "content": "Extract the ticket into the schema." },
{ "role": "user", "content": "My checkout 500s every time I use a saved card. Started today. Account: acct_8842." }
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "support_ticket",
"strict": true,
"schema": {
"type": "object",
"properties": {
"summary": { "type": "string" },
"category": { "type": "string", "enum": ["billing", "bug", "account", "other"] },
"severity": { "type": "integer" },
"account_id": {
"anyOf": [ { "type": "string" }, { "type": "null" } ]
}
},
"required": ["summary", "category", "severity", "account_id"],
"additionalProperties": false
}
}
}
}'
Lee la respuesta
El modelo devuelve un mensaje cuyo content es una cadena JSON que coincide con el esquema:
{
"summary": "Checkout returns HTTP 500 when paying with a saved card",
"category": "bug",
"severity": 3,
"account_id": "acct_8842"
}
Observa account_id: usa anyOf con null. Esa es la forma práctica de modelar un campo que puede no tener valor.
Mantente dentro del subconjunto compatible de JSON Schema
Las salidas estructuradas aceptan un subconjunto de JSON Schema. OpenAI limita el conjunto para poder aplicar las restricciones de forma confiable y cachear el esquema compilado.
Reglas importantes:
- La raíz debe ser un objeto. No uses un array o string como nivel superior. Si necesitas una lista, envuélvela:
{
"items": []
}
Cada propiedad debe estar en
required.
No existe un campo opcional clásico. Para representar ausencia, usaanyOfconnull.Usa
additionalProperties: falseen cada objeto.
Esto impide que el modelo invente claves adicionales.Evita esquemas demasiado grandes o profundos.
Un esquema puede contener aproximadamente 100 propiedades de objeto y hasta 5 niveles de anidamiento. Aplana cuando sea posible.No todas las palabras clave de validación se aplican.
Palabras comopattern,format,minLengthominimumno están garantizadas por el modelo. Si necesitas validar una expresión regular, un rango numérico o un formato concreto, hazlo después de recibir la respuesta.La primera llamada puede ser más lenta.
El primer uso de un esquema nuevo requiere compilación. Después se cachea y las siguientes llamadas suelen ser más rápidas.
“JSON garantizado” no significa “dato de negocio garantizado”. La estructura está bloqueada, pero los valores internos aún deben validarse. Si ya has trabajado con campos opcionales o uniones con oneOf/anyOf/allOf, el modelo mental es el mismo: el esquema restringe la forma; tus pruebas validan los valores.
Maneja rechazos y truncamientos
Hay casos donde la respuesta no coincidirá con tu esquema de forma intencional.
Si el modelo rechaza una solicitud insegura, devuelve un campo refusal en el mensaje en lugar del contenido con la forma esperada. Tu código debe comprobarlo antes de parsear JSON.
Ejemplo en Python:
import json
msg = response.choices[0].message
if msg.refusal:
handle_refusal(msg.refusal)
else:
ticket = json.loads(msg.content)
También debes contemplar estos casos:
-
Truncamiento por
max_tokens: el JSON puede quedar incompleto. -
Llamadas a herramientas paralelas: las salidas estructuradas no las admiten. Si combinas herramientas con salidas estructuradas, configura
parallel_tool_callsenfalse.
Cómo probarlo en Apidog
El modo estricto aplica el esquema durante la generación, pero no reemplaza tus pruebas. Los modelos cambian, los prompts se editan, los esquemas evolucionan y las rutas de rechazo pueden modificarse.
Ahí es donde Apidog encaja: valida la respuesta recibida contra el esquema esperado para detectar desviaciones antes de producción.
División de responsabilidades:
- OpenAI produce JSON válido según el esquema cuando usas
strict: true. - Apidog valida la respuesta real contra tu contrato esperado.
- Tus pruebas fallan si la carga útil deja de cumplir el esquema.
Flujo recomendado:
Crea la solicitud.
Construye la llamada a Chat Completions en Apidog, incluyendo el bloqueresponse_format. Guárdala en una colección para repetirla.-
Añade aserciones.
Verifica que:-
categoryesté dentro de los valores permitidos. -
severitysea un entero. -
account_idsea string onull. - No existan propiedades inesperadas.
-
También puedes validar la respuesta contra un esquema JSON y reutilizar el mismo contrato que pasas a OpenAI.
Ejecútalo en CI.
Incluye la colección en tu pipeline. Cada cambio de prompt, modelo o esquema vuelve a comprobar la conformidad.Simula el contrato.
Antes de conectar la llamada real, crea una API simulada que devuelva respuestas válidas según el esquema. Así puedes probar frontends, workers o consumidores descendentes sin gastar tokens.
Este último punto es especialmente útil: puedes desarrollar todo lo que consume la salida estructurada contra un mock estable y reemplazarlo por la llamada real cuando la integración esté lista. Descarga Apidog para construir la solicitud, las aserciones y el mock en un solo lugar.
Preguntas frecuentes
¿El modo JSON está obsoleto ahora que existen las salidas estructuradas?
No. El modo JSON sigue funcionando y garantiza JSON válido. Simplemente no aplica un esquema. Para código nuevo, las salidas estructuradas con strict: true son una opción más robusta cuando tienes una forma fija.
¿La raíz de mi esquema puede ser un array?
No. El nivel superior debe ser un objeto. Si necesitas devolver una lista, envuélvela en una propiedad:
{
"items": []
}
Luego incluye items en required.
¿Cómo hago que un campo sea opcional?
No uses opcionales clásicos. En salidas estructuradas, todas las propiedades deben estar en required. Modela la ausencia con null:
{
"account_id": {
"anyOf": [
{ "type": "string" },
{ "type": "null" }
]
}
}
La clave siempre existe; el valor puede ser null.
¿Puedo omitir la validación si uso strict: true?
Puedes reducir validaciones de forma, pero no deberías eliminar todas las pruebas. El modelo no garantiza reglas como pattern, format o rangos numéricos, y aún debes manejar rechazos o truncamientos.
Si necesitas repasar los fundamentos, esta introducción a JSON Schema cubre los bloques principales.
¿Qué modelos debo usar?
Usa modelos que soporten salidas estructuradas estrictas. Funcionan en GPT-4o y posteriores, incluida la serie GPT-5. Confirma siempre el ID exacto del modelo antes de confiar en strict: true.
Conclusión
El flujo completo queda así:
- Elige un modelo compatible con salidas estructuradas.
- Envía una solicitud con
json_schemaystrict: true. - Mantén tu esquema dentro del subconjunto soportado.
- Maneja
refusal, truncamientos y límites de herramientas. - Valida la respuesta en tus pruebas y CI.
El modelo promete la forma. Tus pruebas demuestran que esa forma se mantiene. Puedes hacerlo en Apidog: construye la solicitud, valida la respuesta contra tu esquema y crea mocks para que el resto de tu sistema avance mientras la integración se estabiliza.

Top comments (0)