Overview
An extraction schema is a JSON object that defines which fields to extract from a document and how to structure the output. You pass the schema to the API along with Markdown content generated by the API.
Use this article as a reference for understanding how schemas are structured and how the API handles unsupported keywords.
Basic Structure
The extraction schema must follow this structure:
{
"type": "object",
"properties": {
"your_field_name": {
"type": "string",
"description": "Describe what to extract."
}
}
}
Example
This schema extracts two fields from an invoice. It also includes the optional x-alternativeNames keyword to account for field name variations across documents:
{
"type": "object",
"properties": {
"total_invoice_amount": {
"description": "The total monetary value of the invoice, including all charges and taxes.",
"x-alternativeNames": [
"Total Invoice Amount",
"Grand Total",
"Amount Due"
],
"type": "number"
},
"bank_name": {
"description": "The official name of the bank where the payment will be deposited.",
"x-alternativeNames": [
"Bank Name",
"Beneficiary Bank",
"Financial Institution"
],
"type": "string"
}
}
}
Top-Level Type Requirement
The top-level type keyword must be "object". Schemas with a different top-level type will return an error.
In the following example, the highlighted line shows the required top-level type keyword:
{
"type": "object",
"properties": {}
}
Define Each Field
Each field you want to extract is defined as a property inside the properties keyword. Each property can include the following:
| Required | Description |
|---|
| Field name | Required | The key used to identify the extracted value in the output. |
type | Required | The data type of the extracted value. |
description | Optional | Natural-language description of what to extract. |
enum | Optional | Restricts the extracted value to a set of allowed values. |
format | Optional | Instructions for how to format the extracted value. |
x-alternativeNames | Optional | Alternative labels for the field that may appear across different documents. |
properties | Required for object types | Defines the fields within a nested object. |
items | Required for array types | Defines the structure of items in an array. |
Field Names
Required. The field name is the key that identifies each property in the properties object and determines how the extracted value is labeled in the output.
Field names can contain letters, numbers, underscores, and hyphens. Use descriptive, specific names that clearly indicate what data to extract:
invoice_number instead of number
patient_name instead of name
In the following example, the highlighted lines are field names:
{
"type": "object",
"properties": {
"account_holder": {
"description": "The name of the individual or entity who owns the bank account.",
"x-alternativeNames": [
"Account Holder",
"Account Owner",
"Primary Account Holder"
],
"type": "string"
},
"ending_balance": {
"description": "The total amount of money in the account at the end of a specific period.",
"x-alternativeNames": [
"Ending Balance",
"Final Balance",
"Closing Balance"
],
"type": "number"
}
}
}
Supported Field Types
Required. Use the type keyword to define the data type of the extracted value. Supported types are:
| Type | Description |
|---|
array | A list of items. To see an example, go to Arrays. |
boolean | True or false values. |
integer | Whole numbers. |
number | Numeric values, including decimals. Use this type for monetary values or when you need to perform calculations on the extracted value. |
object | A nested structure. To see an example, go to Nested Objects. |
string | Text values. |
In the following example, the highlighted line shows the type keyword:
{
"type": "object",
"properties": {
"statement_date": {
"description": "The date on which the financial statement was issued.",
"format": "Month DD, YYYY",
"x-alternativeNames": [
"Statement Date",
"Date of Statement",
"Billing Date"
],
"type": "string"
}
}
}
To restrict a field to a specific set of allowed values, use the enum keyword.
Restrict Values with Enum
Optional. Use the enum keyword to restrict the extracted value to a specific set of allowed values. Only string values are supported. Include "type": "string" in the field definition. Any non-string values are converted to strings.
For example, the following schema restricts the extracted account type to one of three allowed values. The highlighted lines show the type and enum keywords:
{
"type": "object",
"properties": {
"account_type": {
"type": "string",
"description": "The classification of the bank account, such as checking or savings, with specific features.",
"x-alternativeNames": [
"Account Type",
"Type of Account",
"Account Category"
],
"enum": [
"Premium Checking",
"Basic Checking",
"Savings"
]
}
}
}
In the Playground, “enum” appears as a field type option in the Type drop-down menu. When you export the schema, the Playground outputs this correctly using the enum keyword.
Field Descriptions
Optional. Use the description keyword to help the API identify and extract the correct data. The more specific your descriptions, the more accurate the extraction.
Include the following in your descriptions:
- Exactly what data to extract
- What to include or exclude (for example, “excluding tax” or “including area code”)
In the following example, the highlighted line shows the description keyword:
{
"type": "object",
"properties": {
"total_amount": {
"type": "number",
"description": "Total amount in USD, excluding tax"
}
}
}
Optional. Use the format keyword to specify how the extracted value should be formatted. This is most commonly applied to string fields.
The format keyword accepts natural-language instructions and standard JSON Schema format values. Natural-language instructions offer more flexibility, since you can describe formatting requirements that don’t have a standard equivalent. We recommend experimenting with different values to find what works best for your use case.
The following examples illustrate the range of options:
format value | Output example |
|---|
YYYY-MM-DD | 2026-01-17 |
Month DD, YYYY | January 17, 2026 |
Currency amount with the $ symbol, for example $12.50 | $170.23 |
Two-letter US state code | CA |
In the following example, the highlighted line shows the format keyword:
{
"type": "object",
"properties": {
"statement_date": {
"type": "string",
"format": "YYYY-MM-DD",
"description": "The date on which the financial statement was issued."
}
}
}
Alternative Names
Optional. Use the x-alternativeNames keyword to list alternative labels for a field. This helps the API locate the correct data when documents use different labels for the same field, such as “Invoice Number” versus “Reference Number.”
In the following example, the highlighted lines show the x-alternativeNames keyword:
{
"type": "object",
"properties": {
"total_amount": {
"type": "number",
"x-alternativeNames": [
"Total Amount",
"Grand Total",
"Amount Due"
],
"description": "The total monetary value of the invoice."
}
}
}
Properties (For Objects)
Required for object types. Use the properties keyword to define the fields within a nested object. For a full example, see Nested Objects.
Required for array types. Use the items keyword to define the structure of items in an array. For a full example, see Arrays.
Nested Objects
Use nested objects when the data you want to extract has a natural hierarchical structure. For example, an invoice might include a billing address with multiple sub-fields (street, city, state, and ZIP code), or a patient form might have separate sections for personal details and insurance information.
In the following example, the highlighted lines show a nested properties keyword inside the invoice object:
{
"type": "object",
"properties": {
"invoice": {
"type": "object",
"properties": {
"number": {
"type": "string",
"description": "Invoice number"
},
"date": {
"type": "string",
"description": "Invoice date"
},
"total": {
"type": "number",
"description": "Total amount"
}
}
}
}
}
Arrays
Use arrays to extract repeating structures from a document, such as all rows in a table. Each item in the array follows the same schema, making arrays well-suited for data like transaction lists, invoice line items, or lists of charges.
To define an array field:
- Set
"type": "array" on the field.
- Include the
items keyword to define the structure of each item.
- Inside
items, define the fields each item should contain.
The following example extracts financial transactions from a bank statement, where each transaction is an object with three fields:
{
"type": "object",
"properties": {
"transactions": {
"description": "A list of all financial transactions recorded for the account.",
"x-alternativeNames": [
"Transaction History",
"Activity Log",
"Movements"
],
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"description": "The date when the transaction occurred.",
"format": "YYYY-MM-DD",
"x-alternativeNames": [
"Transaction Date",
"Date of Transaction",
"Activity Date"
],
"type": "string"
},
"description": {
"description": "A brief description of the transaction.",
"x-alternativeNames": [
"Transaction Description",
"Details",
"Item"
],
"type": "string"
},
"type": {
"description": "The type of transaction, for example debit, credit, deposit, or withdrawal.",
"x-alternativeNames": [
"Transaction Type",
"Category",
"Kind"
],
"type": "string"
}
}
}
}
}
}
Keyword Support
The API only supports a specific set of JSON Schema keywords. Unsupported keywords are removed before extraction runs; they do not cause errors.
Supported Keywords
The API supports the following keywords. For details on each, see Define Each Field.
Ignored Keywords
The following keywords are not supported but will not cause errors. The API removes or resolves them before running extraction.
| Keyword | How the API handles it |
|---|
Reference keywords: $anchor, $defs, $id, $ref, $schema, definitions | Used to define and reference reusable schema components. All references are resolved during schema conversion. The keywords are then removed. |
Recursive and dynamic keywords: $dynamicAnchor, $dynamicRef, $recursiveAnchor, $recursiveRef | Used for self-referential schemas. All references are resolved during schema conversion. The keywords are then removed. |
anyOf | To ensure consistent output, each field is limited to a specific type.
If one of the anyOf types is null, the API removes null and sets the type to the other specified type.
If none of the types are null, the API falls back to string, since that is least likely to cause issues. |
default | The API removes the keyword. |
nullable | The API removes the keyword. All fields are nullable by default. For more information, see How the API Handles Missing Fields. |
required | The API removes the keyword. The API considers all fields to be required. |
title | The API removes the keyword. Typically, the title does not give additional information that is not already present in the field name or description. |
Other Unsupported Keywords
Any keyword not listed in Supported Keywords or Ignored Keywords is removed during schema conversion, and extraction continues with the remaining schema. The following list provides common examples and is not exhaustive:
allOf
const
maxItems
maxLength
maximum
minItems
minLength
minimum
oneOf
pattern
propertyOrdering
uniqueItems
How the API Handles Required Fields
The API treats all fields as required and always attempts to extract every property defined in your schema. The required keyword is not supported and is ignored if included. For more information, see Ignored Keywords.
If the API cannot find a field in the document, it returns null rather than an error. For more information, see How the API Handles Missing Fields.
How the API Handles Missing Fields
All fields are nullable, meaning the API returns null when it cannot find a field in the document rather than returning an error. Because of this, the API ignores null and nullable if included in your schema. For more information, see Ignored Keywords.
For example, if your schema includes a first_name field but the document does not contain a first name, the API returns null for that field.
The exact behavior depends on the field type:
| Field type | Behavior when not found |
|---|
Primitive fields (boolean, integer, number, string) | Returns null. |
array | Returns an empty array: []. |
object | Never returns null, but all primitive fields within it return null. |
Schema Validation
The API processes your schema in two stages:
The API checks that your schema is valid JSON and follows the required structure. If validation fails, the API returns a 422 error before processing begins. Common causes are a schema that is not valid JSON, a root that is not "type": "object", or recursive $ref cycles.
Convert Schema (During Processing)
The API converts your schema before running extraction. Keywords that are not supported are removed during this step (see Ignored Keywords and Other Unsupported Keywords), and extraction continues with the remaining schema.
Does the order of properties in the schema need to match the order of the fields in the document?
No. The order of properties in the schema has no impact on extraction. For example, a property defined last in the schema can still extract data from a field that appears at the top of the document.
No. There is no maximum number of properties in an extraction schema.
You can include formatting instructions and alternative field names in description, but using the dedicated format and x-alternativeNames keywords is more effective.
When you use dedicated keywords, the API knows exactly what each piece of information is: format contains only formatting instructions, and x-alternativeNames contains only alternative field labels. This allows the API to apply each more precisely than if the same information were embedded in a general description.
For more information, see Format and Alternative Names.
What is the best practice for writing field descriptions?
Be as specific as needed so there is no ambiguity about what to extract. Think of it as natural-language instructions (like prompting an LLM). The clearer and more specific it is, the better the results. You may want to iterate on your descriptions to find what works best for your use case.
For more information, see Field Descriptions.