This workflow follows the Chainllm → Google Sheets 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 →
{
"id": "c92ZApSKwsRmg6zb",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Smart Document Parser for Invoices, Logs or Sensor Reports (PDF/Image/csv to Sheet)",
"tags": [],
"nodes": [
{
"id": "98517a08-3fc4-4c0c-aa4b-44d93c864eb4",
"name": "Check file type",
"type": "n8n-nodes-base.switch",
"position": [
220,
860
],
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "40ee8e68-2b72-4ba9-b7a2-8c976852d48b",
"operator": {
"type": "string",
"operation": "contains"
},
"leftValue": "={{ $('Webhook Invoice upload').item.binary.file.mimeType }}",
"rightValue": "image"
}
]
}
},
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "c4315e16-313f-4363-a625-71436498e46a",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Webhook Invoice upload').item.binary.file.mimeType }}",
"rightValue": "application/pdf"
}
]
}
},
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cffb0678-f006-47e0-91ea-afd17f133a77",
"operator": {
"type": "string",
"operation": "contains"
},
"leftValue": "={{ $('Webhook Invoice upload').item.binary.file.mimeType }}",
"rightValue": "csv"
}
]
}
}
]
},
"options": {}
},
"typeVersion": 3.2
},
{
"id": "6ef5d99c-b842-4290-9766-8b780df66f6b",
"name": "Invoice data",
"type": "n8n-nodes-base.googleSheets",
"position": [
738,
1110
],
"parameters": {
"columns": {
"value": {
"total": "={{ $json.total }}",
"currency": "={{ $json.currency }}",
"due_date": "={{ $json.due_date }}",
"subtotal": "={{ $json.subtotal }}",
"tax_total": "={{ $json.tax_total }}",
"invoice_id": "={{ $json.invoice_id }}",
"vendor_name": "={{ $json.vendor_name }}",
"invoice_date": "={{ $json.invoice_date }}",
"customer_name": "={{ $json.customer_name }}"
},
"schema": [
{
"id": "invoice_id",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "invoice_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "invoice_date",
"type": "string",
"display": true,
"required": false,
"displayName": "invoice_date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "due_date",
"type": "string",
"display": true,
"required": false,
"displayName": "due_date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "customer_name",
"type": "string",
"display": true,
"required": false,
"displayName": "customer_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "vendor_name",
"type": "string",
"display": true,
"required": false,
"displayName": "vendor_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "subtotal",
"type": "string",
"display": true,
"required": false,
"displayName": "subtotal",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "tax_total",
"type": "string",
"display": true,
"required": false,
"displayName": "tax_total",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "total",
"type": "string",
"display": true,
"required": false,
"displayName": "total",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "currency",
"type": "string",
"display": true,
"required": false,
"displayName": "currency",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "customer_address",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "customer_address",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "customer_tax_id",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "customer_tax_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "vendor_address",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "vendor_address",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "vendor_tax_id",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "vendor_tax_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "vendor_iban",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "vendor_iban",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "vendor_bic",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "vendor_bic",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "line_id",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "line_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "description",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "description",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "quantity",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "quantity",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "unit_price",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "unit_price",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "line_total",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "line_total",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "tax_rate",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "tax_rate",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"invoice_id"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 0,
"cachedResultUrl": "",
"cachedResultName": "Invoice"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "0",
"cachedResultUrl": "",
"cachedResultName": ""
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.6
},
{
"id": "6b0ce6fd-5d09-4bc2-a3b2-cc8c0e2878d6",
"name": "Invoice Data",
"type": "n8n-nodes-base.googleSheets",
"position": [
1256,
760
],
"parameters": {
"columns": {
"value": {
"total": "={{ $json.total }}",
"currency": "={{ $json.currency }}",
"due_date": "={{ $json.due_date }}",
"subtotal": "={{ $json.subtotal }}",
"tax_total": "={{ $json.tax_total }}",
"invoice_id": "={{ $json.invoice_id }}",
"vendor_name": "={{ $json.vendor_name }}",
"invoice_date": "={{ $json.invoice_date }}",
"customer_name": "={{ $json.customer_name }}"
},
"schema": [
{
"id": "invoice_id",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "invoice_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "invoice_date",
"type": "string",
"display": true,
"required": false,
"displayName": "invoice_date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "due_date",
"type": "string",
"display": true,
"required": false,
"displayName": "due_date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "customer_name",
"type": "string",
"display": true,
"required": false,
"displayName": "customer_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "vendor_name",
"type": "string",
"display": true,
"required": false,
"displayName": "vendor_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "subtotal",
"type": "string",
"display": true,
"required": false,
"displayName": "subtotal",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "tax_total",
"type": "string",
"display": true,
"required": false,
"displayName": "tax_total",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "total",
"type": "string",
"display": true,
"required": false,
"displayName": "total",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "currency",
"type": "string",
"display": true,
"required": false,
"displayName": "currency",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Accounting",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Accounting",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"invoice_id"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 0,
"cachedResultUrl": "",
"cachedResultName": "Invoice"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "0",
"cachedResultUrl": "",
"cachedResultName": ""
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.6
},
{
"id": "7f5b8ffe-d4e8-4b7b-803e-6c37d0da0221",
"name": "Transfrom data",
"type": "n8n-nodes-base.code",
"position": [
1036,
760
],
"parameters": {
"jsCode": "const raw = $input.first().json.text || '';\n\n// 1. Remove code block syntax like ```json ... ```\nconst cleaned = raw.replace(/```json|```/g, '').trim();\n\n\n const parsed = JSON.parse(cleaned);\n return [{ json: parsed }];"
},
"typeVersion": 2,
"alwaysOutputData": true
},
{
"id": "b818ac61-4837-4a9f-b90e-bb6b4b7739c1",
"name": "Google Gemini Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
748,
880
],
"parameters": {
"options": {},
"modelName": "models/gemini-1.5-flash"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "2941bf32-0db6-4486-8696-e207de09364c",
"name": "Format data from text",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
660,
660
],
"parameters": {
"text": "=Extract the following invoice details from the given raw text:\n\n- invoice_id \n- invoice_date \n- due_date \n- customer_name \n- vendor_name \n- subtotal \n- tax_total \n- total \n- currency\n\nUse the following input text:\n{{ $json.text }}\n\nReturn the result as a valid JSON object using this exact structure:\n\n{\n \"invoice_id\": \"string or null\",\n \"invoice_date\": \"string (e.g., 2024-10-10) or null\",\n \"due_date\": \"string (e.g., 2024-10-25) or null\",\n \"customer_name\": \"string or null\",\n \"vendor_name\": \"string or null\",\n \"subtotal\": \"string or null\",\n \"tax_total\": \"string or null\",\n \"total\": \"string or null\",\n \"currency\": \"string (e.g., \u20ac, $, \u00a3) or null\"\n}\n\nIf any field is missing or not found, set it as `null`. Return only the JSON output without extra text.\n",
"batching": {},
"promptType": "define"
},
"typeVersion": 1.7
},
{
"id": "7c829587-f028-4332-831f-92f9529b72ca",
"name": "Webhook Invoice upload",
"type": "n8n-nodes-base.webhook",
"position": [
0,
860
],
"parameters": {
"path": "uploadDoc",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2
},
{
"id": "05176b33-fcda-4f1a-84fa-2449108a0a54",
"name": "PDF to Text",
"type": "n8n-nodes-base.extractFromFile",
"position": [
440,
860
],
"parameters": {
"options": {},
"operation": "pdf",
"binaryPropertyName": "file"
},
"typeVersion": 1
},
{
"id": "81690344-d04c-428b-b720-bb539fbe2bbe",
"name": "Image to Text",
"type": "n8n-nodes-tesseractjs.tesseractNode",
"position": [
440,
660
],
"parameters": {
"options": {},
"inputDataFieldName": "file"
},
"typeVersion": 1
},
{
"id": "a0f49ed7-1d42-4df8-a802-74754d1549c0",
"name": "CSV to JSON",
"type": "n8n-nodes-base.extractFromFile",
"position": [
440,
1110
],
"parameters": {
"options": {},
"binaryPropertyName": "file"
},
"typeVersion": 1
},
{
"id": "0473ba6b-734e-4f53-8ecb-86711db1bd76",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-60,
1300
],
"parameters": {
"color": 2,
"width": 1500,
"height": 540,
"content": "---\n### **Purpose**\n * To automatically extract structured data from uploaded documents (PDFs, images, or CSVs) \u2014 such as invoices, logs, or reports \u2014 and save the results into Google Sheets using AI and OCR.\n\n---\n### **Core Logic**\n1. **Webhook Trigger** receives the uploaded document.\n2. **Switch Node** detects file type:\n * Image \u2192 Parsed using **Tesseract OCR**\n * PDF \u2192 Parsed via built-in PDF extractor\n * CSV \u2192 Parsed as raw text\n3. Extracted text is sent to **Google Gemini AI** to identify fields like:\n * `invoice_id`, `invoice_date`, `total`, etc.\n4. AI output is converted into valid JSON.\n5. JSON is **appended to Google Sheets** via `appendOrUpdate`.\n\n---\n### **Outcome**\n* Extracted invoice/report data is stored cleanly in a Google Sheet.\n* Works with scanned documents, images, and structured files.\n* Enables AI-powered automation of manual data entry workflows."
},
"typeVersion": 1
},
{
"id": "63a9e69e-566c-4db6-9d31-b25f438fbd26",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-72,
550
],
"parameters": {
"color": 7,
"width": 1500,
"height": 720,
"content": "## Smart Document Parser for Invoices, Logs or Sensor Reports (PDF/Image/csv to Sheet)"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "b5ae5035-b75f-4f8d-8d43-020fdb2c529e",
"connections": {
"CSV to JSON": {
"main": [
[
{
"node": "Invoice data",
"type": "main",
"index": 0
}
]
]
},
"PDF to Text": {
"main": [
[
{
"node": "Format data from text",
"type": "main",
"index": 0
}
]
]
},
"Image to Text": {
"main": [
[
{
"node": "Format data from text",
"type": "main",
"index": 0
}
]
]
},
"Transfrom data": {
"main": [
[
{
"node": "Invoice Data",
"type": "main",
"index": 0
}
]
]
},
"Check file type": {
"main": [
[
{
"node": "Image to Text",
"type": "main",
"index": 0
}
],
[
{
"node": "PDF to Text",
"type": "main",
"index": 0
}
],
[
{
"node": "CSV to JSON",
"type": "main",
"index": 0
}
]
]
},
"Format data from text": {
"main": [
[
{
"node": "Transfrom data",
"type": "main",
"index": 0
}
]
]
},
"Webhook Invoice upload": {
"main": [
[
{
"node": "Check file type",
"type": "main",
"index": 0
}
]
]
},
"Google Gemini Chat Model": {
"ai_languageModel": [
[
{
"node": "Format data from text",
"type": "ai_languageModel",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
googlePalmApigoogleSheetsOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
How this works
Extract valuable insights from invoices, logs, or sensor reports effortlessly, saving hours of manual data entry by converting PDFs, images, or CSVs into organised Google Sheets. This workflow suits small business owners handling supplier invoices, field technicians processing sensor data, or analysts reviewing equipment logs who need quick, accurate data structuring without advanced coding skills. The key step involves the Google Gemini AI model intelligently parsing the document content after initial text extraction, followed by formatting and appending the results to your sheet for seamless analysis.
Use this workflow when dealing with unstructured documents arriving via uploads or APIs, such as automated invoice processing from email attachments or batch-converting sensor images from IoT devices. Avoid it for highly customised extractions requiring domain-specific rules, where a dedicated OCR service like Tesseract might need tuning, or for real-time streaming data that demands lower latency than webhook triggers allow. Common variations include adapting the AI prompts for medical reports or financial statements, or integrating with email nodes to pull files directly from inboxes.
About this workflow
Smart Document Parser for Invoices, Logs or Sensor Reports (PDF/Image/csv to Sheet). Uses googleSheets, lmChatGoogleGemini, chainLlm, extractFromFile. Webhook trigger; 12 nodes.
Source: https://github.com/abbasZaidi110/n8n-Parse-Invoices-Documents-with-Gemini-AI-OCR-and-Google-Sheets-Integration/blob/main/main.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
ANIS_HUB 1. Uses gmail, googleDrive, googleSheets, httpRequest. Webhook trigger; 89 nodes.
Resume Screening & Behavioral Interviews with Gemini, Elevenlabs, & Notion ATS copy. Uses outputParserStructured, chainLlm, googleDrive, stickyNote. Webhook trigger; 67 nodes.
Candidate Engagement | Resume Screening | AI Voice Interviews | Applicant Insights
leads. Uses supabase, gmail, formTrigger, httpRequest. Webhook trigger; 62 nodes.
Categories: Accounting Automation • OCR Processing • AI Data Extraction • Business Tools