AutomationFlowsAI & RAG › 2-Utility-SaveInvoices_template

2-Utility-SaveInvoices_template

2-Utility-SaveInvoices_template. Uses agent, googleSheets, httpRequest, googleDrive. Scheduled trigger; 26 nodes.

Cron / scheduled trigger★★★★☆ complexityAI-powered26 nodesAgentGoogle SheetsHttp RequestGoogle DriveGmailLm Chat Open RouterFtp
AI & RAG Trigger: Cron / scheduled Nodes: 26 Complexity: ★★★★☆ AI nodes: yes

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
{
  "name": "2-Utility-SaveInvoices_template",
  "nodes": [
    {
      "parameters": {
        "promptType": "define",
        "text": "=- You must respond ONLY with valid raw rendered JSON.\n- Do NOT include the word \"json\".\n- Do NOT include the word \"```json\".\n- Do NOT use triple backticks or markdown formatting.\n- Do NOT wrap the response in any key like \"output\".\n- Do NOT write anything starting at output directly start with valid root-level JSON.\n- Only respond with a valid, root-level JSON object.\n- Do NOT skip any line item. Continue extracting all line items until the sum of all line_total values exactly equals the total sale amount extracted from the invoice. This verification ensures that all items are fully extracted and no entries are missed. If the totals do not match, keep parsing and extracting additional line items until they do. Only then stop.\n\nText to convert: {{ $json.text }}",
        "options": {
          "systemMessage": "You are a document parsing assistant designed to extract structured data from invoice PDFs for automated uploading and validation in a financial system.\n\nExtract the following fields from the invoice text:\n\ninvoice_number: Extract from the 'Invoice No' field.\n\nvendor_name: Company name issuing the invoice.\n\ninvoice_date: Format as DD/MM/YYYY.\n\npo_number: Extract the PO number or return null if not found.\n\npo_date: Extract the PO date in DD/MM/YYYY format or return null if not found.\n\ntotal_amount: Extract the invoice total as a float.\n\ntax_details: Include total CGST, total SGST.\n\nline_items: List of all items in the invoice. For each item, extract:\n\n  Serial No.: Item Serial No. In invoice.\n\n  code: The TWW word and its postfix only (e.g., TWW, TWW-Cover, TWW-HPCN). Do not include HSN code or numbers. This field must always be present.\n\n  description: Item description, never include HSN code of product in product description.\n\n  last character: This is a single word/character string found just after or around the line item, typically at the end of the price line or just on the next line. It will never be a number, HSN code, GST %, or unit (like PCS). Examples: G, C, S, 5C, .C If nothing is present (only digits or blank), return \"\". Check the next 1\u20132 lines after each item if it's not found on the same line.\n\n  quantity: Quantity value.\n\n  unit_price: Price per unit.\n\n  line_total: Total price for the line.\n\n  hsn_code: HSN code of the item.\n\n  cgst: Only extract the CGST percentage (e.g., 9%, 6%) as written in the invoice. Do not calculate based on line total.\n\n  sgst: Only extract the SGST percentage (e.g., 9%, 6%) as written in the invoice. Do not calculate based on line total.\n\nImportant: Double-check that all line items are extracted without omission.\n\nDo NOT skip any line item. Continue extracting all line items until the sum of all line_total values exactly equals the total_amount extracted from the invoice. This verification ensures that all items are fully extracted and no entries are missed. If the totals do not match, keep parsing and extracting additional line items until they do. Only then stop."
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 2.2,
      "position": [
        2736,
        672
      ],
      "id": "8740476c-9d06-414b-b68a-828df048b29e",
      "name": "AI_Agent-fields"
    },
    {
      "parameters": {
        "jsCode": "const output = $input.first().json.output;\nlet raw = output.result || output.completion || output.text || JSON.stringify(output);\n\n// Step 1: Remove backticks if present\nraw = raw.trim();\nif (raw.startsWith(\"```json\")) {\n  raw = raw.replace(/^```json\\s*/, '').replace(/```$/, '').trim();\n} else if (raw.startsWith(\"```\")) {\n  raw = raw.replace(/^```\\s*/, '').replace(/```$/, '').trim();\n}\n\n// Step 2: Find full JSON block from first { to last }\nconst start = raw.indexOf('{');\nconst end = raw.lastIndexOf('}');\nif (start === -1 || end === -1 || end <= start) {\n  return [{\n    json: {\n      error: \"No valid JSON block found\",\n      raw_output: raw\n    }\n  }];\n}\n\nlet jsonCandidate = raw.substring(start, end + 1).trim();\n\n// Step 3: Unescape characters\njsonCandidate = jsonCandidate\n  .replace(/\\\\n/g, '')\n  .replace(/\\\\t/g, '')\n  .replace(/\\\\\"/g, '\"')\n  .replace(/\\\\'/g, \"'\")\n  .replace(/\\\\\\\\/g, '\\\\');\n\n// Step 4: Parse JSON safely\ntry {\n  let parsed = JSON.parse(jsonCandidate);\n\n  // Only double-parse if it looks like stringified JSON\n  if (typeof parsed === \"string\" && parsed.trim().startsWith('{') && parsed.trim().endsWith('}')) {\n    parsed = JSON.parse(parsed);\n  }\n\n  return [{ json: parsed }];\n} catch (e) {\n  return [{\n    json: {\n      error: \"JSON parsing failed\",\n      raw_output: raw,\n      attempted_extraction: jsonCandidate,\n      message: e.message\n    }\n  }];\n}"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3024,
        672
      ],
      "id": "f6d0666f-ba52-4ce9-a8bb-b6ea735427ca",
      "name": "Code_extractFields"
    },
    {
      "parameters": {
        "authentication": "serviceAccount",
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "1-qkYalPWAugIUGqsgR8_gU15CHkzsqQfCVB793i8Ku8",
          "mode": "list",
          "cachedResultName": "n8n",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1-qkYalPWAugIUGqsgR8_gU15CHkzsqQfCVB793i8Ku8/edit?usp=drivesdk"
        },
        "sheetName": {
          "__rl": true,
          "value": 1842419144,
          "mode": "list",
          "cachedResultName": "Fatture-luce",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1-qkYalPWAugIUGqsgR8_gU15CHkzsqQfCVB793i8Ku8/edit#gid=1842419144"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Fornitore": "={{ $json.vendor_name }}",
            "Importo": "={{ $json.total_amount }}",
            "Data": "={{ $json.invoice_date }}",
            "Tipo": "={{ $json.line_items[0].description }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "Fornitore",
              "displayName": "Fornitore",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Tipo",
              "displayName": "Tipo",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Data",
              "displayName": "Data",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Importo",
              "displayName": "Importo",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        3216,
        672
      ],
      "id": "e308190d-ab88-430c-ac06-5835edbf0d7f",
      "name": "GoogleSheets_save"
    },
    {
      "parameters": {
        "url": "={{ $json.webContentLink }}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2352,
        208
      ],
      "id": "3c478faf-ec04-4da4-a7d4-34a208689ab0",
      "name": "downloadFile"
    },
    {
      "parameters": {
        "inputDataFieldName": "={{ $binary.keys()[0] }}",
        "name": "={{ $json.from.value[0].name}}-{{ $json.date }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "folderId": {
          "__rl": true,
          "value": "=YOUR_ID",
          "mode": "id"
        },
        "options": {}
      },
      "id": "cb8e5ab0-cb78-4c18-88cc-6301ce5a00db",
      "name": "GoogleDrive-upload-file",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        2144,
        208
      ],
      "typeVersion": 3
    },
    {
      "parameters": {
        "operation": "get",
        "messageId": "={{ $node[\"Get many messages\"].json.id }}",
        "simple": false,
        "options": {
          "downloadAttachments": true
        }
      },
      "id": "4966a033-d088-4ef1-88d8-b338b3a912b2",
      "name": "Gmail-Get_Invoice",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1936,
        208
      ],
      "typeVersion": 2.1
    },
    {
      "parameters": {
        "operation": "delete",
        "messageId": "={{ $('Get many messages').item.json.id }}"
      },
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        3168,
        208
      ],
      "id": "b45ff76f-eab8-4989-9c0f-3e965b6b2aee",
      "name": "Delete a message"
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "triggerAtMinute": 25
            }
          ]
        }
      },
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        672,
        192
      ],
      "id": "7f91a088-b772-4cf0-9460-3d8b1f907286",
      "name": "Schedule Trigger"
    },
    {
      "parameters": {
        "operation": "getAll",
        "simple": false,
        "filters": {
          "receivedAfter": "={{ new Date(Date.now() - 60 * 60 * 1000).toISOString() }}",
          "sender": "SENDER_EMAIL_ADDRESS"
        },
        "options": {
          "downloadAttachments": true
        }
      },
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        928,
        192
      ],
      "id": "06bbcd36-63f8-4675-8844-50d0f028efa2",
      "name": "Get many messages"
    },
    {
      "parameters": {
        "content": "## Automated Invoice Archiving - overview\n\nThis workflow automatically collects invoice emails from your ISP/utility provider, saves attached PDFs to Google Drive (and optionally SFTP), extracts key invoice data using AI, and logs them into Google Sheets.\n\nRead: [Full setup Guide](https://paoloronco.it/n8n-template-automated-invoice-archiving/)\n\n### How it Works (High-Level)\n\n1. **Trigger** \u2013 Runs at your chosen interval.\n2. **Email Filter** \u2013 Fetches only messages from the sender you specify and only if they include PDF attachments.\n3. **Download Invoice** \u2013 Retrieves the email and PDF file.\n4. **Save to Drive** \u2013 Uploads the PDF to a selected Google Drive folder.\n    (Optional) SFTP Upload \u2013 Sends a copy to your server.\n5. **Extract Text** \u2013 Converts the PDF to text.\n6. **AI Parsing** \u2013 Extracts invoice fields (vendor, date, total, line items, taxes, etc.).\n7. **Cleanup** (Optional) \u2013 Delete email and/or Google Drive temp file.\n8. **Append to Sheets** \u2013 Saves selected fields into your Google Sheet.\n\n### Tips\n\n- Works best with text-based PDFs.\n- SFTP, Gmail deletion, and Drive deletion are optional.\n- You can use different senders for different providers.\n- Sheets can be used to chart or monitor consumption over time.\n\n### Important\n\nInvoices may contain sensitive data.\nUse secure storage, APIs, and accounts.",
        "height": 720,
        "width": 752
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -128,
        -48
      ],
      "id": "b8777576-41e7-46c0-86b8-7af73f30ab5c",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "operation": "pdf",
        "options": {}
      },
      "type": "n8n-nodes-base.extractFromFile",
      "typeVersion": 1,
      "position": [
        2560,
        416
      ],
      "id": "22841f63-b10a-48bd-bf8e-fbd51a65beac",
      "name": "Extract from File1"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "typeVersion": 1,
      "position": [
        2736,
        816
      ],
      "id": "f34ed231-eb4e-4c6d-afe4-55002ec51d8f",
      "name": "OpenRouter Chat Model1"
    },
    {
      "parameters": {
        "operation": "deleteFile",
        "fileId": {
          "__rl": true,
          "value": "={{ $('GoogleDrive-upload-file').item.json.id }}",
          "mode": "id"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleDrive",
      "typeVersion": 3,
      "position": [
        2944,
        208
      ],
      "id": "f544762a-4d82-4638-99f5-dd16cf233bc0",
      "name": "Delete a file1"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "87e927b3-4f28-4843-b2d0-cf7269437fca",
              "operator": {
                "type": "object",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $('Get many messages').item.binary}}",
              "rightValue": ""
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "95b99314-b4c1-4b3b-af12-ac5ee64cff06",
      "name": "Filter-contains_attachment",
      "type": "n8n-nodes-base.filter",
      "position": [
        1168,
        192
      ],
      "typeVersion": 2.2
    },
    {
      "parameters": {
        "content": "### SECTION 1 Trigger\n\nRuns the workflow on a schedule you choose. Adjust interval as needed (hourly, daily, etc.).",
        "height": 400,
        "color": 7
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        640,
        -48
      ],
      "id": "5a407aa3-d3d1-4f45-9c4a-88a5dd0cfdb7",
      "name": "Sticky Note2"
    },
    {
      "parameters": {
        "content": "### SECTION 2.1 \u2014 Email Intake & Attachment filtering\n\nFetches messages from a specific sender and filters only emails containing PDF attachments.\n\n**Setup:**\nIn **Gmail \u2192 Get Many Messages**, enter the sender email that sends you invoices.\n\nConfigure your Gmail OAuth2 account: [\ud83d\udd17 Gmail Node Docs](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.gmail/)",
        "height": 400,
        "width": 560,
        "color": 7
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        896,
        -48
      ],
      "id": "163f9fb4-9dc1-4e92-83ee-ecc3e1510585",
      "name": "Sticky Note3"
    },
    {
      "parameters": {
        "content": "### SECTION 3 \u2014 Download & Storage\n\nDownloads the invoice PDF and saves it to Google Drive. You can optionally upload a copy to your FTP/SFTP server.\n\n**Google Drive:**\nConnect your Drive account: [\ud83d\udd17 Google Drive Docs](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.googledrive/)\nInsert the **Folder ID** where invoices will be stored.\n\n**FTP/SFTP (optional):**\nSet up your FTP/SFTP credentials: [\ud83d\udd17 FTP Node Docs](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.ftp/)\nIn **PATH**, enter the directory where files should be saved. Leave other fields unchanged.\n",
        "height": 416,
        "width": 816,
        "color": 7
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        2096,
        -48
      ],
      "id": "31b2113c-b7f7-45f2-b277-1b3800c8c68d",
      "name": "Sticky Note4"
    },
    {
      "parameters": {
        "content": "### SECTION 4 \u2014 PDF Text Extraction\n\nConverts the PDF into text before sending it to the AI model. OCR not required unless the PDF is image-only.",
        "width": 896,
        "color": 7
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1792,
        400
      ],
      "id": "c633ca42-aeb2-42d9-9a53-6f64ed13a5ad",
      "name": "Sticky Note5"
    },
    {
      "parameters": {
        "content": "### SECTION 5 \u2014 AI Parsing\n\nThe AI Agent extracts structured data (date, vendor, amount, items). The Code node cleans the JSON.\n\n**Setup**\n Enter your LLM provider API key (OpenRouter/OpenAI).\n Ensure you have available credits.\n Select your preferred model (GPT-4.1, Llama 3, etc.).\n No additional configuration needed.\n\n\n\n",
        "height": 544,
        "width": 448,
        "color": 7
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        2704,
        400
      ],
      "id": "08b97c66-9033-4b59-aa9f-2be21f09fee6",
      "name": "Sticky Note6"
    },
    {
      "parameters": {
        "content": "### SECTION 6 - GoogleSheets Logging\n\n**Setup**\nConnect your Google Sheets Service Account.\nSet **Document ID** and **Sheet Name**.\nCreate these columns in the first row:\n\n* **Vendor**\n* **Type**\n* **Date**\n* **Amount**\n\n\n\n",
        "height": 544,
        "width": 352,
        "color": 7
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        3168,
        400
      ],
      "id": "34bfa6d9-f7ea-4acb-95f6-1c57bc6a89d2",
      "name": "Sticky Note7"
    },
    {
      "parameters": {
        "jsCode": "return $input.all().map(item => {\n  if (!item.binary) return item;\n\n  const key = Object.keys(item.binary)[0];         // prende il primo binary field\n  const bin = item.binary[key];\n\n  let n = item.json.name || bin?.fileName || 'invoice';\n\n  n = n.replace(/[\\x00-\\x1F\\x7F]/g, '');\n  n = n.replace(/\\.\\d+Z$/, '');\n  n = n.replace(/[:<>\"/\\\\|?*]/g, '-');\n  n = n.replace(/\\s+/g, ' ').replace(/[. ]+$/, '');\n  if (!n.toLowerCase().endsWith('.pdf')) n += '.pdf';\n\n  item.binary[key].fileName = n;\n  return item;\n});"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2560,
        208
      ],
      "id": "b464e077-d9e3-4100-b6f5-71c5c3117f9a",
      "name": "Code in JavaScript"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        1680,
        192
      ],
      "id": "7f948036-e8a3-4c33-a934-c0e6dcdc5bc6",
      "name": "If"
    },
    {
      "parameters": {
        "authentication": "serviceAccount",
        "documentId": {
          "__rl": true,
          "value": "1-qkYalPWAugIUGqsgR8_gU15CHkzsqQfCVB793i8Ku8",
          "mode": "list",
          "cachedResultName": "n8n",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1-qkYalPWAugIUGqsgR8_gU15CHkzsqQfCVB793i8Ku8/edit?usp=drivesdk"
        },
        "sheetName": {
          "__rl": true,
          "value": "=12345678",
          "mode": "id"
        },
        "filtersUI": {
          "values": [
            {
              "lookupColumn": "uniqueKey",
              "lookupValue": "={{ $('Get many messages').item.json.id }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        1520,
        192
      ],
      "id": "c993184f-56b6-4c05-9868-963917d2dea7",
      "name": "Check: Message already processed",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "content": "### Section 3: Check if already existing\n\nPrevents duplicate processing of the same email.\nThis section checks whether the current Gmail message has already been processed by looking up its Gmail message ID in a Google Sheets registry.\n\nConfiguration\n* Set the Google Sheets document and sheet name.\n* Ensure the sheet has a uniqueKey column containing Gmail message IDs.\n",
        "height": 416,
        "width": 416,
        "color": 7
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1472,
        -48
      ],
      "id": "9f7b972a-3ee1-4ba0-bb35-145aef6efbef",
      "name": "Sticky Note8"
    },
    {
      "parameters": {
        "content": "### Section 2.2\n\nGet attachment from Gmail \n(binary file)",
        "height": 416,
        "width": 176,
        "color": 7
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1904,
        -48
      ],
      "id": "08bbcd5d-dc15-48bd-9d29-a6bb8316364b",
      "name": "Sticky Note9"
    },
    {
      "parameters": {
        "protocol": "sftp",
        "operation": "upload",
        "path": "=PATH/PATH/{{ $binary[Object.keys($binary)[0]].fileName }}"
      },
      "type": "n8n-nodes-base.ftp",
      "typeVersion": 1,
      "position": [
        2752,
        208
      ],
      "id": "114f1c8c-c5de-4f09-ab00-53acff498026",
      "name": "FTP-upload"
    }
  ],
  "connections": {
    "AI_Agent-fields": {
      "main": [
        [
          {
            "node": "Code_extractFields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code_extractFields": {
      "main": [
        [
          {
            "node": "GoogleSheets_save",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "downloadFile": {
      "main": [
        [
          {
            "node": "Extract from File1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GoogleDrive-upload-file": {
      "main": [
        [
          {
            "node": "downloadFile",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail-Get_Invoice": {
      "main": [
        [
          {
            "node": "GoogleDrive-upload-file",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Get many messages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get many messages": {
      "main": [
        [
          {
            "node": "Filter-contains_attachment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract from File1": {
      "main": [
        [
          {
            "node": "AI_Agent-fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "AI_Agent-fields",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Delete a file1": {
      "main": [
        [
          {
            "node": "Delete a message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter-contains_attachment": {
      "main": [
        [
          {
            "node": "Check: Message already processed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "FTP-upload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "FTP-upload": {
      "main": [
        [
          {
            "node": "Delete a file1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "54ea6eaf-4f29-4b70-9b79-20cf3a309300",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "hAr5yxUjH6GnWhRq",
  "tags": [
    {
      "name": "Utility",
      "id": "gZvMl56PRMiUM0GB",
      "updatedAt": "2026-01-13T18:54:25.559Z",
      "createdAt": "2026-01-13T18:54:25.559Z"
    },
    {
      "name": "Mail",
      "id": "vghJqYF0cZvWjgCI",
      "updatedAt": "2026-01-13T18:54:25.550Z",
      "createdAt": "2026-01-13T18:54:25.550Z"
    },
    {
      "name": "PROD",
      "id": "r7fcfwCl5k0mTYj8",
      "updatedAt": "2026-01-13T18:54:59.745Z",
      "createdAt": "2026-01-13T18:54:59.745Z"
    },
    {
      "name": "creator-published",
      "id": "PlxhyZPXjXMiEkoD",
      "updatedAt": "2026-01-13T18:54:59.705Z",
      "createdAt": "2026-01-13T18:54:59.705Z"
    }
  ]
}

About this workflow

2-Utility-SaveInvoices_template. Uses agent, googleSheets, httpRequest, googleDrive. Scheduled trigger; 26 nodes.

Source: https://github.com/paoloronco/n8n-templates/blob/main/free-templates/2-SaveInvoices/workflow.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →