Structured Output
Constrain model output to match a specific JSON schema. Supported via both the OpenAI-compatible and Anthropic-compatible APIs.
OpenAI Format
Use the response_format parameter in the request body to control output format.
JSON Mode
Set response_format to {"type": "json_object"} to constrain the model to output valid JSON. No schema is enforced — the model will produce well-formed JSON, but the structure is not guaranteed.
{
"response_format": {
"type": "json_object"
}
}JSON Schema
Set response_format to a json_schema object to enforce a specific structure. The name and schema fields are required.
{
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "person",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"}
},
"required": ["name", "age"]
}
}
}
}Optional fields: description (schema description) and strict (strict schema adherence).
response_format Fields
| Field | Type | Required | Description |
|---|---|---|---|
| type | string | Required | "text", "json_object", or "json_schema" |
| json_schema.name | string | Required (for json_schema) | Schema name |
| json_schema.schema | object | Required (for json_schema) | JSON Schema object |
| json_schema.description | string | Optional | Schema description |
| json_schema.strict | boolean | Optional | Strict schema adherence |
Anthropic Format
Use the output_config parameter with the Anthropic Messages API (/v1/messages) to enforce structured output natively.
{
"output_config": {
"format": {
"type": "json_schema",
"name": "person",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"}
},
"required": ["name", "age"]
}
}
}
}Native structured output is supported on Claude 4.5+ models (anthropic/claude-opus-4, anthropic/claude-sonnet-4.5, anthropic/claude-haiku-4.5).
output_config Fields
| Field | Type | Required | Description |
|---|---|---|---|
| format.type | string | Required | "json_schema" |
| format.name | string | Required | Schema name |
| format.schema | object | Required | JSON Schema object |
| format.description | string | Optional | Schema description |
Examples
Extracting structured data from text.
curl https://api.routerhub.ai/v1/chat/completions \
-H "Authorization: Bearer $ROUTERHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-sonnet-4.5",
"messages": [
{"role": "user", "content": "Extract: John Smith is 35 years old and lives in New York."}
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "person_info",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"city": {"type": "string"}
},
"required": ["name", "age", "city"]
}
}
}
}'import requests
response = requests.post(
"https://api.routerhub.ai/v1/chat/completions",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"model": "anthropic/claude-sonnet-4.5",
"messages": [
{"role": "user", "content": "Extract: John Smith is 35 years old and lives in New York."}
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "person_info",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"city": {"type": "string"},
},
"required": ["name", "age", "city"],
},
},
},
},
)
import json
data = json.loads(response.json()["choices"][0]["message"]["content"])
print(data)from openai import OpenAI
client = OpenAI(
base_url="https://api.routerhub.ai/v1",
api_key="YOUR_API_KEY",
)
response = client.chat.completions.create(
model="anthropic/claude-sonnet-4.5",
messages=[
{"role": "user", "content": "Extract: John Smith is 35 years old and lives in New York."}
],
response_format={
"type": "json_schema",
"json_schema": {
"name": "person_info",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"city": {"type": "string"},
},
"required": ["name", "age", "city"],
},
},
},
)
import json
data = json.loads(response.choices[0].message.content)
print(data) # {"name": "John Smith", "age": 35, "city": "New York"}from anthropic import Anthropic
client = Anthropic(
base_url="https://api.routerhub.ai",
api_key="YOUR_API_KEY",
)
response = client.messages.create(
model="anthropic/claude-sonnet-4.5",
max_tokens=1024,
messages=[
{"role": "user", "content": "Extract: John Smith is 35 years old and lives in New York."}
],
output_config={
"format": {
"type": "json_schema",
"name": "person_info",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"city": {"type": "string"},
},
"required": ["name", "age", "city"],
},
},
},
)
import json
data = json.loads(response.content[0].text)
print(data)from langchain_openai import ChatOpenAI
from pydantic import BaseModel
class PersonInfo(BaseModel):
name: str
age: int
city: str
llm = ChatOpenAI(
base_url="https://api.routerhub.ai/v1",
api_key="YOUR_API_KEY",
model="anthropic/claude-sonnet-4.5",
)
structured_llm = llm.with_structured_output(PersonInfo)
result = structured_llm.invoke(
"Extract: John Smith is 35 years old and lives in New York."
)
print(result) # name='John Smith' age=35 city='New York'Sample Response
When using structured output, the model's response content will be a JSON string matching your schema:
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1700000000,
"model": "anthropic/claude-sonnet-4.5",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "{\"name\": \"John Smith\", \"age\": 35, \"city\": \"New York\"}"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 32,
"completion_tokens": 18,
"total_tokens": 50
}
}Model Support
All models support structured output via response_format. Native structured output via output_config (Anthropic format) is available on Claude 4.5+ models: anthropic/claude-opus-4, anthropic/claude-sonnet-4.5, and anthropic/claude-haiku-4.5.