Extracting data from documents with AI

How a model turns invoices, contracts and forms into fields: the path from a letter to a record, eight kinds of documents with checks, a schema and a check by code, rules and mistakes.

Artificial intelligence Updated

In short

AI extraction turns documents of any form — invoices, contracts, acts, applications, CVs — into fields of a table without manual typing. A language model reads the document, including scans and photos, and returns the data strictly by a schema: number, date, supplier, items, totals. Then code checks what can be checked — the arithmetic, the dates, the format of tax numbers, whether the supplier exists — and documents without problems go straight into the accounting system or CRM, while the rest go to a person with a list of what is wrong. Unlike old template recognition, the model is not afraid of a new layout, so one solution handles documents from hundreds of different suppliers.

How it works: from a letter to a record

  1. The document arrives

    By email, through a form, in a messenger or from a scanner — into one queue.

  2. The model reads it

    A PDF with text, a scan or a photo — modern models read the image directly.

  3. Fields by a schema

    The answer is strictly the fields of the schema, nothing more and nothing in free form.

  4. Code checks

    Arithmetic, dates, check digits, a known supplier, a duplicate of an earlier document.

  5. A record or a person

    No problems — the record goes into the system; problems — a person sees the document and the list.

  6. Learning from corrections

    Every correction by a person becomes an example for the instruction and a case for the test set.

Which documents and what to check

Eight typical kinds of documents with the fields usually taken and the checks that catch most errors.

DocumentFieldsChecks
Invoice number, date, supplier, items, total arithmetic, tax number, duplicate
Act or delivery note items, quantities, signatures match with the order
Contract parties, subject, terms, amount, penalties a lawyer checks risky clauses
Application from a customer contacts, product, quantity, address phone and email format, product in the catalogue
CV experience, skills, contacts dates of employment in order
Receipt or expense report date, amount, seller, category limits by category
Price list of a supplier article numbers, names, prices a sharp change of price
Questionnaire or form on paper all fields of the form required fields are filled

An invoice: a schema and a check

The schema tells the model what to return; the check tells the system whether to believe it.

The schema of an invoice

All fields are required: if the model cannot find a field, the document goes to a person instead of an empty value going into accounting.

invoice.schema.json
{
  "type": "object",
  "properties": {
    "number":   { "type": "string" },
    "date":     { "type": "string", "description": "YYYY-MM-DD" },
    "supplier": { "type": "string" },
    "tax_id":   { "type": "string" },
    "total":    { "type": "number" },
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name":  { "type": "string" },
          "qty":   { "type": "number" },
          "price": { "type": "number" },
          "sum":   { "type": "number" }
        },
        "required": ["name", "qty", "price", "sum"],
        "additionalProperties": false
      }
    }
  },
  "required": ["number", "date", "supplier", "tax_id", "total", "items"],
  "additionalProperties": false
}

The check by code

Arithmetic and format are checked by code, not by the model: three checks catch most reading errors.

check.ts
// The model reads the document; the code does not trust it and checks the arithmetic
type Invoice = {
  number: string;
  date: string;
  supplier: string;
  tax_id: string;
  total: number;
  items: { name: string; qty: number; price: number; sum: number }[];
};

export function problems(inv: Invoice): string[] {
  const out: string[] = [];
  inv.items.forEach((it, i) => {
    if (Math.abs(it.qty * it.price - it.sum) > 0.01) out.push(`line ${i + 1}: quantity × price ≠ sum`);
  });
  const lines = inv.items.reduce((s, it) => s + it.sum, 0);
  if (Math.abs(lines - inv.total) > 0.01) out.push('the lines do not add up to the total');
  if (!/^\d{4}-\d{2}-\d{2}$/.test(inv.date)) out.push('the date is not in YYYY-MM-DD');
  return out; // empty — straight to accounting; otherwise — to a person with the list
}

7 rules of reliable extraction

  1. 01

    A strict schema

    Fields, types and formats are fixed; the model cannot add its own.

  2. 02

    Every number is checked

    Sums, quantities and dates are recalculated by code.

  3. 03

    Comparison with your data

    The supplier from the directory, the order from the system, the price from the contract.

  4. 04

    Exceptions to a person

    With the document and the list of problems side by side.

  5. 05

    The original is kept

    Every record links to the document it was taken from.

  6. 06

    Duplicates are caught

    The same invoice sent twice is not paid twice.

  7. 07

    A test set of real documents

    Including bad scans, handwriting and unusual layouts.

Common mistakes in extraction

  1. Trusting the totals of the model

    The model can read 8 as 3 — without a recalculation the error goes into accounting.

  2. Empty instead of “not found”

    A missing field silently becomes zero or an empty line.

  3. Templates for each supplier

    The old approach breaks on the first new layout; a schema does not depend on layout.

  4. Full automation from day one

    First a person confirms everything, then only the exceptions.

  5. No link to the original

    An error in a record cannot be traced back to the document.

  6. Testing on clean PDFs

    Real documents are crooked scans and photos taken on the go.

Questions about extracting data from documents

Can AI read scans and photos?

Yes, modern models read images directly; very poor scans still go to a person.

How is it different from ordinary OCR?

OCR gives text; the model understands which number is the total and which is the date, on any layout.

How accurate is it?

It is measured on your documents; checks by code make sure errors do not reach accounting unnoticed.

Can the data go straight into accounting?

Yes, through the API of the accounting system or CRM — documents that passed all checks.

What about handwritten documents?

Neat handwriting is read; doubtful fields are marked for a person.

Is it safe to send documents to a model?

Through business access the data are not used for training; for the strictest cases there are local models.

Online form

Documents
without typing

I build extraction of data from your documents with checks by code and exchange with your accounting system or CRM — people only see the exceptions. Tell me about the task — I answer within one working day.

Or write to [email protected]