Skip to content
Arslan Vuzmal Lone
PROJECT · FINANCE · DOCUMENT AI & EXTRACTION

LedgerQuarry: invoices and receipt photos turned into clean, checked data

An n8n workflow that reads invoice PDFs and images from Gmail or Google Drive, extracts every field with Claude, checks the arithmetic in code, and files each invoice as approved or for review.

By Arslan Vuzmal Lone·Built July 2026·Updated July 2026·Open source
LedgerQuarry → Google Sheet rowPer invoice
✓INV-2026-0412 · Apex Office Supplies
Lines = subtotal; subtotal + tax = totalAUTO_APPROVED
~Receipt photo · Café Central
Average confidence 68REVIEW_RECOMMENDED
✕INV-88 · Northline Freight
Calculated total 1,180.00 ≠ stated 1,108.00REVIEW_REQUIRED
⧉INV-2026-0412 (again)
Already in the sheetDuplicate folder
Figure 1:The statuses the workflow writes. Sample data.

At a glance

FOR
Bookkeepers and finance teams typing invoices by hand
DOES
Read PDF or image · extract fields · check the maths · sort by status
INPUT
Gmail attachments or files dropped in a Google Drive folder
OUTPUT
One Google Sheet row per invoice, filed source document, email notice
BUILT WITH
n8n, Claude 3.5 Sonnet (Anthropic API), Google Sheets, Drive, Gmail
HUMAN IN LOOP
Anything not AUTO_APPROVED is emailed for a person to review

Someone on the team retypes every invoice, and checks the sums by eye.

Invoices arrive as text PDFs, scanned PDFs and phone photos. Each one has to be read, typed into a sheet or ledger, and checked: do the lines add up, is the tax right, have we seen this invoice before?

A model can read the document, but it can also misread a digit. LedgerQuarry lets Claude do the reading and leaves every check to plain code, so a misread total cannot be filed as approved.

One invoice through the workflowStep 1 of 4
Step 01

Arrives

A Gmail attachment or a new file in a watched Drive folder starts the workflow.


How it works

Each stage as it exists in the repository. Select a stage to see what it uses and what happens when it fails.

How it runsSelect a step · arrow keys move
Ingest
Extract
Check
File
Step 01 · Ingest

Trigger

What happens

Starts on a new Gmail attachment or a new Drive file

Uses

n8n Gmail Trigger, Google Drive Trigger

If it fails

Logged to the Error Log sheet with an admin email

Sample data.
invoice_march_2026.pdf

Execution sequence

One item, traced through the system boundaries.

One invoice, from inbox to sheet
  1. Gmail / Drive to n8n workflow: new attachment: invoice.pdf
  2. n8n workflow to Claude API: POST /v1/messages (text or image)
  3. Claude API replies to n8n workflow: JSON fields + confidence
  4. n8n workflow to n8n workflow: validateMath · validateFields · determineStatus
  5. n8n workflow to Google Sheet: check duplicate, then append row
  6. n8n workflow to Gmail / Drive: success or review email; file moved to folder

One item, start to finish

1. Scanned invoice arrives

A supplier emails a scanned PDF. Text extraction finds almost no text, so the page is converted to an image.

2. Fields extracted

Claude returns invoice number, dates, vendor, line items, subtotal, tax and total, each with a confidence score.

3. Arithmetic fails

The lines add up to the subtotal, but subtotal plus tax does not equal the stated total: TOTAL_MISMATCH.

4. Sent for review

The row is written as REVIEW_REQUIRED and a review email goes out with the discrepancy spelled out.


The checks that decide each invoice’s status

Change any number as if the model had misread it. The status logic below is the workflow’s own code, translated line for line.

After Claude returns the extracted fields, three n8n Code nodes decide what happens to the invoice. Change the numbers as if the model had misread one.

AUTO_APPROVED
flags: none
Tolerance ±0.02. Required review: any math mismatch, or a missing invoice number or total. Recommended review: average confidence under 75, more than two low-confidence fields, or a credit note.

Logic copied from LedgerQuarry workflows/workflow.json (nodes validateMath, validateFields, classifyConfidence, determineStatus). Inputs are yours to change; nothing here calls a model or a server.


Architecture

The layers and the decision path, taken from the repository code.

System Architecture StackTop-down request path
System Architecture Stack
LayerComponentTech StackResponsibility
Layer 1: TriggersGmail and Drive watchersn8n trigger nodes, Google OAuthStart one run per document
Layer 2: ExtractionClaude multimodal callKEYAnthropic Messages API, claude-3-5-sonnet-20241022Read text or image into a fixed JSON schema with confidences
Layer 3: ChecksDeterministic validationKEYn8n Code nodes (JavaScript)Arithmetic, required fields, confidence, status
Layer 4: RecordsSheet, folders, emailGoogle Sheets, Drive, Gmail, Apps Script formattingInvoice rows, audit log, error log, filing
LedgerQuarry decision pathRed dashed line = fallback route
  • Gmail / Drive goes to Text or image?: file
  • Text or image? goes to Claude extract: text or page image
  • Claude extract goes to Maths + fields: JSON + confidence
  • Maths + fields goes to Sheet + folder: AUTO_APPROVED
  • Maths + fields falls back to Review email: REVIEW_*

Decisions and trade-offs

DecisionInstead ofWhyWhere in the code
Arithmetic checked in codeAsking the model whether the totals add upThe model reads; code adds. A misread digit shows up as a mismatch instead of being trusted.workflow.json, node validateMath
Confidence per fieldOne confidence for the whole documentThe schema asks for a confidence on every value, so low-confidence fields can be counted and listed.workflow.json, nodes Prepare Claude Multimodal Payload, classifyConfidence
Text first, image only when neededAlways sending page imagesText PDFs go as text; only PDFs with under 50 characters of text are converted to images.workflow.json, node IF PDF Text Length > 50
Duplicates quarantined, not droppedSilently skipping repeatsA repeated invoice is moved to a duplicates folder and an alert is sent, so nobody has to wonder where it went.workflow.json, nodes Check Duplicate, Duplicate Alert
Source: Read from github.com/arslanvuzmal/LedgerQuarry

Known limits

Output is a Google Sheet

There is no direct connection to Xero, QuickBooks or other accounting software in this workflow. Rows land in a sheet; posting to a ledger would be another step.

No VAT number check

The workflow checks arithmetic and required fields. It does not validate supplier VAT numbers against VIES or HMRC.

Single page images

Scanned PDFs are converted to an image for the model; long multi-page scans have not been evaluated.


Results

Only numbers produced by a committed, repeatable script appear here as measured. Until then, each result says how it will be measured.

To be measured
Field-level extraction accuracy

Date, total, tax and vendor accuracy on a public receipt dataset (CORD or SROIE), with the document count, model version, licence and failures shown.

To be measured
Share of invoices auto-approved

Count of AUTO_APPROVED vs review statuses on the same public dataset.

To be measured
Time saved for a finance team

Only measurable with a client: minutes per invoice before and after.


Run it yourself

From the installation guide: run n8n, add credentials, import the workflow. Full instructions ↗

bash
git clone https://github.com/arslanvuzmal/LedgerQuarry.git
# 1. Run n8n (docs/INSTALLATION.md, step 3 has a docker-compose file)
# 2. In n8n, add an Anthropic API key and Google OAuth2 credentials (step 4)
# 3. Workflows → Import from File → LedgerQuarry/workflows/workflow.json (step 5)
# 4. Point the Gmail / Drive triggers and the Google Sheet at your own, then activate
Versions: n8n 1.x · Anthropic API · Google OAuth

Questions people ask first

What files does it read?

PDF (text or scanned), PNG and JPEG. The file type is detected from the file’s first bytes, not its name.

Does it post to my accounting software?

Not in this version. It writes one row per invoice to a Google Sheet and files the document in Drive. A connection to Xero or QuickBooks would be an extra workflow step.

What if a receipt is unreadable?

Fields Claude cannot read come back empty with zero confidence. Missing totals or invoice numbers make the invoice REVIEW_REQUIRED, and a review email is sent.

What happens to a duplicate?

The invoice is looked up in the sheet first. A repeat is moved to a duplicates folder and an alert email is sent; the sheet is not touched.

Related reading & systems

Want LedgerQuarry working in your business?

Book a 20-minute scoping call. I will review your current systems, map where manual friction is costing you time, and give you an honest quote.

AI Workflow Audit · €390 · Credited toward build · or email arslanvuzmallone@gmail.com