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

# Schema Keyword Support

> Which JSON Schema keywords Extract guarantees in the output, and which it treats as guidance

Extract accepts a JSON Schema and returns JSON that matches it. Not every keyword carries the same guarantee. Some keywords are enforced: the output always satisfies them. Others are best effort: Extract reads them as guidance and follows them in most cases, but you should validate them in your own code.

This page applies to the `v4` extract model, the current default. See [Model Versions](/reference/model-versions) for version status.

***

## How Extract uses your schema

Your schema does two jobs at once:

1. **Output shape.** Extract constrains the response so it always has the fields and types you declared.
2. **Guidance.** Field names, descriptions, and constraints tell Extract what to look for and how to format it.

Enforced keywords do both jobs. Best-effort keywords only do the second one. For example, `"pattern": "^[A-Z]{2}-\\d{4}$"` on a string guarantees the output matches. `"format": "email"` does not guarantee a valid address, but it does steer Extract toward one.

***

## Enforced keywords

The output satisfies these keywords, with the exceptions noted in each row.

| Keyword | Notes |
| - | - |
| `type` | Includes type lists such as `["string", "null"]`. Scalar fields can also be `null` when the value is not in the document. |
| `enum` | The output value is always one of the listed values, or `null` when the value is not in the document. |
| `properties` | Every declared field is always present. |
| `required` | Treated as all fields required. Every declared field is always in the output. |
| `additionalProperties` | Objects are closed by default: Extract only returns declared fields. |
| `items` | Every array item matches the item schema. |
| `prefixItems` | Positional item schemas are honored. |
| `minItems`, `maxItems` | Array length stays inside the bounds during generation. Extract then drops empty items (`null`, `[]`, or objects with only `null` values), so a returned array can be shorter than `minItems`. |
| `minLength`, `maxLength` | String length stays inside the bounds. |
| `pattern` | The whole string must match. Patterns are treated as anchored even without `^` and `$`. |
| `minimum`, `maximum`, `exclusiveMinimum`, `exclusiveMaximum` | Exact for integers. For non-integer numbers, exclusive bounds can behave like inclusive bounds. |
| `anyOf`, `oneOf` | The output matches at least one branch. |
| `patternProperties`, `propertyNames`, `minProperties` | Object key constraints are honored. |
| `$ref` to `#/$defs/...` | Local references are resolved before extraction. |
| `nullable: true` | Treated as adding `null` to `type`. |

### Every field is always returned

Extract returns every declared field on every object, even if you list only some of them in `required`. Scalar fields (string, number, integer, boolean, enum) with no supporting value in the document come back as `null`. Object and array fields keep their declared shape: an array with no matches is `[]`, and an object has all of its own fields set to `null`. If a field must not be `null` in your system, check for it in your code.

```json theme={null}
{
  "type": "object",
  "properties": {
    "invoice_number": { "type": "string" },
    "po_number": { "type": "string" }
  },
  "required": ["invoice_number"]
}
```

Output for a document with no PO number:

```json theme={null}
{ "invoice_number": "INV-2041", "po_number": null }
```

***

## Best-effort keywords

Extract reads these keywords as guidance. Output usually follows them, but it is not guaranteed. Validate these in your code if they matter.

| Keyword | What to expect |
| - | - |
| `description`, `title`, `examples` | Guidance only. Descriptions are the strongest lever you have for extraction quality. See [Best Practices](/extraction/best-practices-extract). |
| `format` | Steers formatting for values such as `date`, `date-time`, `email`, and `uuid`. Use `pattern` when the exact shape must be guaranteed. |
| `const` | Not guaranteed. Extract usually returns the declared value. Use a single-value `enum` when the value must be enforced. |
| `uniqueItems` | Not guaranteed. Duplicate array items can appear. Deduplicate in your code when uniqueness matters. |
| `multipleOf` | Not guaranteed. |
| `allOf` | Not guaranteed. Merge the branches into a single schema when possible. |
| `not` | Not guaranteed. |
| `if`, `then`, `else`, `dependentRequired`, `dependentSchemas` | Conditional rules are not guaranteed. |
| `contains`, `minContains`, `maxContains` | Not guaranteed. |

### Prefer `pattern` over `format`

`format` improves how Extract writes a value, but only `pattern` guarantees the shape.

```json theme={null}
{
  "type": "string",
  "description": "Invoice date in ISO 8601 format",
  "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
}
```

***

## Ignored keywords

These keywords are accepted but have no effect on extraction: `default`, `$comment`, `$schema`, `deprecated`, `readOnly`, `writeOnly`.

***

## Schema validation

Extract validates your schema before it runs. Invalid schemas fail with a `400` and a message that points at the problem. Common causes:

* The schema is not valid JSON Schema (draft 2020-12).
* An object declares no `properties`.
* An array declares no `items`.
* `$ref` points outside `#/$defs`, or forms a cycle.
* A `required` entry names a field that is not in `properties` on a closed object.
* An `enum` value does not match the declared `type` or violates a sibling constraint, such as `"enum": ["ab"]` with `"minLength": 3`.

***

## Troubleshooting

**A value comes back `null` even though it is in the document.**
Extract works from the Parse output, so your Parse configuration affects extraction accuracy. Use [Parse r-1](/parse/r-1) or [agentic modes](/configs/parse/agentic-modes) for the best results. If the value is still missing, tighten the field `description` to say where the value appears.

**A string does not match my `format`.**
`format` is best effort. Add a `pattern` for the exact shape.

**An extra field I did not declare is missing.**
Extract only returns declared fields. Declare the field in `properties`.

**My `allOf` constraint is not respected.**
`allOf` is best effort. Combine the branches into one object schema with the union of their properties and constraints.
