Structured outputs
Force the model to return valid JSON with response_format.
The response_format parameter constrains the model output to structured JSON. {"type": "json_object"} forces the response to be valid JSON, while {"type": "json_schema", ...} constrains it to a schema you supply. This value is an opaque passthrough to OpenAI-compatible providers; the backend performs no schema validation.
Request#
| Parameter | Type | Required | Description |
|---|---|---|---|
| response_format | object | Optional | {"type": "json_object"} (force valid JSON) or {"type": "json_schema", "json_schema": {...}} (schema-constrained). The format you specify is forwarded as-is to the routed provider. |
When using {"type": "json_object"}, instruct the model to reply with JSON in your messages (typically the system prompt). Without guidance on the JSON shape you expect, output may be inconsistent.
curl https://apirouter.pleum.ai/v1/chat/completions \
-H "Authorization: Bearer plm_..." \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [
{"role": "system", "content": "Extract the user info. Reply with JSON only."},
{"role": "user", "content": "Jane Doe is 31 and lives in Seoul."}
],
"response_format": {"type": "json_object"}
}'json_schema support#
json_schema support depends on the routed model — not every provider or model supports schema-constrained output. PleumRouter forwards response_format to the provider without validating or modifying it, so sending it to an unsupported model may cause the provider to return an error or ignore the field.
{
"model": "gpt-4o-mini",
"messages": [
{"role": "user", "content": "Jane Doe is 31 and lives in Seoul."}
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "person",
"strict": true,
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"city": {"type": "string"}
},
"required": ["name", "age", "city"],
"additionalProperties": false
}
}
}
}Anthropic (Claude) caveat#
response_format is not translated for Anthropic (Claude) models — it is silently ignored there. To force JSON on Claude, use tool calling with tools and tool_choice to define the schema instead.Define the JSON shape you want as the function's parameters and force that tool with tool_choice, as shown below. The model then calls the tool with arguments matching the schema, and the structured output appears in the arguments (a JSON string) of tool_calls.
{
"model": "claude-sonnet-4-6",
"messages": [
{"role": "user", "content": "Jane Doe is 31 and lives in Seoul."}
],
"tools": [
{
"type": "function",
"function": {
"name": "save_person",
"description": "Save the extracted person record.",
"parameters": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"city": {"type": "string"}
},
"required": ["name", "age", "city"]
}
}
}
],
"tool_choice": {"type": "function", "function": {"name": "save_person"}}
}Response#
The structured output is returned as a JSON string in choices[0].message.content and must be parsed before use. On normal completion, finish_reason is "stop".
{
"id": "chatcmpl-gpt-4o-mini-512ms",
"object": "chat.completion",
"model": "gpt-4o-mini",
"provider": "openai",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "{\"name\":\"Jane Doe\",\"age\":31,\"city\":\"Seoul\"}"
},
"finish_reason": "stop"
}
]
}