Invoice Intake at Scale: OCR + LLM Validation With Human Approvals

Last Updated

From inbox chaos to clean postings in four weeks. This playbook shows how an AP team scaled invoice intake with OCR, LLM extraction, strict validator rules, and fast human approvals. You’ll see the before/after metrics, the minimal policy set that made it safe, and the exact schemas and messages used to keep auditors happy. For context on orchestration and safety patterns, see Automation Workflows, AI Agents Explained, Cost Optimization, and AI Data Privacy 101.

Quick Summary

We centralized intake, extracted fields with an LLM into a strict JSON schema, validated against vendors/PO/VAT, and auto-posted only when policy allowed. Everything else flowed to a one-click approval queue.

  • Straight-through processing (STP) rose from 18% → 67% by week 4.
  • Exception aging fell from 3.6 days → 0.9 days with clear owner routing.
  • Posting accuracy hit 99% after approval thanks to deterministic validators.
  • Net monthly value: ~€1.1–1.6k after software costs at 1k invoices/month.



Manager Mode — results, scope, and the rules that made it safe

This section gives leaders a clean picture of impact and the guardrails used. The build details are in the next section.

Before → After (week 0 vs week 4)

Use the table to explain the impact to finance leadership. Numbers are representative for a 1k-invoice pilot and should be replaced with your real data.

MetricWeek 0 (baseline)Week 4 (pilot)What changed
Straight-through rate (STP)18%67%Whitelist + PO tolerance + VAT/IBAN checks
Exception aging (median)3.6 days0.9 daysOwner routing + 24h escalation
Editor time per invoice (approved)12–15 min5–7 minSchema-first review + one-click approvals
Posting accuracy (approved)97%99%Deterministic validators + audit trail

Scope of the pilot

  • Volume: 1,000 invoices/month across email, scans, and vendor portals.
  • Systems: DMS for archive; accounting/ERP for posting; chat/email for approvals.
  • People: AP lead (owner), backup approver, one ops builder.

Auto vs review thresholds

These rules kept risk low while allowing speed. If any right-hand condition triggers, we route to approval.

Auto-post when…Requires approval when…
Vendor on whitelist, PO match within ±2%, total < €1,000, VAT validNew vendor, PO mismatch, total ≥ €1,000, missing VAT, bank change
IBAN equals last approved IBANIBAN changes or fails checksum
No policy flags in validatorsAny blocked term or failed totals check

Targets to watch weekly

  • STP: 60–80% by week 4, then nudge up by vendor onboarding.
  • Exception aging: < 1 business day.
  • Posting accuracy: ≥ 99% after approval.
  • Reviewer seconds to approve: trending down as schemas stabilize.



Builder Mode — pipeline, schemas, validators, approvals

Copy these components into your stack. They are vendor-agnostic and optimized for auditability and low edit time.

Reference pipeline

  1. Intake: watch accounts@ mailbox, portal folder, and scanner uploads.
  2. OCR: convert PDF/images to text with layout coordinates.
  3. Extract: LLM parses fields into strict JSON (schema below).
  4. Validate: vendor, IBAN, VAT, PO lines, totals, policy flags.
  5. Approve: one-click if policy requires; else auto-post.
  6. Post: create vendor bill with lines, tax, cost centers, and attachments.
  7. Archive & audit: store PDF, JSON, hashes, and approval trail.

The schema ensures every reviewer sees the same fields in the same order and missing items are obvious. It also makes logs and audits painless.

Invoice JSON schema (compact)

{
  "invoice_id":"string",
  "invoice_number":"string",
  "invoice_date":"YYYY-MM-DD",
  "due_date":"YYYY-MM-DD",
  "currency":"EUR|USD|DKK|...",
  "vendor":{"name":"string","vendor_id":"string","vat_id":"string","iban":"string","email":"string"},
  "buyer":{"company":"string","cost_center":"string","po_number":"string"},
  "totals":{"subtotal":"number","vat":"number","grand_total":"number"},
  "lines":[{"sku":"string","description":"string","qty":"number","unit_price":"number","vat_rate":"number","total":"number"}],
  "hashes":{"pdf_sha256":"string","json_sha256":"string"},
  "source":{"channel":"email|scan|portal","filename":"string"},
  "validation":{
    "vendor_match":"pass|fail",
    "bank_match":"pass|fail",
    "vat_valid":"pass|fail",
    "po_match":"pass|warn|fail",
    "totals_check":"pass|fail",
    "policy":"auto|needs_approval|dual_approval",
    "messages":["string"]
  },
  "approvals":[{"by":"user@company.com","at":"ISO-8601","note":"string"}]
}

Validators drive trust by turning fuzzy extraction into hard pass/fail checks. Start minimal and expand only when needed.

Validator rules (minimal set)

  • Vendor match: vendor_id exists in master vendor table.
  • IBAN check: equals last approved IBAN; if changed, force approval.
  • VAT validity: format/country checksum passes.
  • PO match: line-level mapping within ±2% price tolerance.
  • Totals check: sum(lines.total)+VAT equals grand_total within 0.01.
  • Policy engine: compute policy value used for routing.

Prompts should be deterministic. If a field is missing, the model must return null and a validator message, not a guess.

Extraction prompt template

System:
Return ONLY valid JSON matching the schema. Do not invent fields.
User:
Extract the following fields from the invoice text and layout.
Required: invoice_number, invoice_date, due_date, currency, vendor.name, vendor.vat_id, vendor.iban, buyer.po_number, totals.*, lines[*].*
If a field is missing, set null and add a note under validation.messages.
Invoice text: {{OCR_TEXT}}
Layout hints: {{LAYOUT_HINTS}}
Schema: {{JSON_SCHEMA}}

Approvals should be fast and skimmable. Keep links to evidence and a simple yes/no decision.

One-click approval message

Subject: Approve invoice {{invoice_number}} — {{vendor.name}} — {{totals.grand_total}} {{currency}}
Checks: vendor={{vendor_match}}, bank={{bank_match}}, VAT={{vat_valid}}, PO={{po_match}}, totals={{totals_check}}
Open PDF: {{pdf_url}} • JSON: {{json_url}}
Approve: ✅ "approve {{invoice_id}}"  |  Reject: ❌ "reject {{invoice_id}} reason: ..."
SLA: 24h (escalates once)

Most reliability comes from a few small ops patterns: retries, idempotency, and dead-letter queues for human review.

Error handling & idempotency

  • Retries: exponential backoff up to 3x for OCR/LLM/network steps.
  • Idempotency: hash PDFs (pdf_sha256) and skip duplicates.
  • Dead-letter: repeated failures go to a manual queue with reason and last JSON attached.

Log only what you need for audits and privacy. Hashes beat raw content whenever possible.

Minimal logging fields

  • flow_id, user_id, ts, idempotency_key
  • model_name, prompt_version, validators_passed
  • approval_id, approver, decision, evidence_links
  • policy_flags (pii_hit, risky_verb), outcome (auto|approved|rejected)



FAQ — invoice automation

Do we need an LLM if OCR already captures text?
Yes for messy layouts. The LLM structures fields into the schema so validators and posting stay consistent.

When is auto-post safe?
When vendor is whitelisted, PO/totals/VAT pass, and spend is under a threshold (for example €1,000). Anything else routes to approval.

How do we stop bank-change fraud?
Compare IBAN against the last approved record. Any mismatch forces human approval and out-of-band verification.

What about costs?
Keep API costs low by batching, caching vendor lookups, and using smaller models for extraction; reserve larger models for tricky exceptions. See Cost Optimization.

Final thoughts

Schema-first intake with validator rules and one-click approvals turns a noisy inbox into clean, auditable postings. Start with a 30-day pilot on your top vendors, lock the policy thresholds, and measure STP, exception aging, and reviewer time weekly. When the numbers hold, scale coverage and tighten thresholds. The pattern repeats for expenses, receipts, and POs with the same guardrails.

AI Tools Business is independent. We test tools hands-on and publish results with citations or screenshots where relevant.

Editorial safeguards

  • Claims verified by a second reviewer before publication.
  • Changes and price updates are date-stamped and appended.
  • We may use affiliate links - rankings are never paid.

Leave a Comment