Skip to navigation

Structured outputs

Get schema-constrained JSON from any capable model

Structured outputs constrain a response to any JSON object (json_object) or JSON matching your schema (json_schema), using each vendor’s native mechanism. Use json_schema when you deserialize into typed structures.

Request JSON

Pass response_format on /v1/responses or OpenAI Chat Completions, or text.format on /v1/openai/responses. In the TypeScript SDK, build it with zodResponseFormat from merge-gateway-sdk/zod.

curl https://api-gateway.merge.dev/v1/responses \
-H "Authorization: Bearer $MERGE_GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-5.1",
"input": [{"type": "message", "role": "user", "content": "Invent a person."}],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "person",
"schema": {
"type": "object",
"properties": {"name": {"type": "string"}, "age": {"type": "integer"}},
"required": ["name", "age"],
"additionalProperties": false
},
"strict": true
}
}
}'

Your schema passes to the vendor as written, including $ref/$defs and anyOf, rewriting dialect (such as definitions to $defs) only where a vendor needs it.

Strict mode

strict is tri-state on the native API:

strictBehavior
OmittedThe vendor’s default. Gateway sends no value.
trueVendors with a strict mode, such as OpenAI, guarantee conformance but require every property in required and additionalProperties: false. Gateway also fails over on a schema violation.
falseThe schema guides generation without strict constraints. Use it for optional fields and open objects.

The AI SDK provider defaults strictJsonSchema to true; set it to false for schemas with optional fields.

Routing and failover

Gateway checks support on the exact route before calling the vendor: routing policies drop candidates that can’t serve the request, and fallbacks re-check.

On a route with forced tool choice but no native structured outputs, Gateway serves json_schema by forcing one tool whose parameters are your schema, returning its arguments as the message text. This doesn’t apply to json_object, to routes that can’t force a tool, or to requests with their own tools or tool_choice, which return 400 unsupported_params.

With strict: true, a 200 whose body isn’t valid JSON or doesn’t match your schema is a failed attempt, and a Priority or Intelligent policy moves to the next candidate. If every candidate fails, Gateway serves the last body, so validate it. Streaming, tool-call turns, and output-token-limit stops are exempt. Each discarded attempt bills at the route that ran it. Vendor strict modes don’t enforce value keywords such as minimum.

With stream: true, JSON arrives as text deltas, and a mid-stream fallback sends a {"fallback_restart": true, "model": "...", "vendor": "..."} data frame and restarts generation, so discard anything parsed before it.

Reference

FieldNotes
typejson_object or json_schema
json_schema.schemaRequired for json_schema
json_schema.nameDefaults to response
json_schema.descriptionOptional
json_schema.stricttrue, false, or omitted
CaseResult
Route can’t serve the format400 unsupported_params naming the model, vendor, and format type
json_object on Bedrock400 unsupported_params. Send json_schema instead.
json_object on anthropic/claude-fable-5-1 or anthropic/claude-opus-5-5400 unsupported_params. Send json_schema with a schema.
Malformed text.format, or malformed response_format on a compat surface400 invalid_response_format
Malformed response_format on native /v1/responses422 validation error

supports_structured_outputs on GET /v1/models is true for routes Gateway serves natively or by emulation. Errors has the error shapes.

Next steps