Structured Output
Return JSON that follows a schema instead of free-form Markdown.
Use output_schema when you want output.content returned as a JSON object instead of free-form text. This is useful for returning predictable fields, extracting entities, or feeding Research API output into another typed system.
output_schema is supported with standard, deep, exhaustive, and frontier research effort. It is not supported with lite. Sending output_schema with research_effort: "lite" returns 422.
When output_schema is provided, the structured result is returned in output.content and output.content_type is object. Sources remain in output.sources. The API does not add citation fields into your schema object automatically.
Schema Rules
output_schema follows a narrow JSON Schema subset designed for reliable structured generation.
Required rules:
- The root must be an object.
- The root must not use top-level
anyOf. - Every object must define
properties. - Every object must set
additionalProperties: false. - Every property must be listed in
required. To make a field optional, keep it inrequiredand make it nullable—see Optional and Nullable Fields. - Recursive schemas are not supported.
- A property’s type must not be a bare
{"type": "null"}. Use a nullable union such as{"type": ["string", "null"]}instead.
Supported patterns include nested objects, arrays, enums, nested anyOf, and non-recursive $defs and $ref.
Unsupported keywords:
allOfcontainsnotdependentRequireddependentSchemasformatif/then/elsemaxContains/minContainsmaxItems/minItemsmaxLength/minLengthmaxProperties/minPropertiesmaximum/minimummultipleOfpatternpatternPropertiespropertyNamesunevaluatedItems/unevaluatedPropertiesuniqueItems
Selected limits:
If the schema is invalid, the request fails validation before model execution. The schema string budget counts property names, $defs names, enum values, and const values. It applies to schema shape only. Request-level limits such as total task spec size are enforced separately at the request layer.
There is no separate raw byte-size limit on the schema. What matters is the 25,000-character string budget, which counts only property names, $defs names, enum values, and const values—not structural JSON ({}, "type", whitespace). A 30 KB schema file can still pass if its counted strings stay under budget—a much smaller file can fail if it has many long enum values.
A schema is rejected with 422 before any model execution if it exceeds any limit above (depth, property count, enum count, or string budget) or violates a Schema Rule. The error message names the specific limit or rule.
Optional and Nullable Fields
Every property you declare must appear in required. This is what makes structured generation reliable—the model always emits every field—and it matches OpenAI Structured Outputs.
To express a value that may be unknown or not applicable, keep the field in required but make its type nullable by adding "null". The model returns null when the value isn’t available instead of guessing.
Use the concise form (equivalent to string | null):
An anyOf spelling is also valid but more verbose—prefer the concise form above:
A property’s type may not be a bare {"type": "null"} (a field that can only ever be null). Make the field nullable instead, as shown above. A null branch inside an anyOf is fine.
Omitting a field from required produces an invalid schema—the request fails validation before execution. Nullability is the only mechanism for “may be absent.”
Response behavior
- A nullable field with no available value is returned as
null. - A non-nullable required field with no available value forces the model to emit something anyway (typically an empty string
""for strings). Required fields are never omitted from the response, and the model does not fabricate a citation-backed value to fill them. If a field can legitimately be unknown, make it nullable so you get a cleannullinstead of"".
Example
Conditional Structure
Conditional keywords (if / then / else, dependentRequired, dependentSchemas) are not supported. To express “field Y is required only when X”—for example, price_usd is required only when in_stock is true—model the object as a discriminated anyOf union: one branch per case, with a shared field pinned to a distinct value via enum.
When in_stock is true, name is required—when false, only in_stock is allowed. This is the same pattern OpenAI Structured Outputs uses, so one schema works across both.
anyOf may not be used at the schema root—nest the union under a property (or array items), as shown above.
Using Source Control and Structured Output Together
source_control and output_schema can be combined in a single request. For example, you can restrict research to specific domains while requesting a structured response:
The Finance Research API does not support output_schema. If you need structured JSON, use the Research API.