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.