response_schema automatically. The shape you pass determines what they type into. This page lists every shape that renders well, and what falls back to a JSON textarea.
Primitives
Map cleanly to form fields.Optional fields
Optional[X] flattens to the underlying type. The form field is unrequired but renders as the inner kind, not as a generic JSON textarea.
Nested objects
Render as an indented section with the inner fields stacked vertically. Useful for grouping related data.Lists of objects (the killer feature)
list[BaseModel] becomes a spreadsheet-style editable table on the reviewer’s dashboard. One column per property of the element model. The reviewer adds rows, edits cells inline, removes rows.
line_items:
Multi-page response patterns
Three common ways to structure a response for a multi-page document. Pick the one that matches your downstream code; the SDK doesn’t enforce any particular pattern.Pattern 1: Flat list across all pages (simplest)
Pattern 2: Page-keyed structure
repeatable_group (spreadsheet) where each row is itself a section (the per-page object). The reviewer adds one row per page and fills in the section per row. Useful when your downstream code reasons about pages explicitly.
Pattern 3: Top-level totals + nested table
Fields and constraints we recognize
What doesn’t render well (yet)
Some shapes fall back to a long_text JSON textarea. The reviewer can still submit (by typing JSON), but the UX isn’t ideal. v1 limitations:Union[str, int]and similar multi-variant unions- Discriminated unions
- Self-referential schemas (a model that references itself)
- Schemas nested deeper than 6 levels
Examples
The smoke test we use in CI is a real reference for what works:Where to go next
The three flows
Combine schemas with Flow A (prior_extraction) for pre-filled forms.
Providers
Flow B: which provider you pick affects how the extraction maps to your schema.