Extract
POST /v1/decision-machine-1/extract fills a JSON Schema from one text. You send text and schema. The model reads the text once and returns data in the shape of your schema. The shape supports strings, numbers, integers, booleans, enums, string arrays and nested objects. An array-of-objects property is accepted and returned empty for now. A field the text does not carry comes back as null. Nothing is generated: every value comes from a span in the text.
When to use it
- You need several fields from one document in one call: an invoice, a résumé, an order confirmation.
- You already have a JSON Schema and want it filled.
- Use Answer instead when you need one field plus its character offsets.
- Use Entities instead when you want every occurrence of a type, not one value per field.
- Use Verify after extraction to check a critical value against the source text.
Three example decisions
- Pull the invoice number, the total and the payment terms from a billing email.
- Turn a shipping confirmation into
{tracking_number, carrier, delivery_date}. - Read a job application and fill
{candidate_name, years_experience, remote_ok}.
Request
text and texts are mutually exclusive. Send one of them, never both.
Write a description on every property. The description is what the model searches for. "total_due" alone works; "total amount due" works better.
No API key is required during the launch period.
Response
This capture ran the same schema with tags and vendor added. The call took 0.72 s.
data— one object in the shape of your schema. Onlydatacomes back. There is no probability on this endpoint.- Scalar values carry the text’s own span, coerced to your type.
- A missing value is
null. The key stays in place. - A batch over
textswraps the results:{"results":[{"data":{...}}, ...]}.
Reading the numbers
Extract returns no probability, so read the values themselves.
The scalars above are all correct: total_due parsed $2,676.00 into 2676, net_terms_days truncated Net 30 to 30, and paid read yes as true.
One field is wrong, and the failure is typical. vendor.name copied the billing name, because the text has no vendor block. The model fills a described field with the closest span it finds; it does not refuse.
Treat the result as a draft. Some fields move money or write to a record. Send those values and the source text to Verify. Check matches before you commit the value.
Batching
Send texts instead of text to run the same schema over up to 32 texts. Each text costs one inference call.
Results keep the input order. Batching covers the shape on every capability.
Schema support matrix
This call used prices as an array of number, day as a string, meta as {"type":"null"} and weird as an anyOf:
The prices came back as strings, and weird came back null. The key meta is absent from data.
Limits and gotchas
texttakes up to 20,000 characters.textstakes up to 32 items, each up to 20,000 characters.- Send
textortexts, never both. Sending neither also fails, with the same message:body: provide text or texts, not both. - A root schema that is not an object with
propertiesreturns400:
- The common mistake is a bare field name with no
description. Describe the field in the words the document uses. - The second mistake is trusting
required. Handlenullin your own code. - Array order is not stable between calls. Compare arrays by value, not by position.
- Keep schemas small. Root scalar fields run in groups of four, because one large structure makes fields compete for the same span.
- Text over 2,000 characters is chunked, and the records from each chunk merge. Long text and chunking covers the rules.
- Extract runs on the multilingual model, so it reads non-English text. Languages gives the guidance.
- Observed latency: 0.72 s for a nine-property schema, 1.03 s for two texts.
Next
- Extract, then verify — check a value before you write it anywhere.
- Invoice extraction with verification — the invoice header schema with a review queue.
- Structured extraction — the same capability through an OpenAI client.