Skip to main content
Tell us which fields you want (invoice_number, total, line_items[]) and get back just those fields, filled from the document. Every value arrives with proof: the page it came from, a bounding box you can highlight, and the verbatim source text. That’s the difference from parsing: POST /v1/parse gives you the whole document as structured chunks. Schema extraction reads the document for you and answers in exactly the shape your application expects.

Request

POST /v1/extract/schema (JSON body with a url) or POST /v1/extract/schema/file (multipart upload; required for PHI keys). The document can be any supported input: PDF, PPTX, DOCX, or an image (PNG, JPEG, WebP, TIFF, HEIC/HEIF, BMP). The schema is standard JSON Schema, and it is the whole interface: the fields you define are the request, and their descriptions are instructions the extractor follows. A one-line description is the cheapest accuracy lever you have. Say what the field looks like on the page, not just what it means:
Supported subset: string / number / integer / boolean, object (with properties), array (with items), plus enum and description on leaves. Nesting up to 5 levels. Wide schemas are capped (a few hundred fields) and return 422 with a “split your schema” message, so keep schemas focused on one document type.
Use enum for fields with a known set of values (status codes, document types, states). It stops casing and phrasing drift: you’ll get "approved" every time instead of "Approved", "APPROVED", and "approved ✓" across documents.

Request options

The schema is usually all you send. Four more fields tune a run:

Response

values is your schema, filled in, with null where the document genuinely lacks a field. evidence is a parallel map keyed by field path: each value’s source page, box, verified text, and a confidence score.
Three fields do the heavy lifting:
  • strict (default true): a non-null value whose quote can’t be verified against the page is nulled out and listed in ungrounded_fields. This is the safe default: a fabricated value never reaches you. Set strict: false to keep such values but still see them flagged.
  • bbox: [x0, y0, x1, y1] normalized to 0-1000, page-relative, top-left origin. Overlay it directly on a page render without fetching page dimensions. It can be null when the cited text has no box to point at (converted office formats like DOCX and PPTX don’t always carry one). Handle that case before overlaying.
  • confidence: 0 to 1, scored on the hardest-to-read character of the cited text, so one shaky digit lowers the whole score instead of hiding behind an otherwise clear value. It’s null when a citation doesn’t have a score. Route low-confidence values to human review.
Some citations may also carry needs_review: true and a suggested_value: a hint that an identifier was hard to read and is worth confirming. The value in values is never overwritten. These fields are additive; treat their absence as false / null.
On auto_schema runs the response also includes generated_schema: the schema we designed and filled. Save it and pass it as schema on later calls to lock the shape in.

Example

Billing

4 credits per page — $12 per 1,000 pages, all-in. The parse is included, so you’re not paying the 1-credit parsing rate on top. Billed responses carry a usage object with the exact pages, credits, and credits_per_page charged. See Pricing.

Next steps

Parse the whole document

Need every chunk, table, and figure instead of specific fields? Start with the parse quickstart.

Run schemas at scale

Processing thousands of documents? Use the async batch lane and keep the same response schema.