> ## Documentation Index
> Fetch the complete documentation index at: https://docs.textin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Schema Guide

> Create schemas for **Extract**.

A schema defines the fields the extraction API should return. Use clear field names, precise descriptions, and simple structures to improve extraction quality.

## What a schema defines

At minimum, a schema defines:

* The output field names
* The expected value type for each field
* A description of what each field means
* Whether nested objects or arrays should be returned

Example:

```json theme={null}
{
  "type": "object",
  "properties": {
    "invoice_number": {
      "type": ["string", "null"],
      "description": "The invoice number"
    },
    "total_amount": {
      "type": ["number", "null"],
      "description": "The total amount including tax"
    }
  },
  "required": ["invoice_number", "total_amount"]
}
```

## Ways to create a schema

You can create a schema in two ways:

* Ask the Document Agent to generate a draft schema from the current document.
* Create or edit the schema JSON locally.

### Generate a draft schema with the Document Agent

The fastest way to get started is to ask the Document Agent to generate a draft schema JSON used by Extract for the current document.

Typical workflow:

<Steps>
  <Step title="Open a document">
    Open a document in the web app.
  </Step>

  <Step title="Ask the Document Agent">
    Ask the Document Agent to generate the schema JSON for the fields you need.
  </Step>

  <Step title="Review the schema">
    Review the proposed schema in the editor.
  </Step>

  <Step title="Edit as needed">
    Edit field names, field types, descriptions, and output order as needed.
  </Step>

  <Step title="Run extraction">
    Run extraction and review the result.
  </Step>
</Steps>

The generated schema is editable. You can refine field descriptions, remove unnecessary fields, change field types, and reorder fields before using the schema in production.

### Create or edit a schema manually

If you prefer to define the schema yourself, create or edit the schema JSON locally.

<Steps>
  <Step title="Write the schema">
    Write or paste the schema JSON used by Extract.
  </Step>

  <Step title="Save the schema">
    Save the schema as a local JSON file.
  </Step>

  <Step title="Include it in the request">
    Include the schema in your API request.
  </Step>

  <Step title="Run extraction">
    Run extraction and review the result.
  </Step>

  <Step title="Revise">
    Revise field names, types, descriptions, or nesting as needed.
  </Step>
</Steps>

This path is useful when:

* You already have a schema design from your application.
* You want precise control over field names and output structure.
* You want to refine a generated schema before using it in production.
* You want to manage schemas in code, version control, or internal tooling.

## Use the schema in an API request

If you created the schema locally, include the JSON file directly in your API request.

If you created the schema in the web app, export it as JSON before reusing it through the API.

```python theme={null}
import base64
import json
import os
import requests

with open("invoice_schema.json", "r", encoding="utf-8") as schema_file:
    schema = json.load(schema_file)

with open("invoice.pdf", "rb") as file:
    file_base64 = base64.b64encode(file.read()).decode("utf-8")

response = requests.post(
    "https://api.textin.ai/ai/service/v3/entity_extraction",
    headers={
        "x-ti-app-id": os.environ["TEXTIN_APP_ID"],
        "x-ti-secret-code": os.environ["TEXTIN_SECRET_CODE"],
        "Content-Type": "application/json",
    },
    json={
        "file": {"file_base64": file_base64},
        "schema": schema,
    },
)

print(response.json()["result"]["extracted_schema"])
```

## Schema JSON structure

### Object structure

Most extraction schemas use an object at the top level.

```json theme={null}
{
  "type": "object",
  "properties": {
    "field_name": {
      "type": ["string", "null"],
      "description": "Field description"
    }
  },
  "required": ["field_name"]
}
```

| Field        | Description                                      |
| ------------ | ------------------------------------------------ |
| `type`       | The schema or field type                         |
| `properties` | Fields to extract                                |
| `required`   | Fields that are required in the schema structure |

### Common field properties

Individual fields can include additional properties depending on the field type.

| Field         | Used for         | Description                               |
| ------------- | ---------------- | ----------------------------------------- |
| `description` | Most field types | Natural-language description of the field |
| `enum`        | `type: "enum"`   | Predefined values for enum fields         |
| `items`       | `type: "array"`  | Schema for array items                    |

## Field types

The examples in this section show field definitions inside `properties`, not complete top-level schemas.

| Type      | Description                      | Example                             |
| --------- | -------------------------------- | ----------------------------------- |
| `string`  | Text                             | `"John Doe"`                        |
| `number`  | Numeric value                    | `123.45`                            |
| `integer` | Integer value                    | `42`                                |
| `enum`    | One value from a predefined list | `"Paid"`                            |
| `object`  | Nested fields                    | `{"name": "...", "address": "..."}` |
| `array`   | List of values or objects        | `[{...}, {...}]`                    |

### Enum field example

```json theme={null}
{
  "type": "enum",
  "enum": ["Paid", "Pending", "Overdue"],
  "description": "Payment status"
}
```

### Nullable fields

Use nullable types when a field may be missing:

```json theme={null}
{
  "type": ["string", "null"],
  "description": "The purchase order number"
}
```

Use this pattern when a field may be absent or empty in the source document.

In practice, fields that cannot be extracted may be returned as empty values, such as an empty string or an empty array, depending on the field type.

## Schema limits

| Limit                 |    Value |
| --------------------- | -------: |
| Maximum nesting depth | 3 levels |
| Maximum leaf fields   |      100 |

A leaf field is a field that holds a final extracted value rather than nested fields.

## Common schema patterns

Each example in this section is a complete top-level schema that you can adapt for your own extraction task.

### Single value

Use a single field when the value appears once in the document.

```json theme={null}
{
  "type": "object",
  "properties": {
    "invoice_number": {
      "type": ["string", "null"],
      "description": "The invoice number"
    }
  },
  "required": ["invoice_number"]
}
```

### Multiple values

Use an array when the document may contain multiple values for the same field.

```json theme={null}
{
  "type": "object",
  "properties": {
    "available_colors": {
      "type": "array",
      "description": "All available product colors",
      "items": {
        "type": "string"
      }
    }
  },
  "required": ["available_colors"]
}
```

### Table rows

Use an array of objects when you need repeated rows with the same structure.

```json theme={null}
{
  "type": "object",
  "properties": {
    "line_items": {
      "type": "array",
      "description": "Invoice line items",
      "items": {
        "type": "object",
        "properties": {
          "description": {
            "type": ["string", "null"],
            "description": "Item description"
          },
          "quantity": {
            "type": ["number", "null"],
            "description": "Item quantity"
          },
          "amount": {
            "type": ["number", "null"],
            "description": "Line item amount"
          }
        },
        "required": ["description", "quantity", "amount"]
      }
    }
  },
  "required": ["line_items"]
}
```

### Nested object

Use nested objects for grouped fields.

```json theme={null}
{
  "type": "object",
  "properties": {
    "vendor": {
      "type": "object",
      "description": "Vendor information",
      "properties": {
        "name": {
          "type": ["string", "null"],
          "description": "Vendor name"
        },
        "address": {
          "type": ["string", "null"],
          "description": "Vendor address"
        }
      },
      "required": ["name", "address"]
    }
  },
  "required": ["vendor"]
}
```

## Field description guidelines

Good descriptions:

* Use the wording that appears in the source document when possible.
* Explain what the value means.
* Include units, date formats, or currency expectations when relevant.
* Avoid asking the model to calculate values that are not directly present.

Examples:

| Weak description | Better description                               |
| ---------------- | ------------------------------------------------ |
| `Amount`         | `The total amount including tax`                 |
| `Date`           | `The invoice issue date`                         |
| `Name`           | `The vendor or merchant name`                    |
| `Status`         | `Payment status. One of: Paid, Pending, Overdue` |

## Next steps

<CardGroup cols={3}>
  <Card title="Extract Quickstart" icon="rocket" href="/xparse/extract/quickstart">
    Extract your first document.
  </Card>

  <Card title="Response Format" icon="code" href="/xparse/extract/response-format">
    Understand the output.
  </Card>

  <Card title="Best Practices" icon="lightbulb" href="/xparse/extract/best-practices">
    Improve extraction accuracy.
  </Card>
</CardGroup>
