Structured Outputs ensure model responses conform to predefined formats, enabling type-safe, predictable integration with your applications.
Instead of parsing free-form text, Structured Outputs guarantee the model returns data in a specific format you define—whether simple JSON or complex schemas with nested objects and arrays.
Standard Output: Structured Output:
------------------- ---------------------
"The user is 25 {
years old and "name": "Alice",
lives in Paris." "age": 25,
"location": "Paris"
}Get started with JSON mode in 3 simple steps:
import requests
import os
# 1. Set output_mode to "json"
response = requests.post(
"https://api.aitronos.com/v1/model/response",
headers={"Authorization": f"Bearer {os.environ['FREDDY_API_KEY']}"},
json={
"organization_id": "org_abc123",
"model": "ftg-3.0",
"output_mode": "json", # Enable JSON mode
"inputs": [{
"role": "user",
"texts": [{
"text": "Extract the product name, price, and rating from: 'iPhone 15 Pro - $999 - 4.5 stars'"
}]
}]
}
)
# 2. Get guaranteed valid JSON
result = response.json()
data = result["output"][0]["content"][0]["text"]
# 3. Parse and use
import json
product = json.loads(data)
print(f"Product: {product['name']}, Price: {product['price']}")That's it! The model returns valid JSON every time.
Standard free-form text responses.
{
"outputMode": "text",
"inputs": [
{"role": "user", "texts": [{"text": "What is Python?"}]}
]
}Response:
Python is a high-level, interpreted programming language...Use when:
- Natural conversation
- Creative writing
- Open-ended queries
Forces the model to return valid JSON. The model determines the structure based on your prompt.
{
"organization_id": "org_abc123",
"model": "ftg-3.0",
"output_mode": "json",
"inputs": [
{
"role": "user",
"texts": [{"text": "Extract name, age, and city from: 'Alice is 25 and lives in Paris'"}]
}
]
}Response:
{
"name": "Alice",
"age": 25,
"city": "Paris"
}Key features:
- Guarantees valid JSON - No parsing errors
- Flexible structure - Model decides format based on context
- No schema required - Just set the mode
- Prompt-driven - Describe desired structure in your prompt
Use when:
- Need valid JSON but structure varies by request
- Quick prototyping and experimentation
- Structure is implied by prompt context
- Building dynamic responses where schema isn't fixed
Example use cases:
# Dynamic data extraction
response = requests.post(
"https://api.aitronos.com/v1/model/response",
headers={"X-API-Key": api_key},
json={
"organization_id": "org_abc123",
"model": "ftg-3.0",
"output_mode": "json",
"inputs": [{
"role": "user",
"texts": [{
"text": "Analyze this product review and return sentiment, key points, and rating: 'Great product! Fast shipping. Would buy again. 5 stars.'"
}]
}]
}
)
# Returns flexible JSON like:
# {
# "sentiment": "positive",
# "key_points": ["great product", "fast shipping", "would repurchase"],
# "rating": 5,
# "recommendation": "highly recommended"
# }Most powerful option - define exact structure using JSON Schema. The model guarantees output matching your schema.
{
"organization_id": "org_abc123",
"model": "ftg-3.0",
"output_mode": "json_schema",
"json_schema": {
"id": "user_profile_v1",
"description": "User profile extraction schema",
"strict": true,
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"city": {"type": "string"}
},
"required": ["name", "age", "city"],
"additionalProperties": false
}
},
"inputs": [
{
"role": "user",
"texts": [{"text": "Extract: 'Alice is 25 and lives in Paris'"}]
}
]
}Response (guaranteed structure):
{
"name": "Alice",
"age": 25,
"city": "Paris"
}Key features:
- 100% schema compliance - No exceptions, guaranteed structure
- Type safety - Integers are integers, strings are strings, no type coercion
- Validation - Required fields always present, no missing data
- Predictable - Same structure every time, perfect for automation
- Multiple schemas - Provide multiple schemas; model selects appropriate one
Use when:
- Type safety is critical for your application
- Integrating with typed languages (TypeScript, Go, Rust, Java)
- Direct database insertions without validation
- Production API responses requiring consistency
- Compliance and audit requirements
{
"id": "simple_schema",
"schema": {
"type": "object",
"properties": {
"task": {"type": "string"},
"completed": {"type": "boolean"},
"priority": {"type": "integer", "minimum": 1, "maximum": 5}
},
"required": ["task", "completed"]
}
}{
"type": "object",
"properties": {
"text": {"type": "string"},
"count": {"type": "integer"},
"price": {"type": "number"},
"active": {"type": "boolean"},
"data": {"type": "null"}
}
}{
"type": "object",
"properties": {
"tags": {
"type": "array",
"items": {"type": "string"}
},
"scores": {
"type": "array",
"items": {"type": "integer"},
"minItems": 1,
"maxItems": 10
}
}
}{
"type": "object",
"properties": {
"user": {
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string", "format": "email"}
},
"required": ["name", "email"]
}
}
}{
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": ["pending", "in_progress", "completed", "failed"]
},
"priority": {
"type": "string",
"enum": ["low", "medium", "high"]
}
}
}{
"type": "object",
"properties": {
"username": {
"type": "string",
"minLength": 3,
"maxLength": 20,
"pattern": "^[a-zA-Z0-9_]+$"
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 120
},
"email": {
"type": "string",
"format": "email"
},
"website": {
"type": "string",
"format": "uri"
}
}
}{
"type": "object",
"properties": {
"id": {"type": "string"}, // Required (in required array)
"name": {"type": "string"}, // Required
"description": {"type": "string"} // Optional (not in required array)
},
"required": ["id", "name"],
"additionalProperties": false // Reject unknown properties
}{
"id": "order_schema_v2",
"strict": true,
"schema": {
"type": "object",
"properties": {
"orderId": {"type": "string"},
"customer": {
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string", "format": "email"},
"address": {
"type": "object",
"properties": {
"street": {"type": "string"},
"city": {"type": "string"},
"zipCode": {"type": "string"}
},
"required": ["street", "city", "zipCode"]
}
},
"required": ["name", "email", "address"]
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"productId": {"type": "string"},
"name": {"type": "string"},
"quantity": {"type": "integer", "minimum": 1},
"price": {"type": "number", "minimum": 0}
},
"required": ["productId", "name", "quantity", "price"]
},
"minItems": 1
},
"total": {"type": "number", "minimum": 0},
"status": {
"type": "string",
"enum": ["pending", "processing", "shipped", "delivered", "cancelled"]
}
},
"required": ["orderId", "customer", "items", "total", "status"],
"additionalProperties": false
}
}Extract structured information from unstructured text:
response = requests.post(
'https://api.aitronos.com/v1/model/response',
json={
"model": "gpt-4.1",
"outputMode": "json_schema",
"jsonSchema": {
"id": "contact_extraction",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"},
"phone": {"type": "string"},
"company": {"type": "string"}
},
"required": ["name"]
}
},
"inputs": [{
"role": "user",
"texts": [{"text": "Extract contact: John Doe, john@example.com, works at Acme Corp"}]
}]
}
)Generate API-ready responses:
const response = await fetch('/v1/model/response', {
method: 'POST',
body: JSON.stringify({
model: 'gpt-4.1',
outputMode: 'json_schema',
jsonSchema: {
id: 'api_response',
schema: {
type: 'object',
properties: {
success: { type: 'boolean' },
data: {
type: 'object',
properties: {
userId: { type: 'string' },
message: { type: 'string' }
}
},
error: {
type: 'object',
properties: {
code: { type: 'string' },
message: { type: 'string' }
}
}
},
required: ['success']
}
},
inputs: [{
role: 'user',
texts: [{ text: 'Generate success response for user creation' }]
}]
})
});Create type-safe database entries:
# Generate database record
schema = {
"id": "user_record",
"schema": {
"type": "object",
"properties": {
"id": {"type": "string"},
"username": {"type": "string"},
"email": {"type": "string", "format": "email"},
"role": {"type": "string", "enum": ["user", "admin", "moderator"]},
"created_at": {"type": "string", "format": "date-time"},
"active": {"type": "boolean"}
},
"required": ["id", "username", "email", "role", "active"]
}
}
result = generate_response(outputMode="json_schema", jsonSchema=schema)
# Direct database insertion (no validation needed!)
db.users.insert_one(result)Generate type-safe responses for TypeScript:
// Define TypeScript interface
interface UserProfile {
id: string;
name: string;
age: number;
email: string;
interests: string[];
}
// Matching JSON Schema
const schema = {
id: 'user_profile',
schema: {
type: 'object',
properties: {
id: { type: 'string' },
name: { type: 'string' },
age: { type: 'integer' },
email: { type: 'string', format: 'email' },
interests: { type: 'array', items: { type: 'string' } }
},
required: ['id', 'name', 'age', 'email', 'interests']
}
};
// API call with type safety
const response = await createResponse({
outputMode: 'json_schema',
jsonSchema: schema,
inputs: [...]
});
const user: UserProfile = response.output[0].content[0].data; // Type-safe!| Feature | json Mode | json_schema Mode |
|---|---|---|
| Valid JSON | ✅ Guaranteed | ✅ Guaranteed |
| Structure control | ❌ Model decides | ✅ You define exactly |
| Type enforcement | ❌ Best effort | ✅ Strict (int vs string) |
| Required fields | ❌ May be missing | ✅ Always present |
| Schema validation | ❌ None | ✅ 100% compliant |
| Setup complexity | Simple (just set mode) | Requires schema definition |
| Flexibility | ✅ Adapts to context | ❌ Fixed structure |
| Use case | Prototyping, dynamic | Production, type-safe |
| Performance | Fast | Slightly slower (~5-10%) |
✅ Prototyping - Quick experiments without schema overhead
✅ Dynamic structures - Output format varies by request
✅ Exploratory analysis - Discovering what structure works best
✅ Flexible responses - Model adapts structure to content
✅ Simple extraction - Basic data extraction tasks
Example scenarios:
- Analyzing customer feedback (structure varies by feedback type)
- Extracting entities from diverse documents
- Building chatbots with dynamic response formats
- Quick data transformations
✅ Production systems - Type safety prevents runtime errors
✅ Database operations - Direct insertion without validation
✅ API integrations - Consistent structure for downstream systems
✅ Typed languages - TypeScript, Go, Rust, Java integration
✅ Compliance - Audit trails require predictable formats
✅ Critical data - Financial, medical, legal applications
Example scenarios:
- E-commerce order processing
- Medical record extraction
- Financial transaction parsing
- CRM data synchronization
- Automated report generation
import requests
import os
# Analyze support tickets with flexible structure
response = requests.post(
"https://api.aitronos.com/v1/model/response",
headers={"Authorization": f"Bearer {os.environ['FREDDY_API_KEY']}"},
json={
"organization_id": "org_abc123",
"model": "ftg-3.0",
"output_mode": "json",
"inputs": [{
"role": "user",
"texts": [{
"text": """Analyze this support ticket and extract key information:
Subject: Login issues on mobile app
From: john@example.com
Message: I can't log into the iOS app. It keeps saying 'invalid credentials'
but I'm sure my password is correct. This started yesterday after the update.
Return JSON with: issue_type, priority, affected_platform, user_email,
suggested_solution, and any other relevant fields."""
}]
}]
}
)
result = response.json()
ticket_data = json.loads(result["output"][0]["content"][0]["text"])
# Model returns flexible structure:
# {
# "issue_type": "authentication",
# "priority": "high",
# "affected_platform": "iOS",
# "user_email": "john@example.com",
# "suggested_solution": "Password reset or cache clear",
# "started_after": "app update",
# "error_message": "invalid credentials"
# }# Define strict schema for order processing
order_schema = {
"id": "order_processing_v1",
"description": "E-commerce order extraction schema",
"strict": True,
"schema": {
"type": "object",
"properties": {
"order_id": {"type": "string"},
"customer": {
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string", "format": "email"},
"phone": {"type": "string"}
},
"required": ["name", "email"]
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"product_id": {"type": "string"},
"name": {"type": "string"},
"quantity": {"type": "integer", "minimum": 1},
"price": {"type": "number", "minimum": 0}
},
"required": ["product_id", "name", "quantity", "price"]
},
"minItems": 1
},
"total": {"type": "number", "minimum": 0},
"shipping_address": {
"type": "object",
"properties": {
"street": {"type": "string"},
"city": {"type": "string"},
"state": {"type": "string"},
"zip": {"type": "string"}
},
"required": ["street", "city", "state", "zip"]
}
},
"required": ["order_id", "customer", "items", "total", "shipping_address"],
"additionalProperties": False
}
}
response = requests.post(
"https://api.aitronos.com/v1/model/response",
headers={"Authorization": f"Bearer {os.environ['FREDDY_API_KEY']}"},
json={
"organization_id": "org_abc123",
"model": "ftg-3.0",
"output_mode": "json_schema",
"json_schema": order_schema,
"inputs": [{
"role": "user",
"texts": [{
"text": """Extract order details from this email:
Order #12345
Customer: Jane Smith (jane@example.com, 555-0123)
Items:
- Product A123: Wireless Mouse x2 @ $29.99 each
- Product B456: USB Cable x1 @ $9.99
Total: $69.97
Ship to: 123 Main St, Springfield, IL 62701"""
}]
}]
}
)
# Guaranteed structure - safe for direct database insertion
order_data = json.loads(response.json()["output"][0]["content"][0]["text"])
db.orders.insert_one(order_data) # No validation needed!// Parse resumes with flexible structure
const response = await fetch('https://api.aitronos.com/v1/model/response', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.FREDDY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
organization_id: 'org_abc123',
model: 'ftg-3.0',
output_mode: 'json',
inputs: [{
role: 'user',
texts: [{
text: `Parse this resume and extract all relevant information in JSON format:
John Doe
Software Engineer
john.doe@email.com | (555) 123-4567 | linkedin.com/in/johndoe
EXPERIENCE
Senior Developer at Tech Corp (2020-2023)
- Led team of 5 developers
- Built microservices architecture
- Increased performance by 40%
EDUCATION
BS Computer Science, MIT (2016-2020)
SKILLS
Python, JavaScript, AWS, Docker, Kubernetes`
}]
}]
})
});
const result = await response.json();
const resume = JSON.parse(result.output[0].content[0].text);
// Model adapts structure to resume content:
// {
// "name": "John Doe",
// "title": "Software Engineer",
// "contact": {
// "email": "john.doe@email.com",
// "phone": "(555) 123-4567",
// "linkedin": "linkedin.com/in/johndoe"
// },
// "experience": [...],
// "education": [...],
// "skills": [...]
// }- Use
json_schemafor production - Type safety prevents runtime errors - Use
jsonfor prototyping - Faster iteration without schema overhead - Version schema IDs -
user_profile_v2for tracking changes - Set
additionalProperties: false- Reject unexpected fields in schemas - Use enums for fixed values - Ensures valid options (status, priority, etc.)
- Document your schemas - Add descriptions for maintainability
- Test schemas - Validate with sample prompts before deployment
- Describe desired structure in prompts - For JSON mode, be explicit about fields
- Over-constrain schemas - Too strict may fail to generate
- Use
jsonmode for typed systems - Usejson_schemafor type safety - Forget required fields - Model won't generate without them
- Nest too deeply - Keep schemas under 5 levels deep
- Skip ID fields - Always provide schema IDs for caching
- Mix modes - Choose one approach per use case
- Ignore validation errors - Always handle schema validation failures
{
"error": {
"type": "invalid_request_error",
"message": "Invalid JSON Schema: property 'age' must be of type 'integer'",
"code": "invalid_schema"
}
}Solution: Validate your schema against JSON Schema Draft 2020-12 specification.
{
"error": {
"type": "invalid_request_error",
"message": "jsonSchema is required when outputMode is 'json_schema'",
"code": "missing_parameter",
"param": "jsonSchema"
}
}Solution: Always provide jsonSchema when using json_schema mode.
If the model struggles to generate output matching a complex schema:
- Simplify nested structures
- Remove overly strict constraints
- Split into multiple requests
- Use
strict: falsefor best-effort compliance
Q: Can I use json mode without a schema?
A: Yes! json mode returns valid JSON without requiring a schema. Just set output_mode: "json" and describe the desired structure in your prompt.
Q: What's the difference between json and json_schema mode?
A: json mode guarantees valid JSON but lets the model decide the structure. json_schema mode enforces an exact structure you define. Use json for flexibility, json_schema for type safety.
Q: Will JSON mode always return valid JSON?
A: Yes, both json and json_schema modes guarantee syntactically valid JSON that can be parsed without errors.
Q: What JSON Schema version is supported?
A: JSON Schema Draft 2020-12.
Q: Is json_schema mode slower than json mode?
A: Slightly (~5-10%), but negligible compared to the value of guaranteed structure and type safety.
Q: Can the model fail to generate valid output?
A: With strict: true, the model always produces valid schema-compliant output. With strict: false, it makes best effort. In json mode, the model always returns valid JSON.
Q: How do I handle optional fields?
A: In json_schema mode, don't include them in the required array. In json mode, mention in your prompt which fields are optional.
Q: Can I use multiple schemas in one request?
A: Yes! Provide multiple schemas in the json_schema parameter. The model will select the most appropriate one based on context.
Q: What happens if my prompt conflicts with the schema?
A: The schema takes precedence. The model will always conform to the schema structure, even if the prompt suggests otherwise.
Q: Can I use JSON mode with streaming?
A: Yes, both json and json_schema modes work with streaming. The JSON will be streamed incrementally.
Q: How do I debug schema validation errors?
A: Check that your schema follows JSON Schema Draft 2020-12 specification. Use online validators like jsonschemavalidator.net to test your schema.
Related:
- Create Model Response - API reference
- Function Calling - Structured tool outputs
- Best Practices - Optimization tips