Resultados estruturados em API compatíveis com OpenAI: guia de JSON Schema
Guia prático para aplicar JSON Schema estrito em Responses e Chat Completions, validar resultados, tratar falhas e testar a compatibilidade de cada rota.

Structured Outputs permite pedir JSON conforme a um esquema definido, em vez de apenas dizer ao modelo para «devolver JSON». Numa API compatível com OpenAI, o mesmo JSON Schema pode ser usado com Responses ou Chat Completions, mas o invólucro muda e o suporte deve ser verificado no modelo e na rota exatos.
O padrão seguro de produção tem três camadas: usar um esquema strict quando suportado, analisar e validar novamente o JSON na aplicação e, só então, aplicar regras de negócio determinísticas. A conformidade estrutural reduz erros de formato; não prova correção semântica ou factual.
Structured Outputs não é o mesmo que o modo JSON
| Método | JSON válido | Impõe o esquema | Uso típico |
|---|---|---|---|
| Apenas instruções | Não garantido | Não | Protótipos que toleram falhas de análise |
| Modo JSON | Sim, quando suportado e concluído | Não | JSON flexível validado pela aplicação |
Structured Outputs com strict: true |
Sim, com tratamento da conclusão e de recusas | Sim, no subconjunto suportado | Extração tipada e fluxos da aplicação |
O guia OpenAI Structured Outputs recomenda esta opção em vez do modo JSON quando o modelo e o endpoint a suportam. Um formato estruturado serve para devolver um objeto previsível; Function Calling serve para pedir uma ação à aplicação. Os esquemas podem ser semelhantes, mas os identificadores de chamada e as mensagens de resultado pertencem a outro contrato.
Defina o esquema antes de escolher o endpoint
Uma triagem de suporte precisa de quatro campos:
{
"type": "object",
"properties": {
"category": {
"type": "string",
"enum": ["billing", "technical", "account"]
},
"priority": {
"type": "integer",
"minimum": 1,
"maximum": 3
},
"requires_human": {
"type": "boolean"
},
"summary": {
"type": "string"
}
},
"required": ["category", "priority", "requires_human", "summary"],
"additionalProperties": false
}
Tornar todas as propriedades obrigatórias e usar additionalProperties: false cria um objeto estável. Isso não torna todas as palavras-chave de JSON Schema portáteis. A OpenAI documenta um subconjunto, enquanto outro fornecedor pode implementar um subconjunto diferente ou não disponibilizar um modo de esquema estrito.
Envie o esquema com Responses API
Responses coloca o esquema em text.format:
export MODELFLARE_API_KEY="<YOUR_API_KEY>"
export MODEL_ID="<MODEL_WITH_VERIFIED_STRUCTURED_OUTPUT_SUPPORT>"
curl -sS https://modelflare.dev/v1/responses \
-H "Authorization: Bearer $MODELFLARE_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"model\": \"$MODEL_ID\",
\"input\": \"O cliente foi cobrado duas vezes e pretende um reembolso.\",
\"text\": {
\"format\": {
\"type\": \"json_schema\",
\"name\": \"support_ticket\",
\"schema\": {
\"type\": \"object\",
\"properties\": {
\"category\": {
\"type\": \"string\",
\"enum\": [\"billing\", \"technical\", \"account\"]
},
\"priority\": {
\"type\": \"integer\",
\"minimum\": 1,
\"maximum\": 3
},
\"requires_human\": { \"type\": \"boolean\" },
\"summary\": { \"type\": \"string\" }
},
\"required\": [\"category\", \"priority\", \"requires_human\", \"summary\"],
\"additionalProperties\": false
},
\"strict\": true
}
}
}"
Envie para POST https://modelflare.dev/v1/responses com Authorization: Bearer <YOUR_API_KEY>. O conteúdo aparece em itens de saída tipados. Os SDK podem fornecer funções auxiliares, mas um cliente HTTP deve localizar o texto completo e analisá-lo como JSON; não deve assumir que existe um objeto tipado no nível superior.
Envie o mesmo esquema com Chat Completions
Chat Completions usa response_format.json_schema:
curl -sS https://modelflare.dev/v1/chat/completions \
-H "Authorization: Bearer $MODELFLARE_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"model\": \"$MODEL_ID\",
\"messages\": [
{
\"role\": \"user\",
\"content\": \"O cliente foi cobrado duas vezes e pretende um reembolso.\"
}
],
\"response_format\": {
\"type\": \"json_schema\",
\"json_schema\": {
\"name\": \"support_ticket\",
\"schema\": {
\"type\": \"object\",
\"properties\": {
\"category\": {
\"type\": \"string\",
\"enum\": [\"billing\", \"technical\", \"account\"]
},
\"priority\": {
\"type\": \"integer\",
\"minimum\": 1,
\"maximum\": 3
},
\"requires_human\": { \"type\": \"boolean\" },
\"summary\": { \"type\": \"string\" }
},
\"required\": [\"category\", \"priority\", \"requires_human\", \"summary\"],
\"additionalProperties\": false
},
\"strict\": true
}
}
}"
O JSON normalmente é uma cadeia de texto em choices[0].message.content e ainda precisa de ser analisado.
| Objetivo | Responses API | Chat Completions |
|---|---|---|
| Contentor | text.format |
response_format.json_schema |
| Tipo | text.format.type |
response_format.type |
| Nome | text.format.name |
response_format.json_schema.name |
| Esquema | text.format.schema |
response_format.json_schema.schema |
| Indicador de modo estrito | text.format.strict |
response_format.json_schema.strict |
| Resultado | Itens de saída / função auxiliar | choices[0].message.content |
A camada de compatibilidade da Modelflare converte os invólucros em rotas OpenAI/Codex suportadas, mas não cria Structured Outputs num modelo de origem sem essa capacidade. Nas famílias em que Chat Completions é transmitido sem transformação, o contrato do fornecedor continua a ser a fonte de verdade.
Valide estrutura e significado separadamente
{
"category": "billing",
"priority": 2,
"requires_human": true,
"summary": "O cliente comunica uma cobrança duplicada e pede um reembolso."
}
Validação estrutural
Um validador de JSON Schema confirma propriedades obrigatórias, ausência de propriedades adicionais, tipos, valores enumerados e limites. Mesmo quando o fornecedor promete conformidade estrita, a validação protege contra rotas incompatíveis, erros de integração, conteúdo truncado e alterações futuras.
Validação semântica e de negócio
O esquema não sabe se a cobrança duplicada existiu, se priority: 2 está correto ou quem pode aprovar o reembolso. Trate o objeto como uma classificação proposta, compare-o com dados oficiais e aplique permissões e limites financeiros em código determinístico. Um JSON válido nunca deve contornar a autorização, a faturação ou a segurança.
Trate saídas incompletas e excepcionais
Recusas
Verifique o estado e a representação da recusa antes de procurar JSON. Uma recusa de segurança não é um erro de análise.
Truncamento e limites de saída
Se a geração parar antes do fecho do objeto, o esquema não recupera a parte em falta. Verifique o estado de conclusão e o motivo da paragem, e use um limite de saída suficiente, mas controlado.
Palavras-chave não suportadas
Comece com objetos, arrays, tipos primitivos, valores enumerados, propriedades obrigatórias e regras explícitas para propriedades adicionais. Consulte a documentação antes de usar referências, recursão, uniões complexas ou validação avançada.
Latência do primeiro esquema
Alguns fornecedores pré-processam e guardam um esquema novo em cache. Reutilize esquemas estáveis e versionados e meça a primeira utilização separadamente do regime estável.
Modelo ou rota incompatível
Um endpoint pode aceitar Chat Completions, rejeitar json_schema ou ignorar strict. Um 200 com JSON não prova conformidade estrita. Inclua entradas inválidas e casos-limite.
Execute uma matriz de compatibilidade
| Teste | Evidência |
|---|---|
| Objeto obrigatório mínimo | Estado, modelo, rota, objeto analisado e validação |
| Cada valor enumerado | Produção e análise de todos os valores |
| Informação ausente | Valor limitado ou pedido de esclarecimento |
| Entrada que ativa segurança | Formato da recusa e tratamento |
| Limite de saída baixo | Estado de conclusão e truncamento |
| Funcionalidade não suportada | Erro explícito ou restrição ignorada |
| Invólucros Responses e Chat | Objetos equivalentes na aplicação |
| esquema estável repetido | Primeira utilização contra regime estável |
Mantenha constantes o esquema, as instruções, a região, o modo de streaming e o limite de saída, e registe a data.
Escolha o endpoint após testar o fluxo de trabalho
Responses é adequado para itens de saída tipados, eventos de streaming e fluxos de ferramentas mais amplos. Chat Completions é adequado para uma integração baseada em mensagens quando a rota suporta response_format. Consulte Responses API e Chat Completions.
Em qualquer opção:
- mantenha uma fonte de verdade versionada para JSON Schema;
- altere apenas o invólucro, não o significado;
- valide a resposta completa;
- aplique regras determinísticas depois da estrutura;
- monitorize separadamente análise, recusas, truncamento e compatibilidade.
Para a migração, use o guia de APIs compatíveis com OpenAI; para fluxos incompletos, o guia de streaming de APIs de IA. Consulte Modelos e preços e teste Structured Outputs na rota exata da chave de API.
Structured Outputs torna a resposta uma interface mais fiável, mas não substitui a verificação factual, a autorização nem a lógica de faturação. «Compatível com OpenAI» continua a ser uma afirmação que deve ser testada funcionalidade a funcionalidade.