This workflow follows the Google Sheets → HTTP Request 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": "q9JXFmTt3xA1i7xV",
"name": "Invoice Processing Workflow",
"active": false,
"isArchived": false,
"versionId": "49a21b05-aa03-427c-96ab-fabf78dfe098",
"settings": {
"executionOrder": "v1"
},
"connections": {
"Receive Invoice": {
"main": [
[
{
"node": "Extract PDF Text",
"type": "main",
"index": 0
}
]
]
},
"Extract PDF Text": {
"main": [
[
{
"node": "OpenRouter Extract Invoice",
"type": "main",
"index": 0
}
]
]
},
"OpenRouter Extract Invoice": {
"main": [
[
{
"node": "Parse Invoice JSON",
"type": "main",
"index": 0
}
]
]
},
"Parse Invoice JSON": {
"main": [
[
{
"node": "Append to Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"Append to Google Sheets": {
"main": [
[
{
"node": "Respond with Invoice",
"type": "main",
"index": 0
}
]
]
}
},
"nodes": [
{
"id": "30737c6c-186e-43ad-a87a-dd35520c0844",
"name": "Receive Invoice",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
0,
0
],
"parameters": {
"httpMethod": "POST",
"path": "invoice-process",
"responseMode": "responseNode",
"options": {
"binaryData": true,
"binaryPropertyName": "data"
}
}
},
{
"id": "7cb18d3b-0a57-455e-9e9e-411c7cf9d6ed",
"name": "Extract PDF Text",
"type": "n8n-nodes-base.extractFromFile",
"typeVersion": 1.1,
"position": [
224,
0
],
"parameters": {
"operation": "pdf",
"binaryPropertyName": "data"
}
},
{
"id": "8da07760-6778-4c05-9b30-e028b40cebe4",
"name": "OpenRouter Extract Invoice",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.4,
"position": [
448,
0
],
"parameters": {
"method": "POST",
"url": "={{ $vars.OPENROUTER_BASE_URL }}/chat/completions",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"contentType": "json",
"specifyBody": "json",
"jsonBody": "={ \"model\": \"{{ $vars.OPENROUTER_MODEL }}\", \"messages\": [ { \"role\": \"system\", \"content\": \"Extract invoice data from the provided text. Respond ONLY with valid JSON matching this exact schema: {\\\"vendor\\\": \\\"string\\\", \\\"invoice_number\\\": \\\"string\\\", \\\"date\\\": \\\"YYYY-MM-DD\\\", \\\"due_date\\\": \\\"YYYY-MM-DD\\\", \\\"subtotal\\\": number, \\\"tax\\\": number, \\\"total_amount\\\": number, \\\"currency\\\": \\\"string\\\", \\\"line_items\\\": [{\\\"description\\\": \\\"string\\\", \\\"quantity\\\": number, \\\"unit_price\\\": number, \\\"total\\\": number}]}. Use null for any field not found in the text.\" }, { \"role\": \"user\", \"content\": \"Invoice text:\\n{{ $json.text }}\" } ] }",
"options": {
"timeout": 30000
}
}
},
{
"id": "71c221b7-f8ea-4701-8ba3-0828a13c1562",
"name": "Parse Invoice JSON",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
672,
0
],
"parameters": {
"mode": "runOnceForAllItems",
"jsCode": "const raw = $input.first().json?.choices?.[0]?.message?.content ?? '';\nlet invoice = {};\ntry {\n const s = raw.replace(/```(?:json)?\\n?/g, '').trim();\n invoice = JSON.parse(s);\n} catch(e) {\n invoice = {\n vendor: null, invoice_number: null, date: null, due_date: null,\n subtotal: null, tax: null, total_amount: null, currency: null,\n line_items: [],\n _parse_error: `${e.message}: ${raw.slice(0, 200)}`\n };\n}\nreturn [{\n json: {\n ...invoice,\n processed_at: new Date().toISOString(),\n line_items_json: JSON.stringify(invoice.line_items ?? [])\n }\n}];"
}
},
{
"id": "d2daee40-b6b8-477b-8206-57fe66cac60c",
"name": "Append to Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
896,
0
],
"parameters": {
"resource": "sheet",
"operation": "append",
"documentId": {
"__rl": true,
"mode": "list",
"value": ""
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": ""
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"vendor": "={{ $json.vendor }}",
"invoice_number": "={{ $json.invoice_number }}",
"date": "={{ $json.date }}",
"due_date": "={{ $json.due_date }}",
"subtotal": "={{ $json.subtotal }}",
"tax": "={{ $json.tax }}",
"total_amount": "={{ $json.total_amount }}",
"currency": "={{ $json.currency }}",
"line_items_json": "={{ $json.line_items_json }}",
"processed_at": "={{ $json.processed_at }}"
},
"schema": [
{
"id": "vendor",
"displayName": "vendor",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "invoice_number",
"displayName": "invoice_number",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "date",
"displayName": "date",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "due_date",
"displayName": "due_date",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "subtotal",
"displayName": "subtotal",
"required": false,
"defaultMatch": false,
"display": true,
"type": "number",
"canBeUsedToMatch": false
},
{
"id": "tax",
"displayName": "tax",
"required": false,
"defaultMatch": false,
"display": true,
"type": "number",
"canBeUsedToMatch": false
},
{
"id": "total_amount",
"displayName": "total_amount",
"required": false,
"defaultMatch": false,
"display": true,
"type": "number",
"canBeUsedToMatch": false
},
{
"id": "currency",
"displayName": "currency",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "line_items_json",
"displayName": "line_items_json",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "processed_at",
"displayName": "processed_at",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
}
]
}
}
},
{
"id": "8cb95155-6672-4a18-9d8a-1593dcf4b5bd",
"name": "Respond with Invoice",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
1120,
0
],
"parameters": {
"respondWith": "json",
"responseBody": "={{ $('Parse Invoice JSON').item.json }}"
}
}
],
"tags": [],
"meta": {
"aiBuilderAssisted": true,
"builderVariant": "mcp"
},
"description": "Receives PDF invoices via webhook, extracts text, sends to OpenRouter AI for structured parsing, appends to Google Sheets, and returns structured invoice JSON."
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Invoice Processing Workflow. Uses httpRequest, googleSheets. Webhook trigger; 6 nodes.
Source: https://github.com/VoTrongHoang-Dyor/n8n-workflow-templates/blob/main/workflows/invoice-processing/workflow.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.
Resume Screening & Behavioral Interviews with Gemini, Elevenlabs, & Notion ATS copy. Uses googleDrive, httpRequest, notion, formTrigger. Webhook trigger; 67 nodes.
[SANTOBET] FLUXO TODO - BACKUP. Uses googleSheets, httpRequest, googleSheetsTrigger. Webhook trigger; 57 nodes.
This workflow sends post-purchase review request emails for WooCommerce orders, stores expiring form links in Google Sheets, optionally shortens links with Dub.co and delays delivery, serves a hosted
FLUXO DISPARO DATA E HORA. Uses itemLists, googleSheets, httpRequest. Webhook trigger; 48 nodes.
This workflow allows you to accept online payments via YooKassa and log both orders and transactions in Google Sheets — all without writing a single line of code. It supports full payment flow: produc