How to write a taxonomy for invoice extraction
Published , 6 min read
Short answer
A taxonomy is a list of fields, each with an id, a name, a one-sentence description and a type. Pick the narrowest type that fits, describe the field the way the document would label it, and add hints for the words that usually sit next to the value. Twelve well-described fields are enough for most invoices.

What is a taxonomy in document extraction?
It is the schema for what you want back. In jextract a taxonomy has a name and a list of fields, and every field has four required parts: an id, a name, a description and a type. Fields can also carry options (for enums), hints and a required flag.
Which field types are there?
The type decides how candidates are cut out of the page and how the chosen span is normalised. A narrower type means fewer, cleaner candidates.
| Type | Use it for | Example on the page |
|---|---|---|
id | Reference numbers and codes | NW-2026-0912 |
date | Any calendar date; returned as ISO | September 12, 2026 |
money | Amounts with a currency | $4,149.39 |
number | Plain quantities | 4 |
percent | Rates | 19% |
email | Email addresses | billing@northwind.example |
phone | Phone numbers | +1 (206) 555-0142 |
enum | One of a fixed set you define | USD |
boolean | A yes or no judged from the text | Auto-renews |
string | Names and other free text | Northwind Traders Ltd. |
How should I write the description?
The description is the question the model answers, so write it as one plain sentence that separates this field from its neighbours. An invoice has several dates and several amounts; the description is how the right one gets chosen.
- Say whose it is. "The company issuing the invoice (the seller)" and "The company or person being billed (the buyer)" keep supplier and customer apart.
- Say which one. "The final amount payable including tax" is a different field from "The sum of line items before tax and discounts".
- Say when it can be missing. "The buyer's purchase order reference, if any" tells the model that "none" is a fair answer.
What are hints for?
Hints are the words that usually label the value in real documents. "Invoice number" is printed as "Invoice no", "Invoice #" or "Receipt number" depending on the supplier. Listing those helps the field find its line when the document uses different wording from your field name.
What does a working invoice taxonomy look like?
This is a shortened version of the built-in invoice preset. Send it as the taxonomy form field, or pass taxonomy=invoice to use the full twelve-field preset.
{
"name": "Invoice",
"fields": [
{ "id": "invoice_number", "name": "Invoice number", "type": "id",
"description": "The supplier's unique identifier for this invoice",
"hints": ["invoice no", "invoice #", "receipt number"] },
{ "id": "invoice_date", "name": "Invoice date", "type": "date",
"description": "The date the invoice was issued",
"hints": ["date", "issued"] },
{ "id": "supplier_name", "name": "Supplier name", "type": "string",
"description": "The company issuing the invoice (the seller)",
"hints": ["from", "vendor", "seller"] },
{ "id": "total", "name": "Total due", "type": "money",
"description": "The final amount payable including tax",
"hints": ["total", "amount due", "balance due"] },
{ "id": "currency", "name": "Currency", "type": "enum",
"options": ["USD", "EUR", "GBP", "INR", "SGD", "other"],
"description": "The currency the invoice is denominated in" }
]
}What are the common mistakes?
- Using
stringfor everything. A total typed asmoneyis chosen from the amounts on the page; typed asstringit competes with every phrase in the chunk. - Two fields with near-identical descriptions. If you cannot say how they differ in a sentence, the model cannot either.
- Expecting a table. Line items are rows, and this method returns one span per field. Ask for the totals, not the rows.
- Leaving out "other" in an enum. Without it the model has to force a document into one of your options.
How do I check that a taxonomy is working?
Run it on a few real documents in the app and look at the candidates for any field that comes back wrong or with low confidence. If the right value is not among the candidates, the type or the hints need to change. If it is there but lost, the description is not separating it from the others.
Questions
How many fields can a taxonomy have?
There is no fixed small limit; the presets have twelve to fourteen. Both model requests ask about every field in parallel, so the request count stays at two (three with the refine round) whether the taxonomy has 5 fields or 40.
Do I have to start from scratch?
No. jextract ships presets for invoices, contracts, résumés and purchase orders. Each opens with a sample document, and you can edit the fields or send your own taxonomy as JSON.
Can a taxonomy extract invoice line items?
Not as rows. The method returns one span per field, so tables that should come back as arrays are a known limitation. Totals, tax and subtotal work well because each is a single amount on the page.