---
title: "Generating extraction schemas | Nutrient .NET SDK"
canonical_url: "https://www.nutrient.io/guides/dotnet/csharp/extraction/generate-extraction-schema/"
md_url: "https://www.nutrient.io/guides/dotnet/csharp/extraction/generate-extraction-schema.md"
last_updated: "2026-10-08T00:00:00.000Z"
description: "Generate JSON schemas for structured data extraction using Nutrient .NET SDK."
---

# Generating extraction schemas

Structured extraction starts with a JSON Schema: the schema tells the extraction model exactly which fields to fill, and an LLM's structured-output mode guarantees the result matches it. Writing that schema by hand is the slow part — you study sample documents, name every field, decide what's nullable, what repeats, what's an enum. *Schema generation* drafts it for you: describe the document type, state your requirements in plain language, attach a few example documents, and get back a schema ready for structured-output extraction.

This sample shows how to generate an extraction schema from example documents using Nutrient.NET SDK. Generation uses a vision model — by default a local server, so documents don't have to leave your machine.

[Download sample](https://www.nutrient.io/downloads/samples/csharp/generate-extraction-schema.zip)

## How Nutrient helps

Nutrient.NET SDK runs the full schema generation workflow behind a single method call. The SDK handles:

- Rendering the example documents' pages and sending them to the vision model in one request

- Drafting a schema grounded in the document type, your requirement, and the examples

- Validating and hard-clamping the draft — field budget, nesting depth, and the feature set of your target structured-output dialect

- Optionally drafting cross-field constraint rules (sums, orderings) and validating each one against the schema

- Serializing the result to JSON

The result always satisfies the limits you configured, regardless of what the model drafted — the same call with the same settings yields a schema your extraction target accepts.

## How generation works

Three inputs shape the schema:

- **Document type** (required) — The class of documents the schema must represent, such as "invoice" or "application form". It grounds the schema's vocabulary.

- **Requirement** (optional) — A free-form description of what the schema must capture: fields of interest, granularity, naming preferences — anything you'd tell a colleague.

- **Example documents** (optional, up to five) — Opened documents whose pages are rendered and shown to the model as representative samples. The schema is designed so *other* documents of the same type also fit, not just the examples. At most 20 pages are sent in total across all examples; pages beyond that bound aren't rendered.

Generation requires a vision model. By default the SDK talks to a local OpenAI-compatible server at `http://localhost:1234/v1` — configure the connection through the custom VLM API settings the same way as in the [describe image with local AI](https://www.nutrient.io/guides/dotnet/csharp/extraction/describe-image-with-local-ai.md) guide. Schema generation requires the vision schema generation feature in your license.

## Targeting a structured-output dialect

LLM providers each accept a different subset of JSON Schema in their structured-output modes — one rejects `oneOf`, another rejects `maxItems`, a third silently ignores keywords it doesn't know. The `Compatibility` setting picks the target dialect, and the SDK guarantees the generated schema stays inside it:

- **`SchemaCompatibility.Portable`** (default) — The intersection accepted by the major structured-output modes and local grammar-constrained inference engines. The safest choice when you don't know where the schema will run.

- **`SchemaCompatibility.OpenAI`**, **`SchemaCompatibility.Anthropic`**, **`SchemaCompatibility.Gemini`** — Unlock the keywords that specific provider documents as supported, while enforcing its documented rejections.

- **`SchemaCompatibility.None`** — No dialect filter; any standard JSON Schema feature the other knobs enable.

Every generated schema also satisfies the strict-mode invariants shared by all providers: an object root, every property listed in `required`, `additionalProperties: false` on every object, and optionality expressed as a null type union rather than a missing requirement.

## Bounding the schema

Generated schemas stay within the budgets you set — properties beyond `MaxFields` are truncated and structures deeper than `MaxNestingDepth` are flattened, so a verbose model can't produce an unusable schema. Feature knobs (`AllowEnums`, `AllowNullable`, `AllowStringFormats`, and others) control which JSON Schema features the draft may use.

## Cross-field constraints

A schema describes each field in isolation; it can't say "the subtotal equals the sum of the line item amounts." Setting `IncludeConstraints` to `true` asks the model to also encode such relationships as [JsonLogic](https://jsonlogic.com) constraint rules — inert JSON expressions your validation layer can evaluate after extraction. Every rule is checked against the generated schema: a rule referencing a field that doesn't exist is dropped, so the constraints always match the schema they ship with.

## Complete implementation

Import the Nutrient namespace:

```csharp

using Nutrient;

```

## Building the request

Open the example documents in [using statements](https://learn.microsoft.com/dotnet/csharp/language-reference/statements/using) so resources are cleaned up after processing, then describe what the schema must represent:

```csharp

try
{
    using Document firstExample = Document.Open("input_forms.pdf");
    using Document secondExample = Document.Open("input_forms_detection.pdf");

    using SchemaGenerationRequest request = new SchemaGenerationRequest();
    request.DocumentType = "application form";
    request.Requirement = "Capture the applicant's identity (full name, date of birth, contact details), " +
        "every checkbox group as an enumerated field, and the signature and date block. " +
        "Repeating rows belong in arrays of objects.";
    request.AddExampleDocument(firstExample);
    request.AddExampleDocument(secondExample);

```

## Configuring the schema shape

Create standalone document settings carrying the schema knobs — bound the field budget and opt in to cross-field constraints:

```csharp

    using DocumentSettings settings = new DocumentSettings();
    SchemaGenerationSettings schemaGeneration = settings.SchemaGenerationSettings;
    schemaGeneration.MaxFields = 40;
    schemaGeneration.IncludeConstraints = true;

```

## Generating the schema

Call the static `Vision.GenerateSchema()` with the request and settings:

```csharp

    string resultJson = Vision.GenerateSchema(request, settings);

    File.WriteAllText("output.json", resultJson);
}
catch (NutrientException e)
{
    Console.Error.WriteLine($"Error: {e.Message}");
    Environment.Exit(1);
}

```

## Understanding the output

Schema generation returns a JSON envelope with two members — the shape is the same whether or not constraints are enabled:

- **`schema`** — The generated JSON Schema, ready to pass to an LLM structured-output mode. Every property carries a `description` telling the extractor what to put there.

- **`constraints`** — Cross-field rules (empty unless constraints are enabled). Each carries a short `id`, a one-sentence `description`, and a `rule` — a plain, standard JsonLogic expression that evaluates to `true` when the extracted document is internally consistent, for example, `{"==": [{"var": "total"}, {"+": [{"var": "subtotal"}, {"var": "tax_amount"}]}]}`.

Pass `schema` to your extraction call, and after extraction, evaluate each constraint rule against the extracted data with any JsonLogic implementation — a `false` result flags the document for review. Comparison policy (such as tolerating sub-cent rounding differences in numeric checks) is yours to apply in that evaluation step.

## Error handling

The SDK throws a `NutrientException` when generation fails. Common failure scenarios include a missing document type, more than five example documents, an unreachable vision model endpoint, or a model response that isn't valid JSON after a retry. In production code, catch `NutrientException`, return a clear error message, and log failure details for debugging.

## Conclusion

The workflow for generating an extraction schema is:

1. Open up to five representative example documents using [using statements](https://learn.microsoft.com/dotnet/csharp/language-reference/statements/using) for automatic resource cleanup.

2. Build a `SchemaGenerationRequest` with the document type (required), a natural-language requirement, and the examples.

3. Configure the schema shape — field budget, nesting, target dialect, constraints — through `SchemaGenerationSettings`.

4. Call the static schema generation method on `Vision` to draft, validate, and clamp the schema.

5. Write the envelope to a file; feed `schema` to your structured-output extraction and `constraints` to your validation layer.

6. Handle `NutrientException` for robust error recovery.

For configuring the vision model connection, refer to the [describe image with local AI](https://www.nutrient.io/guides/dotnet/csharp/extraction/describe-image-with-local-ai.md) guide. For related extraction workflows, refer to the [.NET SDK guides](https://www.nutrient.io/guides/dotnet/csharp.md).

Download [this ready-to-use sample package](https://www.nutrient.io/downloads/samples/csharp/generate-extraction-schema.zip) to explore schema generation.
---

## Related pages

- [Nutrient .NET SDK extraction guides](/guides/dotnet/csharp/extraction.md)
- [Applying OCR to a PDF page](/guides/dotnet/csharp/extraction/apply-ocr-to-pdf-page.md)
- [Applying OCR to a PDF document](/guides/dotnet/csharp/extraction/apply-ocr-to-pdf.md)
- [Classifying documents](/guides/dotnet/csharp/extraction/classify-document.md)
- [Generating image descriptions using Claude](/guides/dotnet/csharp/extraction/describe-image-with-claude.md)
- [Generating image descriptions using local AI](/guides/dotnet/csharp/extraction/describe-image-with-local-ai.md)
- [Generating image descriptions using OpenAI](/guides/dotnet/csharp/extraction/describe-image-with-openai.md)
- [Detecting document language](/guides/dotnet/csharp/extraction/detect-document-language.md)
- [Extracting data from images using ICR](/guides/dotnet/csharp/extraction/extract-data-from-image-icr.md)
- [Extracting data from images using OCR](/guides/dotnet/csharp/extraction/extract-data-from-image-ocr.md)
- [Extracting data from images using vision language models](/guides/dotnet/csharp/extraction/extract-data-from-image-vlm.md)
- [Extracting data from specific pages](/guides/dotnet/csharp/extraction/extract-data-from-specific-pages.md)
- [Extracting form fields from images](/guides/dotnet/csharp/extraction/extract-form-fields-from-image.md)
- [Extracting structured data from documents](/guides/dotnet/csharp/extraction/extract-structured-data.md)
- [Extracting JSON data from a PDF document](/guides/dotnet/csharp/extraction/json-data-extraction.md)
- [Labeling form fields with a vision language model](/guides/dotnet/csharp/extraction/label-form-fields-with-vlm.md)
- [Parsing a document into structured content](/guides/dotnet/csharp/extraction/parse-document.md)
- [Extracting text from PDF documents](/guides/dotnet/csharp/extraction/pdf-to-text.md)
- [Reading barcodes with vision extraction](/guides/dotnet/csharp/extraction/read-barcodes-with-vision.md)
- [Extracting text from multilingual images](/guides/dotnet/csharp/extraction/read-text-from-image-multi-language.md)
- [Extracting text from images](/guides/dotnet/csharp/extraction/read-text-from-image.md)
- [Searching document text](/guides/dotnet/csharp/extraction/search-document-text.md)
- [Speeding up first ICR operation by predownloading models](/guides/dotnet/csharp/extraction/speed-up-first-icr-by-downloading-requirements.md)

