Structured Outputs
Constrain a chat model's reply to JSON — or to a JSON Schema you supply — with response_format, and know where the JSON arrives for each provider.
Chat models accept an OpenAI-style response_format, which turns "please reply
in JSON" from a request the model may quietly ignore into a constraint the
provider enforces:
{ "response_format": { "type": "json_schema", "json_schema": {
"name": "person",
"strict": true,
"schema": {
"type": "object",
"properties": { "name": { "type": "string" }, "age": { "type": "integer" } },
"required": ["name", "age"],
"additionalProperties": false
}
} } }Leave the field out — or send { "type": "text" } — and the call behaves
exactly as before, so existing integrations are unaffected.
The two modes
| Type | What you get |
|---|---|
json_object | Valid JSON. The shape is up to the model, and it can change between calls. |
json_schema | JSON that conforms to the schema you supply. |
Prefer json_schema whenever you know the shape you want. json_object still
leaves you writing defensive parsing code, because nothing stops the model from
renaming a key or nesting the answer one level deeper next time.
Model support
Every chat model accepts both types, with these exceptions:
| Models | Accepts |
|---|---|
claude-4.5-sonnet, claude-opus-4.7 | json_schema only |
gpt-4, gpt-4-turbo | json_object only |
deepseek-chat, deepseek-reasoner | json_object only |
qwq-plus, qvq-max | json_object only |
qwen3-coder-flash, qwen3-coder-plus, qwen3.5-flash, qwen3.5-plus | json_object only |
claude-4-sonnet | neither |
Claude has no schema-less JSON mode, which is why json_object is refused
there rather than approximated. The Qwen models above accept a schema upstream
and then answer without enforcing it — a silently unconstrained reply is worse
than a clear error, so the gateway refuses the type the model cannot honour.
Ask for an unsupported type and you get a 400 naming the one that works,
before the request reaches the provider — never a surprise later.
Where the JSON arrives
The response keeps the provider's native envelope. Your JSON is a string in the usual text field, which you parse yourself:
| Provider | Field |
|---|---|
| OpenAI-compatible (GPT, DeepSeek, Qwen, Grok, OpenRouter) | choices[0].message.content |
| Claude | content[0].text |
| Gemini | candidates[0].content.parts[0].text |
{
"choices": [
{ "message": { "role": "assistant", "content": "{\"name\":\"Mara Ellison\",\"age\":34}" } }
]
}On v2
An async result carries the whole
provider response as a string in output, so there are two decodes: one to
get the envelope, one to get your object.
result = requests.get(poll_url, headers=headers).json()
envelope = json.loads(result["output"]) # provider response
person = json.loads(envelope["choices"][0]["message"]["content"]) # your objectThe Python SDK collapses both steps: ChatResponse.json()
returns the parsed object on the sync and async paths alike.
Rules that produce a 400
OpenAI and DeepSeek require the word "json" in the conversation when you use
json_object. The provider rejects the request outright:
'messages' must contain the word 'json' in some form, to use 'response_format' of type 'json_object'Adding "Reply in json." to your prompt is enough. json_schema has no such
rule.
Schemas are not portable between providers. Each enforces its own subset:
| Provider | Constraint |
|---|---|
OpenAI (strict: true) | every property listed in required, and additionalProperties: false |
| Anthropic | rejects minimum/maximum, minLength/maxLength and recursive $ref |
| Gemini | accepts full JSON Schema |
The intersection — an object with every property required and
additionalProperties: false, no numeric or length bounds — works everywhere.
Write to that if one schema has to serve several models.
Errors
These come from the gateway, before the provider is called. On /v1 they are a
400; on /v2 the request lands as FAILED carrying the same message.
| Message | Cause |
|---|---|
response_format must be an object with "type" one of: text, json_object, json_schema | The field is not an object, or the type is unrecognised |
response_format.json_schema.schema is required and must be a JSON schema object | json_schema sent without a schema object |
response_format type json_schema is not supported by this model; use type json_object | See the support table above |
this model does not support response_format | The model supports neither type |
A schema keyword the provider rejects surfaces as a 400 naming the keyword.
Examples
curl -X POST https://api.segmind.com/v1/gpt-5.4-mini \
-H "x-api-key: $SEGMIND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"messages": [{ "role": "user", "content": "Invent one person." }],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "person",
"strict": true,
"schema": {
"type": "object",
"properties": { "name": { "type": "string" }, "age": { "type": "integer" } },
"required": ["name", "age"],
"additionalProperties": false
}
}
}
}'With the Python SDK, where .json() does the parsing:
import segmind
reply = segmind.chat_sync(
"gpt-5.4-mini",
messages=[{"role": "user", "content": "Invent one person."}],
response_format={
"type": "json_schema",
"json_schema": {
"name": "person",
"strict": True,
"schema": {
"type": "object",
"properties": {"name": {"type": "string"}, "age": {"type": "integer"}},
"required": ["name", "age"],
"additionalProperties": False,
},
},
},
)
person = reply.json() # {'name': 'Mara Ellison', 'age': 34}.json() raises a SegmindError when the reply was not JSON — a refusal, for
instance — so catch it rather than assuming the constraint always held.
Notes
- Billing is unchanged. You pay the model's usual token rates; asking for structured output costs nothing extra.
- No streaming. Structured replies arrive whole.
- Schema-shaped output is also what powers fan-out from an LLM in PixelFlow, where the schema is derived from the fields your downstream nodes consume.
Random Seed
Use the seed parameter to control randomness in Segmind model output. Pass -1 for a random seed, or any positive integer for reproducible results.
Web Search Grounding
Ground Gemini text and image generations in live Google Search results with web_search: true, and read back the queries and sources behind the answer.