AutomationFlowsData & Sheets › Invoice Processing Workflow

Invoice Processing Workflow

Invoice Processing Workflow. Uses httpRequest, googleSheets. Webhook trigger; 6 nodes.

Webhook trigger★★★★☆ complexity6 nodesHTTP RequestGoogle Sheets
Data & Sheets Trigger: Webhook Nodes: 6 Complexity: ★★★★☆ Added:

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 →

Download .json
{
  "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."
}
Pro

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 →

More Data & Sheets workflows → · Browse all categories →

Related workflows

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

Data & Sheets

Resume Screening & Behavioral Interviews with Gemini, Elevenlabs, & Notion ATS copy. Uses googleDrive, httpRequest, notion, formTrigger. Webhook trigger; 67 nodes.

Google Drive, HTTP Request, Notion +3
Data & Sheets

[SANTOBET] FLUXO TODO - BACKUP. Uses googleSheets, httpRequest, googleSheetsTrigger. Webhook trigger; 57 nodes.

Google Sheets, HTTP Request, Google Sheets Trigger
Data & Sheets

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

HTTP Request, Google Sheets, Email Send
Data & Sheets

FLUXO DISPARO DATA E HORA. Uses itemLists, googleSheets, httpRequest. Webhook trigger; 48 nodes.

Item Lists, Google Sheets, HTTP Request
Data & Sheets

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

Google Sheets, HTTP Request