Extract structured data in Python
⚠️
Preview — this feature is being built; the design below is the spec.
Pull invoice fields out of free text into a typed object with a JSON schema.
import json, os
import requests
SCHEMA = {
"type": "object",
"additionalProperties": False,
"required": ["supplier", "invoice_number", "issue_date", "total", "currency", "line_items"],
"properties": {
"supplier": {"type": "string"},
"invoice_number": {"type": ["string", "null"]},
"issue_date": {"type": ["string", "null"], "description": "YYYY-MM-DD"},
"total": {"type": "string", "description": "Decimal, two places, no symbol"},
"currency": {"type": "string", "enum": ["EUR", "GBP", "USD", "AED", "OTHER"]},
"line_items": {"type": "array", "maxItems": 50, "items": {
"type": "object", "additionalProperties": False, "required": ["description", "amount"],
"properties": {"description": {"type": "string"}, "amount": {"type": "string"}}}},
},
}
def extract(text: str) -> dict:
r = requests.post(
"https://app.syntic.ai/v1/chat/completions",
headers={"Authorization": f"Bearer {os.environ['SYNTIC_API_KEY']}"},
json={
"model": "Amara Quick",
"stream": False,
"max_tokens": 1500,
"response_format": {"type": "json_schema", "json_schema": {"name": "invoice", "schema": SCHEMA, "strict": True}},
"messages": [
{"role": "system", "content": "Extract invoice fields. Use null when a field is not stated. Never compute a total that is not printed."},
{"role": "user", "content": text},
],
},
timeout=60,
)
r.raise_for_status()
choice = r.json()["choices"][0]
if choice["finish_reason"] == "length":
raise RuntimeError("cut off; raise max_tokens")
if choice["finish_reason"] == "refusal":
raise RuntimeError(choice["message"]["refusal"])
return json.loads(choice["message"]["content"])
print(extract("ACME Tools Ltd — Invoice 2026-118, 3 Nov 2026. 4x drill bits 36.00; delivery 9.50. Total GBP 45.50"))Expected output:
{"supplier": "ACME Tools Ltd", "invoice_number": "2026-118", "issue_date": "2026-11-03", "total": "45.50", "currency": "GBP",
"line_items": [{"description": "4x drill bits", "amount": "36.00"}, {"description": "delivery", "amount": "9.50"}]}Check sums in your own code (sum(line_items) == total) rather than asking the model to; arithmetic belongs in code. See Design schemas.
Was this page helpful?