Structured output and JSON Schema support by provider
What each provider's structured outputs accept of a JSON Schema, their limits, and what happens to a schema on the way through Salyro, with sources.
The table has two kinds of row, and the Evidence column says which each one is. They are never mixed.
- Provider's page: a rule the provider documents for the JSON Schema its structured outputs accept. The rule covers a response schema and a strict tool (a tool with
strict: true), or a tool withoutstrict. Each row quotes the page and gives the day it was read. A provider whose page could not be read has one row, marked unknown. Its rules are not filled in from memory. - Measured through Salyro: what Salyro's engine recorded happening to a schema on the way through its pinned proxy. These rows describe requests sent through Salyro, never the provider called directly. They come from the engine's own tables, regenerated with the rest of the catalogue.
The statuses are words, not colours. Rejected means the request is refused, usually with a 400: by the provider, as its page says, or by Salyro on a measured row. Unsupported means the page lists the feature as not supported without saying the request is refused. Not enforced or not guaranteed means the request is accepted and the schema, or part of it, is not held to. Removed means Salyro's proxy drops the keyword before the request is sent. Documented means the page gives a value, such as a limit or a list of keywords, rather than a verdict; the value is in its own column. Unknown means nobody could read the page. A keyword no page mentions has no row: whether it is accepted is unknown.
The limits count across every strict schema in one request, not per schema. To check a schema of your own against each provider and see what would change, use the JSON Schema compatibility checker. It runs in your browser and reads the same rules as this table.
Search by rule or keyword, filter by provider, evidence, scope or status, and download the rows you see as CSV.
37 rows
| Where these rules apply | Anthropic | Provider’s page | JSON output and strict tools | documented | response_ | Under "JSON Schema limitations" the page states: "Structured outputs support standard JSON Schema with some limitations. Both JSON outputs and strict tool use share these limitations." JSON outputs are `output_config.format`; strict tool use is a tool with `strict: true`. | platform.claude.com/docs/en/build-with-claude/structured-outputs (read 2026-09-25) |
|---|---|---|---|---|---|---|---|
| Numerical constraints (minimum, maximum, multipleOf) | Anthropic | Provider’s page | JSON output and strict tools | rejected | — | Listed under "Not supported": "Numerical constraints (such as `minimum`, `maximum`, `multipleOf`)" "If you use an unsupported feature, you'll receive a 400 error with details." | platform.claude.com/docs/en/build-with-claude/structured-outputs (read 2026-09-25) |
| String length (minLength, maxLength) | Anthropic | Provider’s page | JSON output and strict tools | rejected | — | Listed under "Not supported": "String constraints (`minLength`, `maxLength`)" "If you use an unsupported feature, you'll receive a 400 error with details." | platform.claude.com/docs/en/build-with-claude/structured-outputs (read 2026-09-25) |
| Array constraints beyond minItems 0 or 1 | Anthropic | Provider’s page | JSON output and strict tools | rejected | — | Listed under "Not supported": "Array constraints beyond `minItems` of 0 or 1" and under "Supported features": "Array `minItems` (only values 0 and 1 supported)" "If you use an unsupported feature, you'll receive a 400 error with details." | platform.claude.com/docs/en/build-with-claude/structured-outputs (read 2026-09-25) |
| minItems values accepted | Anthropic | Provider’s page | JSON output and strict tools | documented | 0, 1 | Listed under "Supported features": "Array `minItems` (only values 0 and 1 supported)" Any other value is an array constraint the page lists as not supported. | platform.claude.com/docs/en/build-with-claude/structured-outputs (read 2026-09-25) |
| additionalProperties values accepted | Anthropic | Provider’s page | JSON output and strict tools | documented | false | Listed under "Supported features": "`required` and `additionalProperties` (must be set to `false` for objects)" and under "Not supported": "`additionalProperties` set to anything other than `false`" "If you use an unsupported feature, you'll receive a 400 error with details." The page does not say what happens to an object that omits it. | platform.claude.com/docs/en/build-with-claude/structured-outputs (read 2026-09-25) |
| Recursive schemas | Anthropic | Provider’s page | JSON output and strict tools | rejected | — | Listed under "Not supported": "Recursive schemas" "If you use an unsupported feature, you'll receive a 400 error with details." | platform.claude.com/docs/en/build-with-claude/structured-outputs (read 2026-09-25) |
| External $ref | Anthropic | Provider’s page | JSON output and strict tools | rejected | — | Listed under "Not supported": "External `$ref` (for example, `'$ref': 'http://...'`)" "If you use an unsupported feature, you'll receive a 400 error with details." Local references are supported: "`$ref`, `$def`, and `definitions` (external `$ref` not supported)" | platform.claude.com/docs/en/build-with-claude/structured-outputs (read 2026-09-25) |
| allOf with $ref | Anthropic | Provider’s page | JSON output and strict tools | unsupported | — | Listed under "Supported features": "`anyOf` and `allOf` (with limitations - `allOf` with `$ref` not supported)" It is not in the "Not supported" list that says a 400 follows, so the page does not say it is refused. | platform.claude.com/docs/en/build-with-claude/structured-outputs (read 2026-09-25) |
| Complex types in enum | Anthropic | Provider’s page | JSON output and strict tools | rejected | — | Listed under "Not supported": "Complex types within enums" and under "Supported features": "`enum` (strings, numbers, bools, or nulls only - no complex types" | platform.claude.com/docs/en/build-with-claude/structured-outputs (read 2026-09-25) |
| String formats accepted | Anthropic | Provider’s page | JSON output and strict tools | documented | date-time, time, date, duration, email, hostname, uri, ipv4, ipv6, uuid | Listed under "Supported features": "String formats: `date-time`, `time`, `date`, `duration`, `email`, `hostname`, `uri`, `ipv4`, `ipv6`, `uuid`" The page does not say what another format does; the SDKs "Filter string formats to supported list only". | platform.claude.com/docs/en/build-with-claude/structured-outputs (read 2026-09-25) |
| pattern with backreferences, lookaround, word boundaries or large {n,m} | Anthropic | Provider’s page | JSON output and strict tools | may be rejected | — | Under "Pattern support (regex)", NOT supported: "Backreferences to groups (for example, `\1`, `\2`)" "Lookahead/lookbehind assertions (for example, `(?=...)`, `(?!...)`)" "Word boundaries: `\b`, `\B`" "Complex `{n,m}` quantifiers with large ranges" "Simple regex patterns work well. Complex patterns may result in 400 errors." The page does not say how large a range is too large. | platform.claude.com/docs/en/build-with-claude/structured-outputs (read 2026-09-25) |
| Capitalisation of enum and const values | Anthropic | Provider’s page | JSON output and strict tools | not guaranteed | — | Under "Invalid outputs": "Structured outputs don't guarantee the capitalization of string `enum` and `const` values" "Compare enum values case-insensitively, and avoid enum values that differ only in capitalization." | platform.claude.com/docs/en/build-with-claude/structured-outputs (read 2026-09-25) |
| Keywords listed as supported | Anthropic | Provider’s page | JSON output and strict tools | documented | type, enum, const, anyOf, allOf, $ref, $defs, definitions, default, required, additionalProperties, properties, items, format, minItems, pattern, description | The "Supported features" list: "All basic types: object, array, string, integer, number, boolean, null" "`const`" "`default` property for all supported types" plus the keywords quoted in the other facts. `properties`, `items` and `description` appear in every example on the page, and the SDKs write constraints into `description`. | platform.claude.com/docs/en/build-with-claude/structured-outputs (read 2026-09-25) |
| Optional properties per request, across strict schemas | Anthropic | Provider’s page | JSON output and strict tools | documented | 24 | Under "Explicit limits": Optional parameters, 24 — "Total optional parameters across all strict tool schemas and JSON output schemas. Each parameter not listed in `required` counts toward this limit." "These limits apply to the combined total across all strict schemas in a single request." | platform.claude.com/docs/en/build-with-claude/structured-outputs (read 2026-09-25) |
| Union-typed properties per request (anyOf or a type list) | Anthropic | Provider’s page | JSON output and strict tools | documented | 16 | Under "Explicit limits": Parameters with union types, 16 — "Total parameters that use `anyOf` or type arrays (for example, `"type": ["string", "null"]`) across all strict schemas." | platform.claude.com/docs/en/build-with-claude/structured-outputs (read 2026-09-25) |
| Tools with strict: true per request | Anthropic | Provider’s page | JSON output and strict tools | documented | 20 | Under "Explicit limits": Strict tools per request, 20 — "Maximum number of tools with `strict: true`. Non-strict tools don't count toward this limit." | platform.claude.com/docs/en/build-with-claude/structured-outputs (read 2026-09-25) |
| What the SDKs change in a schema | Anthropic | Provider’s page | JSON output and strict tools | documented | — | Under "How SDK transformation works": "**Remove unsupported constraints** (for example, `minimum`, `maximum`, `minLength`, `maxLength`)" "**Update descriptions** with constraint info (for example, "Must be at least 100"), when the constraint is not directly supported with structured outputs" "**Add `additionalProperties: false`** to all objects" "**Filter string formats** to supported list only" | platform.claude.com/docs/en/build-with-claude/structured-outputs (read 2026-09-25) |
| Whether the schema is enforced | Anthropic | Provider’s page | Tools without strict | not enforced | — | The strict tool use page states: "Without strict mode, Claude might return incompatible types (`"2"` instead of `2`) or omit required fields, breaking your functions and causing runtime errors." A tool without `strict: true` is guidance the model follows, not a guarantee. | platform.claude.com/docs/en/agents-and-tools/tool-use/strict-tool-use (read 2026-09-25) |
| Response schema through Salyro | Anthropic | Measured through Salyro | JSON output | supported | native_ | The schema is translated into the provider’s own structured-output field, which enforces it; there is no strict flag to send. | Salyro’s measurement, catalogue revision 2026-08-26.3 |
| strict: true on a tool, through Salyro | Anthropic | Measured through Salyro | Strict tools | rejected | toolStrictSurvives: false | Salyro refuses strict: true on a tool for Anthropic with a 400: its path to the provider does not carry the flag, so the guarantee would silently not apply. | Salyro’s measurement, catalogue revision 2026-08-26.3 |
| additionalProperties in a tool’s parameters, through Salyro | Anthropic | Measured through Salyro | Tools | supported | toolAdditionalPropertiesSurvives: true | additionalProperties in a tool’s parameters reaches the provider as written. | Salyro’s measurement, catalogue revision 2026-08-26.3 |
| Which keywords are accepted | Provider’s page | JSON output and strict tools | unknown | — | The provider page is blocked by this build's network egress and was not read. Only the provider's own page may supply a schema rule, so every keyword is unknown for this provider until somebody reads it. | ai.google.dev/gemini-api/docs/structured-output (tried, not read, 2026-09-25) | |
| Whether the schema is enforced | Provider’s page | Tools without strict | unknown | — | The provider page is blocked by this build's network egress and was not read. Only the provider's own page may supply a schema rule, so every keyword is unknown for this provider until somebody reads it. | ai.google.dev/gemini-api/docs/function-calling (tried, not read, 2026-09-25) | |
| Response schema through Salyro | Measured through Salyro | JSON output | supported | native_ | The schema is translated into the provider’s own structured-output field, which enforces it; there is no strict flag to send. | Salyro’s measurement, catalogue revision 2026-08-26.3 | |
| strict: true on a tool, through Salyro | Measured through Salyro | Strict tools | rejected | toolStrictSurvives: false | Salyro refuses strict: true on a tool for Google with a 400: its path to the provider does not carry the flag, so the guarantee would silently not apply. | Salyro’s measurement, catalogue revision 2026-08-26.3 | |
| additionalProperties in a tool’s parameters, through Salyro | Measured through Salyro | Tools | removed | toolAdditionalPropertiesSurvives: false | additionalProperties is removed from the parameters of a tool for Google before the request is sent — silently. The model may add keys you did not list. | Salyro’s measurement, catalogue revision 2026-08-26.3 | |
| Which keywords are accepted | OpenAI | Provider’s page | JSON output and strict tools | unknown | — | The provider page is blocked by this build's network egress and was not read. Only the provider's own page may supply a schema rule, so every keyword is unknown for this provider until somebody reads it. | platform.openai.com/docs/guides/structured-outputs (tried, not read, 2026-09-25) |
| Whether the schema is enforced | OpenAI | Provider’s page | Tools without strict | unknown | — | The provider page is blocked by this build's network egress and was not read. Only the provider's own page may supply a schema rule, so every keyword is unknown for this provider until somebody reads it. | platform.openai.com/docs/guides/function-calling (tried, not read, 2026-09-25) |
| Response schema through Salyro | OpenAI | Measured through Salyro | JSON output | supported | strict_ | The schema reaches the provider with strict: true, so the provider’s own guarantee applies. | Salyro’s measurement, catalogue revision 2026-08-26.3 |
| strict: true on a tool, through Salyro | OpenAI | Measured through Salyro | Strict tools | supported | toolStrictSurvives: true | strict: true on a tool reaches the provider. | Salyro’s measurement, catalogue revision 2026-08-26.3 |
| additionalProperties in a tool’s parameters, through Salyro | OpenAI | Measured through Salyro | Tools | supported | toolAdditionalPropertiesSurvives: true | additionalProperties in a tool’s parameters reaches the provider as written. | Salyro’s measurement, catalogue revision 2026-08-26.3 |
| Which keywords are accepted | xAI | Provider’s page | JSON output and strict tools | unknown | — | The provider page is blocked by this build's network egress and was not read. Only the provider's own page may supply a schema rule, so every keyword is unknown for this provider until somebody reads it. | docs.x.ai/docs/guides/structured-outputs (tried, not read, 2026-09-25) |
| Whether the schema is enforced | xAI | Provider’s page | Tools without strict | unknown | — | The provider page is blocked by this build's network egress and was not read. Only the provider's own page may supply a schema rule, so every keyword is unknown for this provider until somebody reads it. | docs.x.ai/docs/guides/function-calling (tried, not read, 2026-09-25) |
| Response schema through Salyro | xAI | Measured through Salyro | JSON output | unknown | forwarded_ | The schema is forwarded untranslated, and nothing states that the provider honours it: an ignored schema would come back as ordinary text, with no error. | Salyro’s measurement, catalogue revision 2026-08-26.3 |
| strict: true on a tool, through Salyro | xAI | Measured through Salyro | Strict tools | rejected | toolStrictSurvives: false | Salyro refuses strict: true on a tool for xAI with a 400: its path to the provider does not carry the flag, so the guarantee would silently not apply. | Salyro’s measurement, catalogue revision 2026-08-26.3 |
| additionalProperties in a tool’s parameters, through Salyro | xAI | Measured through Salyro | Tools | supported | toolAdditionalPropertiesSurvives: true | additionalProperties in a tool’s parameters reaches the provider as written. | Salyro’s measurement, catalogue revision 2026-08-26.3 |
Where the rows come from
- Google (tried, not reachable from the build): ai.google.dev/gemini-api/docs/function-calling, 2026-09-25.
- Google (tried, not reachable from the build): ai.google.dev/gemini-api/docs/structured-output, 2026-09-25.
- xAI (tried, not reachable from the build): docs.x.ai/docs/guides/function-calling, 2026-09-25.
- xAI (tried, not reachable from the build): docs.x.ai/docs/guides/structured-outputs, 2026-09-25.
- Anthropic (read): platform.claude.com/docs/en/agents-and-tools/tool-use/strict-tool-use, 2026-09-25.
- Anthropic (read): platform.claude.com/docs/en/build-with-claude/structured-outputs, 2026-09-25.
- OpenAI (tried, not reachable from the build): platform.openai.com/docs/guides/function-calling, 2026-09-25.
- OpenAI (tried, not reachable from the build): platform.openai.com/docs/guides/structured-outputs, 2026-09-25.
