> ## Documentation Index
> Fetch the complete documentation index at: https://docs.inputapi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Structured output

> Read typed JSON and handle refusal, truncation, and validation failures.

## Choose an output mode

| Mode | When to use it | Application responsibilities |
| - | - | - |
| Ask for JSON in a text prompt | Best-effort fallback when no dedicated JSON mode is available | Handle Markdown wrappers or non-JSON text |
| `response_format.type: json_object` | The model supports JSON mode | Explicitly request JSON and validate fields and types |
| `response_format.type: json_schema` | The model and channel support structured output | Check completion, refusal, business rules, and the supported Schema subset |

A compatible endpoint does not imply `json_schema` support for every model. Test the target model with a minimal Schema. Resolve unsupported-parameter errors before changing modes; avoid silently accepting invalid business data after a fallback.

## Runnable example: extract a product

Complete the [TypeScript SDK setup](/en/guides/typescript.md). Save as `structured-output.mts` and run `node structured-output.mts`. The example requests a product name and quantity using strict Schema, then independently checks a nonempty name and a nonnegative safe integer quantity.

```typescript theme={null}
import OpenAI from 'openai';

const { API_BASE_URL, API_KEY, API_MODEL } = process.env;
if (!API_BASE_URL || !API_KEY || !API_MODEL) {
  throw new Error('Set API_BASE_URL, API_KEY, and API_MODEL first.');
}
const client = new OpenAI({
  baseURL: API_BASE_URL.replace(/\/+$/, ''),
  apiKey: API_KEY,
  timeout: 60_000,
  maxRetries: 0,
});

try {
  const result = await client.chat.completions.create({
    model: API_MODEL,
    messages: [{ role: 'user', content: 'Extract the product: three notebooks.' }],
    response_format: {
      type: 'json_schema',
      json_schema: {
        name: 'product',
        strict: true,
        schema: {
          type: 'object',
          properties: { name: { type: 'string' }, quantity: { type: 'integer' } },
          required: ['name', 'quantity'],
          additionalProperties: false,
        },
      },
    },
  });
  const choice = result.choices[0];
  if (!choice || choice.finish_reason !== 'stop' || choice.message.refusal
    || choice.message.tool_calls?.length || !choice.message.content) {
    throw new Error('No complete structured output.');
  }
  const product = JSON.parse(choice.message.content);
  if (!product || Array.isArray(product) || Object.keys(product).length !== 2
    || typeof product.name !== 'string' || !product.name.trim()
    || !Number.isSafeInteger(product.quantity) || product.quantity < 0) {
    throw new Error('Invalid product data.');
  }
  console.log(JSON.stringify(product));
} catch (error) {
  console.error(error instanceof OpenAI.APIError && error.status
    ? `Request failed (HTTP ${error.status}). Check the request logs.`
    : 'Invalid or incomplete structured output. Check the request logs.');
  process.exitCode = 1;
}
```

An example successful output shape:

```json theme={null}
{"name":"notebooks","quantity":3}
```

The exact product wording can vary. Valid JSON does not establish factual correctness; check allowed products, ranges, and business operations too. For larger objects, use an existing JSON Schema validator or data-model library instead of manual field checks.

## Handle failures

* `finish_reason=length`: the output may be truncated; do not repair the JSON and treat it as complete.
* `message.refusal` or absent content: use a refusal/failure branch before parsing.
* Unsupported Schema or failed validation: retain a failed state, inspect the request and model capabilities, and avoid unbounded retries.
* Streaming: JSON fragments generally cannot be parsed separately. Confirm completion before parsing the full text; discard interrupted structured results.

OpenAI-style strict Schema generally requires `additionalProperties: false` on objects and properties listed in `required`. Nullable fields need an appropriate Schema and support from the selected model.

## Responses uses a different field

Chat Completions uses `response_format: {type: "json_schema", json_schema: {...}}`. Responses uses `text: {format: {type: "json_schema", name, schema, strict}}`. Do not copy `response_format` unchanged into a Responses request.

[API parameters](/en/api-reference/chat-completions.md) · [Errors and retries](/en/guides/errors.md)

## TypeScript: structured extraction with Responses

Save as `responses-structured.mts`, configure the [TypeScript SDK](/en/guides/typescript.md), and run `node responses-structured.mts`. The channel must support strict Schema through Responses `text.format`; Chat Completions support alone does not establish this capability.

```typescript theme={null}
import OpenAI from 'openai';

const { API_BASE_URL, API_KEY, API_MODEL } = process.env;
if (!API_BASE_URL || !API_KEY || !API_MODEL) {
  throw new Error('Set API_BASE_URL, API_KEY, and API_MODEL first.');
}
const client = new OpenAI({
  baseURL: API_BASE_URL.replace(/\/+$/, ''), apiKey: API_KEY,
  timeout: 60_000, maxRetries: 0,
});

try {
  const result = await client.responses.create({
    model: API_MODEL,
    input: 'Extract the product: three notebooks.',
    text: {
      format: {
        type: 'json_schema', name: 'product', strict: true,
        schema: {
          type: 'object',
          properties: { name: { type: 'string' }, quantity: { type: 'integer' } },
          required: ['name', 'quantity'], additionalProperties: false,
        },
      },
    },
  });
  if (result.status !== 'completed' || !result.output_text.trim()) {
    throw new Error('No complete structured output.');
  }
  for (const item of result.output) {
    if (item.type === 'reasoning') continue;
    if (item.type !== 'message' || item.status !== 'completed'
      || item.content.some((part) => part.type !== 'output_text')) {
      throw new Error('Refusal or unexpected output.');
    }
  }
  const product = JSON.parse(result.output_text);
  if (!product || Array.isArray(product) || Object.keys(product).length !== 2
    || typeof product.name !== 'string' || !product.name.trim()
    || !Number.isSafeInteger(product.quantity) || product.quantity < 0) {
    throw new Error('Invalid product data.');
  }
  console.log(JSON.stringify(product));
} catch (error) {
  console.error(error instanceof OpenAI.APIError && error.status
    ? `Request failed (HTTP ${error.status}). Check the request logs.`
    : 'Invalid or incomplete structured output. Check the request logs.');
  process.exitCode = 1;
}
```

The successful structure matches the Chat example: a product name and a nonnegative safe-integer quantity. Before parsing, this example checks response and message completion, rejects refusals, tool calls, and empty text, then validates JSON and business fields. A refusal may appear in `output[].content[]` even when the overall status is `completed`.

Reference: [OpenAI structured outputs](https://developers.openai.com/api/docs/guides/structured-outputs).

[简体中文](/zh/guides/structured-output.md)

## Complete JSON-mode example

[JSON mode and result validation](/en/guides/json-mode.md) adds Chat / Responses json\_object examples, required nullable fields, integer ranges, and failure short-circuiting. It complements this page's json\_schema examples.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.