Skip to content

Invoice Approval Workflow

An n8n workflow that picks invoices up from Gmail and Google Drive, extracts them with a multimodal LLM, asks a human to approve, and writes clean rows to PostgreSQL.

Year
2026
Role
Solo: workflow design, schemas, integration
Status
Shipped
Context
Product
Automation · n8n · Human-in-the-loop2026

Results

  • 85%

    shorter processing cycle

    Compared with manual invoice handling

  • 99.8%

    structural insertion accuracy

    Rows written to PostgreSQL

Gmail and Google Drive webhooks pick up incoming PDF invoices. A multimodal LLM extracts them against strict JSON schemas, so the output is structured before anything downstream sees it.

Every extraction then goes to a human through an n8n Form for approval, and a vector-storage risk assessment flags anything that looks unusual before it is written to PostgreSQL.

The result is a processing cycle 85% shorter than the manual one, with 99.8% structural accuracy on database inserts.

I also published an open-source accounts-payable version under MIT. It watches a Gmail AP inbox and archives originals to Google Drive, runs Mistral Document AI OCR into Markdown, and extracts with Gemini 2.5 Pro at temperature 0 against a strict schema covering vendor, tax ID, line items, totals and a GL category. Validation reconciles line items to totals and checks confidence; duplicates are blocked, exceptions are emailed to AP, high-value invoices go to Slack for one-tap approval, and clean ones are upserted into a Google Sheets ledger. Invoice text is treated as untrusted, so instructions hidden in a document are ignored.

README · synced from GitHubOpen original ↗

Touchless Accounts Payable on n8n. Invoices and receipts arrive in your inbox. Each one is read, validated against finance controls, routed for approval when needed and posted to your ledger, usually without anyone keying data in by hand.

n8n OCR LLM Sheets Slack License


Executive Overview

Finance teams still re-type invoice data from PDFs into spreadsheets and ERPs. The work is slow, error-prone and costly to scale. Duplicate payments and missed early-payment discounts slip through because no one has time to check every document.

This workflow replaces that manual loop with a six-stage, auditable pipeline:

Stage What happens Business control
① Intake & Archive Watches a dedicated AP inbox, splits attachments and accepts PDFs and receipt photos Every original is stored immutably in Google Drive
② OCR Mistral Document AI converts every page to structured Markdown, tables included Automatic retries on transient API failures
③ AI Extraction Gemini 2.5 Pro (temperature 0) returns a record locked to a strict JSON schema No free-text output; missing data becomes null and is never invented
④ Validation Required fields, line-item → subtotal → total reconciliation, date checks, confidence gate Bad data never reaches the ledger silently
⑤ Exceptions & Approval Duplicates blocked, exceptions emailed to AP, high-value invoices approved in Slack with one click Segregation of duties and duplicate-payment prevention
⑥ Ledger & Alerts Idempotent upsert of invoice header and line items to Google Sheets, Slack status, Gmail label Full audit trail: who, what, when, plus a link to the original

Extracted data model

Group Fields
Vendor Name · Tax ID (VAT / EIN / GSTIN / ABN) · Address · Email
Invoice Invoice # · Invoice date · Due date · PO # · Currency (ISO 4217) · Payment terms
Line items Description · SKU · Quantity · Unit price · Tax rate · Line total
Totals Subtotal · Tax · Shipping · Discount · Total
Classification GL expense category (12-category enum) · Document type · AI confidence · Warnings

Business ROI

Illustrative model. Replace the inputs with your own volumes and loaded labour cost.

Input Manual AP With this workflow
Invoices per month 1,000 1,000
Handling time per invoice ~8 min ~1 min (exceptions only)
Staff hours per month ~133 h ~17 h
Cost at $40/h loaded ~$5,300 / month ~$700 / month + API usage
Cycle time (receipt → posted) Days Minutes

Value drivers your CFO will care about

  • ~85% fewer manual touches. Staff handle exceptions, not data entry.
  • Duplicate-payment prevention. Each invoice is fingerprinted on vendor identity plus invoice number.
  • Policy enforcement. Approval thresholds and confidence gates are configuration, not tribal knowledge.
  • Faster close. Line-item data with GL categories is ready for spend analytics on day one.
  • Audit-ready. Every ledger row links back to the archived original and the n8n execution ID.

Architecture

flowchart LR
    subgraph S1["① Intake & Archive"]
        A["📥 Gmail AP Inbox<br/>(trigger)"] --> B["⚙️ Config<br/>Pipeline Settings"]
        B --> C["✂️ Split Attachments"]
        C --> D{"PDF / Image?"}
        D -- yes --> E["🗄️ Archive Original<br/>Google Drive"]
    end

    subgraph S2["② OCR"]
        E --> F["⬆️ Upload to Mistral"]
        F --> G["🔗 Signed URL"]
        G --> H["🔍 Mistral Document AI<br/>all pages → Markdown"]
    end

    subgraph S3["③ AI Extraction"]
        H --> I["🤖 Gemini 2.5 Pro<br/>temperature 0"]
        J["📐 Strict JSON Schema<br/>Output Parser"] -.-> I
    end

    subgraph S4["④ Validation & Controls"]
        I --> K["✅ Business Rules<br/>required fields · reconciliation<br/>dates · confidence · duplicates"]
        K --> L{"Decision"}
    end

    subgraph S5["⑤ Exceptions & Approval"]
        L -- Duplicate --> M["🚨 Slack: Duplicate Blocked"]
        L -- Needs Review --> N["📧 Email AP Review Queue"]
        L -- "Total ≥ threshold" --> O["💰 Slack Approve / Reject"]
    end

    subgraph S6["⑥ Ledger & Notifications"]
        P["🧾 Prepare Ledger Record"]
        L -- Auto-Approved --> P
        L -- Needs Review --> P
        O --> P
        P --> Q["📊 Sheets: Invoices<br/>(upsert on invoice_key)"]
        P --> R["📊 Sheets: Line_Items<br/>(upsert on line_id)"]
        P --> S["💬 Slack Status Update"]
        P --> T["🏷️ Label Email Processed"]
        M --> T
    end

Decision logic

Decision Condition Outcome
DUPLICATE Vendor + invoice # already processed Slack alert, no ledger entry, email labelled
NEEDS_REVIEW Any validation issue (missing field, totals don't reconcile, low confidence, credit note…) Ledger row with status NEEDS_REVIEW, email to AP with the issue list
APPROVAL_REQUIRED Clean extraction and total ≥ approvalThreshold Slack Approve/Reject buttons (48 h window) → APPROVED / REJECTED / APPROVAL_TIMEOUT
AUTO_APPROVED Clean extraction below threshold Posted straight to the ledger as APPROVED

Repository Structure

├── workflows/
│   └── invoice_processing_pipeline.json   # Import this into n8n
├── .env.example                           # Reference config & credential checklist
├── .gitignore
├── LICENSE
└── README.md

Setup & n8n Import

Prerequisites

  • n8n 1.90+ (self-hosted or n8n Cloud). The instance must be reachable over HTTPS for the Slack approval buttons.
  • Google Workspace account (Gmail, Drive, Sheets)
  • Mistral API key (OCR)
  • Google Gemini API key
  • Slack workspace with a bot token (chat:write, channels:read)

Step 1: Prepare Google Workspace

  1. Gmail: create the label ai-invoice-processed. Copy its label ID (open n8n → Gmail node → Get Many Labels, or use the Gmail API explorer).

  2. Drive: create a folder such as AP / Invoice Archive. Copy the folder ID from its URL.

  3. Sheets: create a spreadsheet with two tabs and these header rows:

    Invoices

    invoice_key | status | vendor_name | vendor_tax_id | invoice_number | invoice_date | due_date | po_number | currency | subtotal | tax_total | shipping_total | discount_total | total | expense_category | document_type | confidence | line_item_count | issues_text | warnings_text | drive_link | file_name | processed_at | execution_id | email_message_id
    

    Line_Items

    line_id | invoice_key | invoice_number | vendor_name | line_number | sku | description | quantity | unit_price | tax_rate | line_total | currency | expense_category
    

Step 2: Import the workflow

  1. In n8n, open Workflows → Add workflow → ⋯ menu → Import from File.
  2. Select workflows/invoice_processing_pipeline.json.
  3. The workflow opens as Enterprise AI Invoice & Expense Automation (inactive).

Step 3: Create credentials

Create these credentials and select them on the matching nodes (names are pre-filled as placeholders):

Credential name n8n type Used by
Enterprise AI Invoice · Gmail (AP Inbox) Gmail OAuth2 Trigger, review email, label
Enterprise AI Invoice · Google Drive Google Drive OAuth2 Archive nodes
Enterprise AI Invoice · Google Sheets Google Sheets OAuth2 Ledger nodes
Enterprise AI Invoice · Mistral API Header Auth → Name Authorization, Value Bearer <MISTRAL_API_KEY> 3 OCR nodes
Enterprise AI Invoice · Google Gemini API Google Gemini (PaLM) API Gemini model
Enterprise AI Invoice · Slack Slack API (bot token) Alerts & approvals

Step 4: Configure the pipeline

Open Config · Pipeline Settings. It is the only node you need to edit:

Setting Default Purpose
approvalThreshold 5000 Totals at or above this need Slack sign-off
confidenceThreshold 0.85 Below this, the invoice goes to manual review
amountTolerance 0.02 Rounding tolerance for reconciliation (or 0.5% of amount, whichever is larger)
requireTaxId true Set false for receipt-heavy expense flows
defaultCurrency USD Used when the document has no currency
slackChannel #ap-invoices Alerts and approvals
apTeamEmail accounts-payable@… Exception queue
googleSheetId / driveArchiveFolderId / processedLabelId placeholders IDs from Step 1

Step 5: Test, then activate

  1. Send a sample invoice PDF to the AP inbox.
  2. Click Test workflow and inspect each stage's output.
  3. Toggle the workflow Active. Duplicate detection persists only in production executions (n8n workflow static data).

Customising

  • Different LLM: swap the Gemini node for OpenAI, Anthropic Claude or Azure OpenAI. The schema parser and prompts are model-agnostic.
  • ERP instead of Sheets: replace the two ledger nodes with QuickBooks, Xero, NetSuite or SAP (HTTP) nodes. Ledger · Prepare Record already outputs a flat, ERP-ready object.
  • Stricter policies: add rules in Validate · Apply Business Rules, e.g. vendor allow-list or PO matching. Each rule pushes a message to issues.

Security & Compliance Notes

  • No API keys live in the workflow JSON; all secrets sit in n8n's encrypted credential store.
  • Document text is treated as untrusted. The system prompt tells the model to ignore instructions embedded in invoices (prompt-injection hardening).
  • Original documents are retained in Drive for audit. Apply your retention policy to the archive folder.
  • Run self-hosted n8n if invoices must stay within your infrastructure or region.

License

MIT