AutomationFlowsFinance › Benchmark Invoice Data Extraction Accuracy with Easybits

Benchmark Invoice Data Extraction Accuracy with Easybits

ByFelix @easybits on n8n.io

Upload the same invoice in different qualities (original PDF, scanned copy, phone photo, compressed JPEG, etc.) and instantly see how accurately each field was extracted. The workflow compares every extracted value against a fixed ground truth and returns a per-field pass/fail…

Event trigger★★★★☆ complexity13 nodesForm Trigger@Easybits/N8N Nodes ExtractorForm
Finance Trigger: Event Nodes: 13 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #14957 — we link there as the canonical source.

This workflow follows the Form → Form Trigger recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "name": "Stresstest Workflow (easybits Extractor verified community node)",
  "tags": [],
  "nodes": [
    {
      "id": "0fcb599c-7cce-45a3-bbdb-179ae3078e79",
      "name": "Document Upload",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        16,
        96
      ],
      "parameters": {
        "options": {},
        "formTitle": "Document Upload Form",
        "formFields": {
          "values": [
            {
              "fieldType": "file",
              "fieldLabel": "Upload"
            }
          ]
        },
        "responseMode": "lastNode"
      },
      "typeVersion": 2.5
    },
    {
      "id": "9b51006c-7343-412d-87b2-55005b5e1aa1",
      "name": "Validation",
      "type": "n8n-nodes-base.set",
      "position": [
        1232,
        96
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a9749b03-86a3-42ab-9bea-2e37b3bc2f45",
              "name": "amount_due_status",
              "type": "string",
              "value": "={{ $json.data.amount_due === 0 ? \"correct \u2705\" : \"incorrect \u274c\" }}"
            },
            {
              "id": "d155a6b5-108b-4634-9cf0-d857b582ecd0",
              "name": "amount_paid_status",
              "type": "string",
              "value": "={{ $json.data.amount_paid === 73.82 ? \"correct \u2705\" : \"incorrect \u274c\" }}"
            },
            {
              "id": "a160371f-7ca0-4453-bd9e-b665839f1d18",
              "name": "billing_period_status",
              "type": "string",
              "value": "={{ $json.data.billing_period === \"Jan 15 to Feb 15, 2026\" ? \"correct \u2705\" : \"incorrect \u274c\" }}"
            },
            {
              "id": "7ecd25a0-9ebb-4538-a754-3719cabfb3fe",
              "name": "currency_status",
              "type": "string",
              "value": "={{ $json.data.currency === \"EUR\" ? \"correct \u2705\" : \"incorrect \u274c\" }}"
            },
            {
              "id": "ebf4410d-9528-4825-8522-9f4702ef2814",
              "name": "customer_name_status",
              "type": "string",
              "value": "={{ $json.data.customer_name === \"Max Mustermann\" ? \"correct \u2705\" : \"incorrect \u274c\" }}"
            },
            {
              "id": "0b5f14ea-ab7c-4d9b-869a-a5dc293b799d",
              "name": "invoice_date_status",
              "type": "string",
              "value": "={{ $json.data.invoice_date === \"Jan 15, 2026\" ? \"correct \u2705\" : \"incorrect \u274c\" }}"
            },
            {
              "id": "92da2d35-6694-4113-8572-2f58b1e5a235",
              "name": "invoice_number_status",
              "type": "string",
              "value": "={{ $json.data.invoice_number === \"IN-2026-0022514\" ? \"correct \u2705\" : \"incorrect \u274c\" }}"
            },
            {
              "id": "f51863ca-174f-48cc-949d-af161fd3140e",
              "name": "payment_status_status",
              "type": "string",
              "value": "={{ $json.data.payment_status === \"PAID\" ? \"correct \u2705\" : \"incorrect \u274c\" }}"
            },
            {
              "id": "678b30ca-69eb-424c-bd3a-c383b166b7d4",
              "name": "total_amount_status",
              "type": "string",
              "value": "={{ $json.data.total_amount === 73.82 ? \"correct \u2705\" : \"incorrect \u274c\" }}"
            },
            {
              "id": "6b94284d-8ebb-4896-8dcf-203b2272b0ff",
              "name": "vendor_name_status",
              "type": "string",
              "value": "={{ $json.data.vendor_name === \"easybits GmbH\" ? \"correct \u2705\" : \"incorrect \u274c\" }}"
            },
            {
              "id": "51efc06b-0fc7-409c-b5a9-7b8a0947698c",
              "name": "accuracy_percent",
              "type": "number",
              "value": "={{ (\n  ($json.data.amount_due === 0 ? 1 : 0) +\n  ($json.data.amount_paid === 73.82 ? 1 : 0) +\n  ($json.data.billing_period === \"Jan 15 to Feb 15, 2026\" ? 1 : 0) +\n  ($json.data.currency === \"EUR\" ? 1 : 0) +\n  ($json.data.customer_name === \"Max Mustermann\" ? 1 : 0) +\n  ($json.data.invoice_date === \"Jan 15, 2026\" ? 1 : 0) +\n  ($json.data.invoice_number === \"IN-2026-0022514\" ? 1 : 0) +\n  ($json.data.payment_status === \"PAID\" ? 1 : 0) +\n  ($json.data.total_amount === 73.82 ? 1 : 0) +\n  ($json.data.vendor_name === \"easybits GmbH\" ? 1 : 0)\n) / 10 * 100 }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "f7f9ba54-b830-4f2b-abae-e31d3183923c",
      "name": "Merge Ground Truth",
      "type": "n8n-nodes-base.merge",
      "position": [
        928,
        384
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "3a2a3e96-586d-4f5c-997c-adad9e466725",
      "name": "Ground Truth",
      "type": "n8n-nodes-base.set",
      "position": [
        624,
        96
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "f4ee8a43-3aea-431f-8d9b-4d856fb07190",
              "name": "gt_amount_due",
              "type": "number",
              "value": 0
            },
            {
              "id": "69e34d32-9262-411c-acb3-bac059b8095f",
              "name": "gt_amount_paid",
              "type": "number",
              "value": 73.82
            },
            {
              "id": "d8b4619b-aedf-4207-a142-1903c5417239",
              "name": "gt_billing_period",
              "type": "string",
              "value": "Jan 15 to Feb 15, 2026"
            },
            {
              "id": "1766bb6f-ab35-4032-b47a-fdb429521f04",
              "name": "gt_currency",
              "type": "string",
              "value": "EUR"
            },
            {
              "id": "bbaea181-5391-494b-80a3-58756692203c",
              "name": "gt_customer_name",
              "type": "string",
              "value": "Max Mustermann"
            },
            {
              "id": "efb28932-894d-4357-9e0a-2dd989fef99a",
              "name": "gt_invoice_date",
              "type": "string",
              "value": "Jan 15, 2026"
            },
            {
              "id": "3df929a7-ca9e-4a50-96cf-06e41856772b",
              "name": "gt_invoice_number",
              "type": "string",
              "value": "IN-2026-0022514"
            },
            {
              "id": "d281a5cb-07d0-481d-b71b-8844aaf975a9",
              "name": "gt_payment_status",
              "type": "string",
              "value": "PAID"
            },
            {
              "id": "2feba545-bd40-4c4e-9519-741c1aeca7d2",
              "name": "gt_total_amount",
              "type": "number",
              "value": 73.82
            },
            {
              "id": "29eff29d-9fe0-4a03-97d4-3ed0cc59dfb0",
              "name": "gt_vendor_name",
              "type": "string",
              "value": "easybits GmbH"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "a8a48fb4-163a-4b3a-8ba9-887736b25b07",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -848,
        -336
      ],
      "parameters": {
        "width": 752,
        "height": 1088,
        "content": "# \ud83e\uddea easybits Extractor \u2013 Stress Test Workflow\n\n## What This Workflow Does\nUpload the same invoice in different qualities (original PDF, scanned copy, phone photo, compressed JPEG, etc.) and instantly see how accurately each field was extracted. The workflow compares every extracted value against a fixed ground truth and returns a per-field pass/fail report with an overall accuracy percentage \u2013 directly in the browser.\n\n## How It Works\n1. **Upload** \u2013 A document is submitted through the n8n web form\n2. **Extract** \u2013 easybits Extractor processes the file and returns structured data\n3. **Compare** \u2013 Each extracted field is compared against the known correct values\n4. **Report** \u2013 A completion screen shows which fields matched and the overall accuracy\n\n## Setup Guide\n\n### 1. Create Your easybits Extractor Pipeline\n1. Go to [extractor.easybits.tech](https://extractor.easybits.tech/) and create a new pipeline\n2. Upload one of the example invoices as your reference document \u2013 you can find them here: https://github.com/felix-sattler-easybits/n8n-workflows/tree/88d7c9818b150e71dd749bf9f665359fa57efcb9/data-extraction-stresstest\n3. Click **Auto-Mapping** \u2013 the Extractor will automatically detect and set up all fields for you\n4. Save the pipeline and copy your **Pipeline ID** and **API Key**\n\n### 2. Connect Your easybits Credentials\nOpen the **easybits Extractor** node in the workflow and connect your credentials (Pipeline ID & API Key). The node will use the pipeline you just created \u2013 no further configuration needed.\n\n### 3. Adjust the Ground Truth (if needed)\nThe **Ground Truth** node contains the expected values for all 10 fields. If you're testing with a different document, update these values to match your reference invoice.\n\n### 4. Activate & Test the workflow by uploading your first test document\n\n---\n\n## \ud83d\udd04 Want to Test a Different Extraction Solution?\nYou can swap out the easybits Extractor node for an **HTTP Request node** pointing at any other extraction API. As long as your HTTP node returns the same field names under `json.data` (e.g. `data.invoice_number`, `data.amount_paid`, etc.), the rest of the workflow \u2013 ground truth comparison, validation, and results display \u2013 works identically. This makes it easy to benchmark multiple solutions side by side using the exact same test documents and accuracy criteria."
      },
      "typeVersion": 1
    },
    {
      "id": "b1edcf65-811a-43b3-ad64-2d283af43e68",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -80,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 384,
        "content": "## \ud83d\udce5 Document Upload\nHosts a simple web form with a single file upload field. Set to \"Workflow Finishes\" mode so the browser waits for the full pipeline to complete before showing results."
      },
      "typeVersion": 1
    },
    {
      "id": "d4082c17-e4fb-4b05-b4cc-aa3b0f3968fb",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        224,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 384,
        "content": "## \ud83e\udd16 easybits Data Extraction\nSends the uploaded file to the easybits Extractor API. Returns structured fields under `json.data` \u2013 including invoice number, amounts, dates, vendor, and payment status."
      },
      "typeVersion": 1
    },
    {
      "id": "54adb19b-1033-4358-a88e-7b0d608a6a09",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        528,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 384,
        "content": "## \ud83d\udccb Ground Truth\nHolds the known correct values for all 10 fields, prefixed with `gt_` to avoid name collisions after merging. Update these values if you switch to a different test document."
      },
      "typeVersion": 1
    },
    {
      "id": "a951b9cd-a29f-42db-904c-7a236b188f9d",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        832,
        176
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 384,
        "content": "## \ud83d\udd00 Merge Ground Truth\nCombines the extracted data (Input 1) with the ground truth values (Input 2) into a single item using positional merge. This puts both datasets side by side for comparison."
      },
      "typeVersion": 1
    },
    {
      "id": "8f89e502-1420-43e8-8db6-4b1ee5224f51",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1136,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 384,
        "content": "## \u2705 Validation\nCompares each extracted field against its ground truth value. Outputs a status per field (correct \u2705 / incorrect \u274c) and calculates the overall accuracy as a percentage."
      },
      "typeVersion": 1
    },
    {
      "id": "7d2fa37b-5d86-4909-8a9e-e3095a1b73a8",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1440,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 384,
        "content": "## \ud83d\udcca Results\nDisplays the final report as a form completion page. Shows the accuracy percentage and a per-field breakdown so you can immediately see which fields were extracted correctly and which ones drifted."
      },
      "typeVersion": 1
    },
    {
      "id": "3fefe62e-e5eb-45c3-9585-d5296790e0f8",
      "name": "easybits: Data Extraction",
      "type": "@easybits/n8n-nodes-extractor.easybitsExtractor",
      "position": [
        320,
        96
      ],
      "parameters": {},
      "typeVersion": 2
    },
    {
      "id": "55f36569-dd9b-4957-ba75-e6df41977ffc",
      "name": "Results in Form",
      "type": "n8n-nodes-base.form",
      "position": [
        1536,
        96
      ],
      "parameters": {
        "options": {},
        "operation": "completion",
        "completionTitle": "Stresstest Results",
        "completionMessage": "=Extraction Accuracy: {{ $json.accuracy_percent }}%<br><br>Vendor Name: {{ $json.vendor_name_status }}<br>Customer Name: {{ $json.customer_name_status }}<br>Invoice Number: {{ $json.invoice_number_status }}<br>Invoice Date: {{ $json.invoice_date_status }}<br>Billing Period: {{ $json.billing_period_status }}<br>Currency: {{ $json.currency_status }}<br>Total Amount: {{ $json.total_amount_status }}<br>Amount Paid: {{ $json.amount_paid_status }}<br>Amount Due: {{ $json.amount_due_status }}<br>Payment Status: {{ $json.payment_status_status }}"
      },
      "typeVersion": 2.5
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "Validation": {
      "main": [
        [
          {
            "node": "Results in Form",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ground Truth": {
      "main": [
        [
          {
            "node": "Merge Ground Truth",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Document Upload": {
      "main": [
        [
          {
            "node": "easybits: Data Extraction",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Ground Truth": {
      "main": [
        [
          {
            "node": "Validation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "easybits: Data Extraction": {
      "main": [
        [
          {
            "node": "Merge Ground Truth",
            "type": "main",
            "index": 0
          },
          {
            "node": "Ground Truth",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Upload the same invoice in different qualities (original PDF, scanned copy, phone photo, compressed JPEG, etc.) and instantly see how accurately each field was extracted. The workflow compares every extracted value against a fixed ground truth and returns a per-field pass/fail…

Source: https://n8n.io/workflows/14957/ — original creator credit. Request a take-down →

More Finance workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Finance

This workflow allows you to quickly generate and send invoices by collecting missing billing details from clients through an automated form and email sequence. It integrates Gmail and QuickBooks Onlin

QuickBooks, Form Trigger, Gmail
Finance

This is the ultimate sales-to-cash automation. When a deal in Airtable is marked "Approved for Invoicing," this workflow intelligently syncs customer data across QuickBooks and Stripe (creating them i

Airtable Trigger, Stripe, QuickBooks +2
Finance

How It Works Trigger: Watches for new emails in Gmail with PDF/image attachments. OCR: Sends the attachment to OCR.space API (https://ocr.space/OCRAPI) to extract invoice text. Parsing: Extracts key f

Gmail Trigger, Google Sheets, Slack +3
Finance

Automated Stripe Payment to QuickBooks Sales Receipt

HTTP Request, Stripe, Stripe Trigger +1
Finance

Automatically generate an Invoice PDF from Google Sheets data with DocuPotion. Uses googleSheetsTrigger, googleSheets, n8n-nodes-docupotion, googleDrive. Event-driven trigger; 12 nodes.

Google Sheets Trigger, Google Sheets, N8N Nodes Docupotion +1