Invoice PDFs to Accounting Entries: 6 Fields, 1 Approve

Abstract tech illustration: Invoice PDFs to Accounting Entries: 6 Fields, 1 Approve

Take an illustrative scenario: a small business with 10-15 suppliers gets around 200 invoices a month. If each one takes roughly four minutes (open the PDF, find the supplier, date, tax ID, net, tax, total, type it all in), that's about 13 hours a month of pure typing. Typing is also where the errors live: a transposed digit in a tax number, a total keyed against the wrong supplier, discovered at audit time. Here's how a pipeline can remove the typing and keep a human in charge of what hits the books.

What the pipeline looks like: five stages, no magic

The pipeline has five stages: input, extraction, validation, approval, output. A watcher picks up new files, an extractor turns them into structured JSON, deterministic code checks the JSON, a human approves, and an importer writes the approved record to your accounting system. Only the extractor uses an LLM. The rest is boring code, on purpose.

Documents arrive two ways: forwarded to a dedicated mailbox, or dropped into a shared folder. A script polls both every few minutes and pushes anything new (PDF or Excel) into a queue. That's the whole input layer.

mailbox / shared folder
        │
   watcher (poll every few min)
        │
      queue ──► extract ──► validate ──► approve ──► import
                  (LLM)      (code)      (human)     (API/CSV)

You can build this in plain Python, or on n8n if you prefer a visual runner. n8n's Community Edition is free to self-host under its Sustainable Use License, which is fair-code, not OSI-approved open source, and you pay only for the server (source). That license has restrictions on commercial hosting, so if you plan to run this for clients, read the license text first. A modest self-hosted box or a small VPS is enough to run it.

Extraction: Excel is mostly deterministic, PDFs need a strict prompt

For Excel, you map columns to fields in code, and use an LLM only to read the header row when a supplier's layout differs. For PDFs, use the text layer if one exists, run OCR if it's a scan, then have a language model return JSON with exactly your fields and null for anything missing. The "never guess" instruction matters more than which model you pick.

Excel first. Don't try to feed .xlsx files straight to an LLM document input. Claude's document blocks don't accept Excel; binary formats like .xlsx must be converted to text or PDF first, while .txt, .csv and .md work directly (Claude docs). So the flow is: read the sheet with a library, and when the layout is unfamiliar, send only the header row (as CSV text) to the model and ask which column is which.

import pandas as pd, json

df = pd.read_excel(path, header=None, nrows=3)
header_csv = df.to_csv(index=False, header=False)

mapping = llm_json(
    system="Map spreadsheet columns to invoice fields. Return JSON "
           "{field: column_index}. Use null if a field has no column. Never guess.",
    user=header_csv,
)
# From here on it's plain pandas: no LLM touches the amounts.

The model never sees or retypes the numbers. It only labels columns, so it can't corrupt a figure.

Then PDFs. Try the text layer first. If the file has real text, use it. If it's a scan, OCR it, or send the PDF to a vision-capable model directly. Either way, the instruction is the same:

Return JSON with exactly these keys:
supplier_name, tax_id, invoice_number, issue_date,
net_amount, tax_amount, total.
If a field is not present in the document, return null.
Never guess or infer a missing value.

Two practical limits to know if you go the direct-PDF route with Claude: requests are capped at 32 MB and 600 pages (dropping to 100 pages when the context window is under 1M tokens), and password-protected or encrypted PDFs aren't supported (source). For single invoices you'll never hit the page cap, but encrypted PDFs from suppliers do show up, so handle that error path. Gemini's equivalent limit is 50 MB or 1,000 pages (Google docs).

One caveat that matters later: Claude reads PDFs through its vision capabilities, so low-quality, rotated, or very small scans are a real failure risk (source). Plan for that. Don't hope it won't happen.

Validation: the stage most tutorials skip

Extraction output is never trusted on its own. Deterministic code checks that net plus tax equals total to the cent, that the date is real and not in the future, that the tax ID matches your country's format, and that this invoice number from this supplier doesn't already exist. Any failed check flags the document and blocks it from reaching the books automatically.

Here's the shape of it:

from datetime import date
from decimal import Decimal

def validate(inv, seen, tax_id_re):
    problems = []
    if None in (inv["net_amount"], inv["tax_amount"], inv["total"]):
        problems.append("missing amount")
    else:
        net, tax, tot = (Decimal(str(inv[k])) for k in ("net_amount", "tax_amount", "total"))
        if net + tax != tot:
            problems.append(f"total mismatch: {net}+{tax} != {tot}")

    try:
        d = date.fromisoformat(inv["issue_date"])
        if d > date.today():
            problems.append("date in future")
    except (TypeError, ValueError):
        problems.append("invalid date")

    if not inv["tax_id"] or not tax_id_re.fullmatch(inv["tax_id"]):
        problems.append("tax ID format")

    if (inv["supplier_name"], inv["invoice_number"]) in seen:
        problems.append("possible duplicate")

    return problems  # empty list = green, otherwise amber

Use Decimal, not floats, or your "to the cent" check will fail on perfectly good invoices.

The tax-ID rule is the one that has to come from you. Generic tools assume a tax ID shape, and yours may be different. Write the regex from your actual suppliers' documents, not from a demo. If you're unsure of the correct format for your jurisdiction, check with your accountant or the tax authority's official site.

An illustrative failure this catches. Say a supplier sends a scan photographed at an angle, slightly blurry, with a stamp over the total. OCR reads part of the stamp as digits. The extracted total doesn't equal net plus tax, validation catches it, and the document goes amber with the note "total mismatch." You open it, see the stamp, type the correct figure, approve. Thirty seconds. Without that one rule, the wrong number would go straight into the books.

Approval: why a one-click black box is a liability

Every extracted invoice appears in a simple review screen or chat message, with the original document next to the extracted fields. Green means every validation passed, amber means something was off. One click approves a green one; amber ones get opened and fixed. This step is what makes the system trustworthy.

My position here is blunt: a pipeline that writes straight into your books with no review is a liability. One silently wrong voucher costs more than all the hours you saved that week. So the design goal isn't "zero human touches," it's "one human touch on the invoices that are fine, and real attention on the ones that aren't."

What the review view needs, nothing more:

  • The original PDF or scan, rendered next to the fields
  • Six fields plus supplier: name, tax ID, invoice number, date, net, tax, total
  • The validation notes in plain language ("total mismatch: 100.00 + 20.00 != 130.00")
  • Approve and Edit buttons

A Telegram message with an inline "Approve" button works fine for a one-person shop. A small web page works for a team. Either way, green items are one tap, and amber items open for correction.

Output: write the record, attach the evidence

Approved records are written to the accounting system through its import format or API, with the original PDF attached so the audit trail is one click away. Which path you use depends on what your accounting tool exposes: most support a CSV/Excel import at minimum, and many have an API.

def push(inv, pdf_path):
    entry_id = accounting.create_entry(
        supplier=inv["supplier_name"],
        tax_id=inv["tax_id"],
        number=inv["invoice_number"],
        date=inv["issue_date"],
        net=inv["net_amount"], tax=inv["tax_amount"], total=inv["total"],
    )
    accounting.attach(entry_id, pdf_path)
    seen.add((inv["supplier_name"], inv["invoice_number"]))  # feeds duplicate check

Note the last line: the output stage feeds the duplicate check in the validation stage. If the import fails halfway, make the whole operation idempotent so a retry doesn't create a second entry.

What it costs to run, and where it still breaks

Extraction cost per document is small and depends on the model you pick. One estimate for Gemini 3.1 Flash-Lite is about $0.004 per document; pricier models cost more, and batch APIs can cut the price further. The bigger question is accuracy on your worst documents, so measure that before you trust any number, including mine.

Cost. Prices change often, and the aggregators I checked disagree on model lineups, so treat these as a snapshot and confirm on the vendor's pricing page before you commit.

Option Input / output per 1M tokens Notes
Claude Sonnet 5 $2 / $10 Third-party tracker, Oct 2026
Claude Haiku 4.5 $1 / $5 Third-party tracker; check Anthropic's deprecations page, one aggregator suggests retirement around now
Gemini 3.1 Flash-Lite $0.25 / $1.50 Cheapest current Gemini per a Sep 2026 tracker
GPT-5 mini $0.25 / $2 OpenAI launch pricing; model may be marked deprecated, verify

Sources: Opslyft, Puter, OpenAI.

For scale: one third-party estimate puts a document-extraction pipeline on Gemini 3.1 Flash-Lite at about $0.004 per document, or $8.50 a month for 2,000 documents, assuming roughly 8,000 input and 1,500 output tokens per document (source). Invoices aren't urgent, so also consider Claude's Batch API: requests complete asynchronously within 24 hours at a flat 50% discount on input and output tokens (source). Your own number depends on page count and prompt length, so pull it from your logs after a week, not from a blog.

For comparison, APQC's cross-industry median cost to process one accounts payable invoice is $6.00 across 5,846 organizations, covering personnel, systems, overhead and outsourced costs (APQC). Ardent Partners' sponsored research puts the average at $9.84 in 2025 and $9.90 in 2026, with best-in-class teams at $2.67 (summary). Those definitions differ, so don't mix them. The point is that API cost per document is small next to the labor and overhead figures; the real spend is your review time on amber items.

Where it breaks. The typical problems are:

  • Blurry, angled, or stamped scans: caught by validation, fixed by hand
  • Unusual layouts where the invoice number sits somewhere unexpected
  • Multi-page invoices with line items spilling onto page two
  • Documents mixing Cyrillic and Latin on one page: OCR and models handle this unevenly, so test it explicitly if your suppliers do this

I haven't published a first-pass accuracy percentage here, because that number is only meaningful on your documents. Run the batch yourself and read your own logs: invoices processed, percent that went green, number needing a manual fix, cost per document.

Versus the AI entry built into accounting software. Vendor features are useful if you live entirely inside one product and your documents are clean. But it's a closed box: you can't see why a field was read wrong, add your own validation rules, or reuse the extraction elsewhere. The test is cheap. Run fifty of your worst real documents through any auto-entry tool, count the errors, and decide from that. If the error rate is acceptable and you're staying in that ecosystem, use it. If not, build the pipeline above.

Where bizflowai.io fits

At bizflowai.io I build AI automations for small teams, and document-to-ledger workflows like this one are the kind of project I take on. If you'd rather not build it yourself, that's the conversation to have: what your documents look like, which accounting tool you use, and which validation rules your jurisdiction requires. Your accountant can confirm the tax-ID formats and bookkeeping rules that apply to you.


Want more like this?

I publish practical AI automation, GenAI engineering, and faceless content workflows on YouTube every week.

Subscribe to bizflowai.io on YouTube — never miss a new tutorial.

Planning an AI automation project or need a second opinion on your architecture?

Connect with me on LinkedIn — Lazar Milicevic, GenAI Engineer & bizflowai.io Founder.

Visit bizflowai.io for our services, case studies, and AI consulting.

Frequently asked questions

What is an automated invoice processing pipeline?

An automated invoice processing pipeline is a five-stage system that moves invoices from arrival to the accounting record: input, extraction, validation, approval, and output. Documents arrive by email or shared folder, a language model extracts fields such as supplier, tax ID, dates, and amounts, code validates the results, a human approves them, and approved records are written to the accounting system with the original PDF attached.

How do I extract data from PDF and scanned invoices with an LLM?

Run PDFs through a text parser first and use the text layer if the file contains real text. If it is a scan, run OCR instead. Then send the text to a language model with a strict instruction: return JSON with exactly the required fields (supplier name, tax ID, invoice number, issue date, net amount, tax amount, total), return null for any missing field, and never guess.

Why does validation matter for automated invoice extraction?

Extraction output should never be trusted on its own. Validation code checks that net plus tax equals the total to the cent, that the date is real and not in the future, that the tax ID matches your country's format, and that the invoice number is not a duplicate. If any check fails, the document is flagged and never reaches the accounting record automatically, which catches errors like OCR misreading a stamp as part of a number.

Why should invoice automation include a human approval step?

A one-click black box that writes straight into your books is a liability, because one silently wrong voucher can cost more than the hours saved that week. A review screen shows the original document beside the extracted fields. Green means every validation passed and takes one click to approve; amber means something was off and needs a manual fix. This step is what makes the system trustworthy.

How much time does manual invoice entry take for a small business?

A small business with ten to fifteen suppliers receives roughly 200 invoices a month. At about four minutes each to open the PDF, find the supplier, date, tax number, net amount, tax, and total, and type them into the accounting system, that comes to about thirteen hours of typing monthly. Manual entry also carries error risk, such as a transposed tax ID digit or a total keyed to the wrong supplier.