Skip to content

Blog

Schema-first extraction: why we don't ship 'invoice models'

Most document-extraction tools ship pre-built models per document type. We took the opposite approach. Here's why.

The Beaqua team 7 min read schemas architecture document-intelligence

Most document-extraction tools start with a simple question: “what type of document is this?” They run a classifier, pick a pre-built model — invoice model, contract model, KYC model — and the user watches from a dropdown. “Select document type: [Invoice / Contract / Expense Report].”

This approach is intuitive. It feels clean. But it breaks in production, regularly and predictably.

Why document-type classifiers break in production

Real business documents don’t fit neat categories. An invoice often includes payment terms (contract content). A contract includes line items (invoice content). A purchase order might double as a delivery note. A KYC form might have embedded contract language.

A classifier forces a choice. It says: this is an invoice, run the invoice model. It ignores everything that looks like a contract. It misses the renewal clause buried in the terms section. It extracts the line items and total, but skips the data residency requirement you actually need for compliance.

Worse, the classifier itself can be wrong. A vendor sends an “invoice” that’s actually a statement of account. Or a contract preamble that starts with an order number. The classifier gets it wrong, runs the wrong model, and you don’t find out until human review (or until the extracted data goes into your systems and causes problems).

This forces a false choice on customers:

  • Build custom models for every variant your documents take (expensive, vendor lock-in, slow to update).
  • Accept wrong extractions and drown in manual review.
  • Cobble together multiple tools and hope they don’t conflict.

Schema-first: define what you want, not what the document is

Beaqua takes the opposite approach. Forget document types. Define the fields you actually care about.

You don’t want an “invoice model.” You want: vendor_name, invoice_number, total_amount, due_date, payment_terms, line_items. If a document contains those fields — whether it’s a typed invoice, a faxed statement, or a handwritten order — Beaqua extracts them.

This shift is subtle but fundamental. The system stops asking “what is this?” and starts asking “what’s in here that matters to me?” The document type becomes irrelevant. The schema is the only source of truth.

What this looks like in practice

An insurance company sends Beaqua claims documents arriving in 15 different layouts. Some are typed reports from their standard form. Some are handwritten statements taken in the field. Some are photos of police reports or accident sketches. Different formats. Same information.

Traditional extraction: you pick 15 models, or you build custom rules, or you accept wrong extractions.

Schema-first: you define a schema with the 22 fields you extract from claims — claimant name, incident date, loss type, amount claimed, insured coverage details, exclusions mentioned, policy number, claim date, status, etc. You send 5,000 documents of all 15 types to Beaqua. It extracts those 22 fields from each one, regardless of format.

You don’t care that document 47 is a handwritten statement and document 48 is a typed form. Beaqua extracted the same 22 fields from both. You feed the results into your claims workflow. Done.

The trade-offs you get with schema-first

This approach is slower to onboard. You can’t just pick “invoice” from a dropdown. You have to define your schema: what fields do you need, what type is each one (string, currency, date, list), what thresholds do you set for confidence-based routing.

But the trade-offs are worth it:

  • No document-type misclassification. A document that spans types gets all relevant fields, not just the ones matching the wrong classifier decision.
  • No waiting for Beaqua to ship a new model for a new document variant you start receiving.
  • No surprise fields. If your contract model extracts renewal clauses but your claims model doesn’t, you notice immediately because you’re defining the schema, not trusting a vendor’s judgment about what’s in an “invoice.”
  • Easier updates. Change your schema, re-run your backlog, done. No need to wait for a new model release.

How to design a good schema

If you’re building a schema for the first time, here’s what works:

  • Name fields by business intent, not document field name. Use invoice_total not amount_due. Use claimant_full_name not names of persons involved. The schema describes your needs, not the document’s structure.
  • Set types correctly. A date should be type: date (ISO 8601), not string. A currency should be type: currency with a code (GBP, EUR). A party name should be type: party_name. Specific types let Beaqua understand what validation makes sense.
  • Set confidence thresholds per field. A vendor name can auto-accept at 90% confidence. An amount claimed should probably go to review at less than 95%. A date can be more permissive. This is based on downstream risk, not a global setting.
  • Include optional fields for things that sometimes appear. A renewal_clause field might appear in 60% of your contracts. Make it optional, set its threshold lower (70-80%), and let your workflow handle “extracted but not present” gracefully.
  • Revise the schema as you see real documents. Your first schema is a guess. Run it on 100 real documents. You’ll see fields you missed, fields you don’t actually need, fields that need type refinement. Update. Repeat.

Next steps

If you’re evaluating extraction tools and they’re pushing pre-built models (“pick your document type”), ask what happens when your documents don’t fit neatly. Ask about schema-first extraction. Ask how they handle documents that span categories.

See how to define and refine schemas in the Beaqua product documentation.

Written by the Beaqua team. Want to discuss this post? Email contact@m31g.com.

Try it on your documents

See Beaqua extract from your messiest PDF in under a minute.

Upload one document. We extract the fields. You decide if it goes further.