Structured outputs: JSON schema with output_config.format
To make Claude's reply match a JSON schema, put the schema in output_config.format with type set to json_schema. The response is constrained to that schema, no beta header is needed, and a schema that uses an unsupported feature is rejected with a 400 error.
How it works
You send output_config: {"format": {"type": "json_schema", "schema": {...}}} on a Messages request. Objects in the schema need additionalProperties: false. The deprecated output_format parameter still exists, but it needs the structured-outputs-2025-11-13 beta header and returns a 400 without it.
JSON outputs control what Claude says. Strict tool use, set with strict: true on a tool definition, validates how Claude calls your tools. They are separate features and you can use both in one request.
What the schema cannot contain
Supported keywords include enum, const, anyOf, required, default and internal $ref. Not supported: recursive schemas, numerical constraints such as minimum, maximum and multipleOf, string constraints such as minLength and maxLength, array constraints beyond minItems of 0 or 1, external $ref, and additionalProperties set to anything other than false. Any of these returns a 400 with details.
So a rating field with minimum: 1 and maximum: 5 fails. Drop the bounds and check the range in your own code, or list the allowed values as an enum. A comment tree whose replies holds more comments is recursive, so model it as a flat list with a parent id instead.
Latency, caching and edge cases
The first request with a new schema is slower while the schema compiles into a grammar. Compiled grammars are cached for 24 hours from last use. Changing the schema structure or the set of tools invalidates that cache; changing only name or description fields does not. Changing output_config.format also invalidates the prompt cache for that conversation.
Two stop reasons can still give you output that does not match the schema. With stop_reason: "refusal" the refusal takes precedence over the schema. With stop_reason: "max_tokens" the JSON may be cut off, so retry with a higher max_tokens. Always check stop_reason before parsing.
Where the exam catches people
Believing minimum and maximum are enforced by the schema: numerical constraints are unsupported and the request is rejected.
Believing a slow first request means a prompt cache miss: it is grammar compilation for a schema seen for the first time.
Believing structured outputs can be combined with citations: enabling citations on any document while setting output_config.format returns a 400.
Believing every successful response is valid JSON: a refusal or max_tokens stop can return output that does not match the schema.