Klaaro logoKlaaro
  • Developers
  • Pricing
  • Team
EN|DE
Log inSign up

AI schema generation

Generate a fitting schema from documents automatically

After classification, Klaaro proposes the fields that document type needs, using the file you just sent. You do not configure the schema before the first document: it is a zero-shot configuration. Edit and fine-tune the schema after extraction, if needed.

Sarah Stemmler
Talk to our founder

Sarah Stemmler · Founder & CEO

Try for free

100 pages · no credit card

From quotation to data schema

Document AI that reads the first file of a document type and drafts relevant fields for extraction accordingly.

  1. Start from the class

    The document class defined in the previous step decides which schema is most relevant. A new class gets a new data schema.

  2. Based on the document's fields

    Klaaro proposes fields from the information actually present: totals, dates, parties, line items.

  3. Ready for the data extraction

    Keep the schema and export it as JSON, Zod, a Pydantic model, or SQL. The data is extracted according to this schema.

    Next: Data extraction
Northlight_QT-2024-1185.pdfpdfQuotation
N
SupplierNorthlight Solar Ltd48 Harbour RoadEdinburgh EH6 6QQ, UK

QUOTATION

No. Quote no.QT-2024-1185

Issued 18 Sep 2024

Valid until Valid until18 Oct 2024

Prepared for

Acme Industries Ltd.

42 Commerce Way, London EC2A 4NE, UK

Line items
DescriptionQtyUnitAmount
Solar panel module 450W24£185.00£4,440.00
Hybrid inverter 10kW2£1,950.00£3,900.00
Mounting & installation1£2,100.00£2,100.00
Subtotal£10,440.00
Total£10,440.00

Prices exclude VAT · Payment terms: Net 14 days · Bank: Barclays Bank PLC

Schema· QuotationWaiting for classDrafting…4 fieldsKept · v1
  • supplier_address
  • quotation_number
  • due_date
  • line_items
  • description
  • quantity
  • unit_price
  • amount
[
  { "name": "supplier_address",
    "type": "address" },
  { "name": "quotation_number",
    "type": "string" },
  { "name": "due_date", "type": "date" },
  { "name": "line_items",
    "type": "array",
    "arrayItemType": "object",
    "arrayItemFields": [
      { "name": "description",
        "type": "string" },
      { "name": "quantity",
        "type": "number" },
      { "name": "unit_price",
        "type": "currency" },
      { "name": "amount",
        "type": "currency" }
    ] }
]
import { z } from "zod"

export const extractionSchema = z.object({
  supplier_address: z.object({
    street: z.string().nullable(),
    city: z.string().nullable(),
    // house_number, postal_code, …
  }).nullable().describe("Postal address"),
  quotation_number: z.string().nullable(),
  due_date: z.string().nullable(),
  line_items: z.array(z.object({
    description: z.string().nullable(),
    quantity: z.number().nullable(),
    unit_price: z.object({
      amount: z.number().nullable(),
      currency: z.enum([…]).nullable()
    }).nullable(),
    // amount: same shape as unit_price
  })).nullable()
})
# Every field defaults to None
class SupplierAddress(BaseModel):
    street: str | None
    city: str | None
    # house_number, postal_code, …

class LineItemsItem(BaseModel):
    description: str | None
    quantity: float | None
    unit_price: UnitPrice | None
    amount: Amount | None

class UnitPrice(BaseModel):
    amount: float | None
    currency: str | None

class Quotation(BaseModel):
    supplier_address: SupplierAddress | None
    quotation_number: str | None
    due_date: str | None
    line_items: list[LineItemsItem] | None
CREATE TABLE IF NOT EXISTS "Quotation" (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  document_id uuid,
  "supplier_address" jsonb,
  "quotation_number" text,
  "due_date" date,
  "line_items" jsonb,
  created_at timestamptz NOT NULL DEFAULT now()
);
  1. Start from the class

    The document class defined in the previous step decides which schema is most relevant. A new class gets a new data schema.

    Northlight_QT-2024-1185.pdfpdfQuotation
    N
    SupplierNorthlight Solar Ltd48 Harbour RoadEdinburgh EH6 6QQ, UK

    QUOTATION

    No. Quote no.QT-2024-1185

    Issued 18 Sep 2024

    Valid until Valid until18 Oct 2024

    Prepared for

    Acme Industries Ltd.

    42 Commerce Way, London EC2A 4NE, UK

    Line items
    DescriptionQtyUnitAmount
    Solar panel module 450W24£185.00£4,440.00
    Hybrid inverter 10kW2£1,950.00£3,900.00
    Mounting & installation1£2,100.00£2,100.00
    Subtotal£10,440.00
    Total£10,440.00

    Prices exclude VAT · Payment terms: Net 14 days · Bank: Barclays Bank PLC

  2. Based on the document's fields

    Klaaro proposes fields from the information actually present: totals, dates, parties, line items.

    Northlight_QT-2024-1185.pdfpdfQuotation
    N
    SupplierNorthlight Solar Ltd48 Harbour RoadEdinburgh EH6 6QQ, UK

    QUOTATION

    No. Quote no.QT-2024-1185

    Issued 18 Sep 2024

    Valid until Valid until18 Oct 2024

    Prepared for

    Acme Industries Ltd.

    42 Commerce Way, London EC2A 4NE, UK

    Line items
    DescriptionQtyUnitAmount
    Solar panel module 450W24£185.00£4,440.00
    Hybrid inverter 10kW2£1,950.00£3,900.00
    Mounting & installation1£2,100.00£2,100.00
    Subtotal£10,440.00
    Total£10,440.00

    Prices exclude VAT · Payment terms: Net 14 days · Bank: Barclays Bank PLC

  3. Ready for the data extraction

    Keep the schema and export it as JSON, Zod, a Pydantic model, or SQL. The data is extracted according to this schema.

    Schema· QuotationWaiting for classDrafting…4 fieldsKept · v1
    • supplier_address
    • quotation_number
    • due_date
    • line_items
    • description
    • quantity
    • unit_price
    • amount
    [
      { "name": "supplier_address",
        "type": "address" },
      { "name": "quotation_number",
        "type": "string" },
      { "name": "due_date", "type": "date" },
      { "name": "line_items",
        "type": "array",
        "arrayItemType": "object",
        "arrayItemFields": [
          { "name": "description",
            "type": "string" },
          { "name": "quantity",
            "type": "number" },
          { "name": "unit_price",
            "type": "currency" },
          { "name": "amount",
            "type": "currency" }
        ] }
    ]
    import { z } from "zod"
    
    export const extractionSchema = z.object({
      supplier_address: z.object({
        street: z.string().nullable(),
        city: z.string().nullable(),
        // house_number, postal_code, …
      }).nullable().describe("Postal address"),
      quotation_number: z.string().nullable(),
      due_date: z.string().nullable(),
      line_items: z.array(z.object({
        description: z.string().nullable(),
        quantity: z.number().nullable(),
        unit_price: z.object({
          amount: z.number().nullable(),
          currency: z.enum([…]).nullable()
        }).nullable(),
        // amount: same shape as unit_price
      })).nullable()
    })
    # Every field defaults to None
    class SupplierAddress(BaseModel):
        street: str | None
        city: str | None
        # house_number, postal_code, …
    
    class LineItemsItem(BaseModel):
        description: str | None
        quantity: float | None
        unit_price: UnitPrice | None
        amount: Amount | None
    
    class UnitPrice(BaseModel):
        amount: float | None
        currency: str | None
    
    class Quotation(BaseModel):
        supplier_address: SupplierAddress | None
        quotation_number: str | None
        due_date: str | None
        line_items: list[LineItemsItem] | None
    CREATE TABLE IF NOT EXISTS "Quotation" (
      id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
      document_id uuid,
      "supplier_address" jsonb,
      "quotation_number" text,
      "due_date" date,
      "line_items" jsonb,
      created_at timestamptz NOT NULL DEFAULT now()
    );
    Next: Data extraction

The AI features around your schema

Zero-shot from one file

The first document of a class is enough for a draft. You do not label a training set first.

Nested fields stay nested

Line items, parties, and addresses are understood as objects and arrays, not a flat row of columns. Complexity is not taken away when transforming your documents into datasets.

Yours to edit

Change fields by hand or with the integrated AI agent. Version the schema and override it per class.

Export the schema

Hand the schema to another system as JSON, Zod, Pydantic, or SQL.

  • JSON
  • Zod
  • Pydantic
  • SQL

Continue the product tour

Product capabilities

  • OCR with AITurn scans and photos into text
  • Document parsingIngest files and keep their structure
  • Document classificationRecognize every document type
  • Data extractionThe right values in the right fields
  • IntegrationsAPI, SDKs, MCP, and n8n

Quality & validation

  • Validation rulesRules that refuse a bad value
  • ApprovalsPeople decide the exceptions
  • EvaluationTest a schema edit before it goes live
See the full product overview

…Or let's talk personally!

Tell me which documents slow you down by booking your 20-minute slot in my calendar. Together, we can find out if Klaaro is the right tool for you.

Sarah Stemmler

Sarah Stemmler

Founder & CEO

Book your slotTry for free

Schema generation, answered

Klaaro logoKlaaro

© 2026 Klaaro by synsugar GmbH.
All rights reserved.

Product

  • Product
  • Pricing

Resources

  • Docs
  • For AI agents
  • Comparisons
  • n8n Integration
  • Customers

Solutions

  • Energy
  • Construction
  • Logistics
  • Bill of Quantities

Company

  • Team
  • Contact

Community

  • Discord
  • Reddit
  • YouTube
  • Instagram

Legal

  • Privacy Policy
  • Terms of Service
  • Refund Policy
  • Legal Notice
Hosted in EUGDPR compliantNIS2 ReadyFunded by MicrosoftPart of Daytona Startup Gridn8n integration partner