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

# Output Schema Validation

> How ViscribeAI validates parsed image extraction output against your schema in Python and TypeScript.

## Overview

ViscribeAI validates parsed model output before returning `result.data`.

The model is still asked for structured JSON through the provider request, but
the SDK also checks the returned object locally. If the object does not match
the requested schema, ViscribeAI raises `StructuredOutputValidationError`
instead of returning invalid data.

Validation runs after response parsing and before the result wrapper is created.
Malformed JSON is still a parse error, model refusals are still refusal errors,
and incomplete provider responses are still finish-reason errors.

ViscribeAI also checks strict schemas before sending the request. If a schema is
outside the OpenAI Structured Outputs subset, ViscribeAI raises
`StructuredOutputSchemaError` with the schema path and a suggested fix.

## Effective schema

ViscribeAI validates against the same effective schema it uses for structured
output requests.

* Simple fields are converted into an object JSON Schema.
* JSON Schema inputs are validated as JSON Schema.
* Python Pydantic model schemas are validated with Pydantic.
* TypeScript Zod schemas are converted to JSON Schema for the model request
  and validated with Zod after parsing.
* Strict mode is enabled by default.

Simple field definitions are intentionally strict: every field is required,
values may be `null`, array fields are capped at five items, and additional
properties are rejected.

When you pass raw JSON Schema with strict mode enabled, ViscribeAI tightens
object schemas by marking object properties as required and rejecting additional
properties when the schema does not already specify that behavior. With
`strict=False` in Python or `strict: false` in TypeScript, ViscribeAI validates
against the JSON Schema you provided without that extra tightening.

For TypeScript Zod schemas, strict mode follows the provider structured-output
rule that object fields must be present. Use nullable fields such as
`z.string().nullish()` when a value may be absent or empty.

## Provider compatibility

With strict mode enabled, ViscribeAI accepts the OpenAI Structured Outputs
subset:

* root schemas must be objects
* nested unions must use `anyOf`; root-level unions are rejected
* every object property must be required
* every object must use `additionalProperties: false`
* arrays must define an `items` schema
* unsupported composition such as `allOf`, `oneOf`, `not`, and conditional
  schemas is rejected
* tuple arrays, pattern-based object keys, and uniqueness/member constraints are
  left to application validation
* documented schema size limits are checked before the request is sent

Set `strict=False` in Python or `strict: false` in TypeScript only when you need
to bypass this provider-compatibility check for a custom backend.

## Python

Python supports Pydantic models, simple fields, and JSON Schema dictionaries.

<Tabs>
  <Tab title="Pydantic">
    Pydantic schemas are validated with `model_validate`. A successful result
    returns a Pydantic model instance.

    ```python theme={null}
    from pydantic import BaseModel, Field
    from viscribe import StructuredOutputSchemaError, StructuredOutputValidationError
    from viscribe.images import extract


    class Receipt(BaseModel):
        merchant_name: str | None = Field(description="Store or business name")
        total_amount: float | None = Field(description="Final receipt total")


    try:
        result = extract(
            image_path="examples/receipt.png",
            output_schema=Receipt,
            instruction="Extract the visible receipt fields.",
        )
        print(result.data.model_dump())
    except StructuredOutputSchemaError as error:
        print(f"Unsupported schema: {error}")
    except StructuredOutputValidationError as error:
        print(f"Invalid extracted data: {error}")
    ```
  </Tab>

  <Tab title="JSON Schema">
    Simple fields and JSON Schema dictionaries are validated with JSON Schema.
    A successful result returns a dictionary.

    ```python theme={null}
    from viscribe import StructuredOutputSchemaError, StructuredOutputValidationError
    from viscribe.images import extract


    try:
        result = extract(
            image_path="examples/receipt.png",
            output_schema=[
                {"name": "merchant_name", "type": "text"},
                {"name": "total_amount", "type": "number"},
            ],
            instruction="Extract the visible receipt fields.",
        )
        print(result.data)
    except StructuredOutputSchemaError as error:
        print(f"Unsupported schema: {error}")
    except StructuredOutputValidationError as error:
        print(f"Invalid extracted data: {error}")
    ```
  </Tab>
</Tabs>

## TypeScript

TypeScript supports simple fields, JSON Schema objects, and Zod schemas.
Simple fields and JSON Schema are validated with AJV. Zod schemas are validated
with Zod, and a successful result returns Zod-parsed data.

<Tabs>
  <Tab title="Zod">
    ```ts theme={null}
    import { z } from "zod/v4";
    import { images, StructuredOutputSchemaError, StructuredOutputValidationError } from "viscribe";

    const Receipt = z.object({
      merchant_name: z.string().nullish(),
      total_amount: z.number().nullish(),
    });

    try {
      const result = await images.extract({
        imagePath: "examples/receipt.png",
        outputSchema: Receipt,
        instruction: "Extract the visible receipt fields.",
      });

      console.log(result.data.merchant_name);
    } catch (error) {
      if (error instanceof StructuredOutputSchemaError) {
        console.error("Unsupported schema:", error.message);
      }
      if (error instanceof StructuredOutputValidationError) {
        console.error("Invalid extracted data:", error.message);
      }
      throw error;
    }
    ```
  </Tab>

  <Tab title="Simple fields">
    ```ts theme={null}
    import { images, StructuredOutputSchemaError, StructuredOutputValidationError, type ExtractField } from "viscribe";

    const fields: ExtractField[] = [
      { name: "merchant_name", type: "text" },
      { name: "total_amount", type: "number" },
    ];

    try {
      const result = await images.extract({
        imagePath: "examples/receipt.png",
        outputSchema: fields,
        instruction: "Extract the visible receipt fields.",
      });

      console.log(result.data);
    } catch (error) {
      if (error instanceof StructuredOutputSchemaError) {
        console.error("Unsupported schema:", error.message);
      }
      if (error instanceof StructuredOutputValidationError) {
        console.error("Invalid extracted data:", error.message);
      }
      throw error;
    }
    ```
  </Tab>
</Tabs>

## What validation catches

Validation catches schema mismatches such as:

* missing required fields
* values with the wrong type
* array values that exceed simple field limits
* extra object properties when strict mode rejects them
* invalid data returned through SDK-compatible custom clients

Provider-compatibility checks catch schema issues such as:

* root Zod unions or discriminated unions
* raw JSON Schema with `additionalProperties: true`
* unsupported composition such as `allOf` or `oneOf`
* array schemas without `items`

<Note>
  Validation confirms that the output shape matches the schema. It cannot prove that every
  extracted value is factually correct, so high-stakes workflows should still include
  review, confidence fields, or downstream checks.
</Note>
