Structured JSON output for automation
You'll end up with code that gets JSON with the fields you need from a model and validates it before passing it to a spreadsheet, CRM, accounting software or backend.
You need: a fetch_... key (create one), a balance of at least $0.01 (top up), Python 3.10+ with pip install openai pydantic or Node.js 18+ with npm install openai zod.
- 1Describe the fields
Types: string, number, yes/no, a choice from a list. For a list, always set
enum, or you'll get "Delivery", "delivery" and "shipping". - 2Send a request with the schema
response_formatwithjson_schemaandstrict: true— example 1. Few fields?json_objectwith the fields in the prompt is enough — example 2. - 3Validate the answer in code
pydanticorzod. Even a strict schema doesn't guarantee a correct answer. - 4Give a second chance
If validation fails, show the model its answer and the error and ask for corrected JSON. Fails again — hand the document to a person.
1Modes and models
| Mode | What it guarantees |
|---|---|
response_format: {"type": "json_object"} | valid JSON, fields are not checked |
response_format: {"type": "json_schema", ...} with strict: true | JSON that follows your schema: the right fields of the right types |
| Model | Strict schema | json_object |
|---|---|---|
deepseek-v4.1-flash | yes | yes |
claude-haiku-5-5 | yes | yes |
gpt-6-luna | no | — |
Test other models on 20–50 of your own examples. Prices: Models and pricing.
2Example 1. Invoice data, strict schema
"""
Invoice data as JSON that follows a strict schema.
pip install openai pydantic
"""
import os
from typing import Literal
from openai import OpenAI
from pydantic import BaseModel, ConfigDict, Field, ValidationError
MODEL = "deepseek-v4.1-flash" # or "claude-haiku-5-5"
client = OpenAI(
base_url="https://api.zukko.pro/v1",In Node.js the schema for the model and the zod schema are written separately — keep them in sync. In Python both come from the Invoice class.
3Example 2. Support ticket triage, json_object mode
"""
Triage a support ticket: category, priority, whether a human is needed.
pip install openai pydantic
"""
import os
from typing import Literal
from openai import OpenAI
from pydantic import BaseModel, ValidationError
client = OpenAI(
base_url="https://api.zukko.pro/v1",
api_key=os.environ["ZUKKO_API_KEY"],
timeout=60,4Schema rules
- Numbers as numbers (
1540.05, not "EUR 1,540.05"), currency in its own field. - Dates as strings, format in the field description:
YYYY-MM-DD. - 5–10 fields, no deep nesting.
- Every field in
required,additionalProperties: false.pydanticwithextra="forbid"does this for you.
5If it doesn't work
| What you see | What to do |
|---|---|
| The answer starts with three backticks and the word json | Strip the wrapper with clean() from the example |
"Shipping" instead of delivery | Set an enum on the field |
| The JSON is cut off halfway | Raise max_tokens |
| The model invents a number or date | Allow an empty string in the field description and say "do not make anything up" in the instruction |
| The answer takes about a minute and ignores the schema | Use deepseek-v4.1-flash or claude-haiku-5-5 |
400 mentioning response_format | Pick a model from the table above or use json_object mode |