{
  "name": "Automate timesheet to invoice conversion with OpenAI, Gmail & Google Workspace",
  "nodes": [
    {
      "id": "87ce7a42-e246-464a-b466-f5f1f6a8c118",
      "name": "Gmail Trigger",
      "type": "n8n-nodes-base.gmailTrigger",
      "position": [
        -7120,
        752
      ]
    },
    {
      "id": "0460076d-e261-420b-94c2-e20ab74c4be7",
      "name": "Split Binary Attachments",
      "type": "n8n-nodes-base.code",
      "position": [
        -6896,
        752
      ]
    },
    {
      "id": "797d4d1d-87a3-4106-b30d-425f2678f973",
      "name": "Loop: Process Each Attachment",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -6672,
        752
      ]
    },
    {
      "id": "af7850b0-e5c8-448b-b399-d67b663d88fa",
      "name": "Extract Timesheet Data (OpenAI)",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        -6128,
        768
      ]
    },
    {
      "id": "8c7aad74-4441-47c7-8156-a8a244d0bcd6",
      "name": "Get Customer Info From PO Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -5440,
        768
      ]
    },
    {
      "id": "cdcefae3-154c-4562-92b7-7506cdb271f3",
      "name": "Set Invoice Date & Due Date Days",
      "type": "n8n-nodes-base.set",
      "position": [
        -2464,
        272
      ]
    },
    {
      "id": "2c8cac15-9aec-464a-a820-7aefbe4f5618",
      "name": "Generate Sheet Name (Employee + Week Start to End Dates)",
      "type": "n8n-nodes-base.set",
      "position": [
        -2288,
        272
      ]
    },
    {
      "id": "6951b033-5547-4f23-a6b4-d140126e48af",
      "name": "Set: Invoice Range",
      "type": "n8n-nodes-base.set",
      "position": [
        -3264,
        640
      ]
    },
    {
      "id": "dd1191dc-d72d-400e-8ffd-32775b6927a8",
      "name": "If: File Already Exists?",
      "type": "n8n-nodes-base.if",
      "position": [
        -1504,
        976
      ]
    },
    {
      "id": "031af0bc-68ad-49c4-8902-54fb547d792d",
      "name": " If: Invoice Range is 15 Days?",
      "type": "n8n-nodes-base.if",
      "position": [
        -2912,
        640
      ]
    },
    {
      "id": "418a0a3c-4233-48b1-9e0f-31f1b0017fa7",
      "name": "Set: File Name from Start & End Based Date Range",
      "type": "n8n-nodes-base.set",
      "position": [
        -2608,
        928
      ]
    },
    {
      "id": "4c347d9a-c68a-499b-983e-a87a493ba18d",
      "name": " Merge: Combine Folder Search Results",
      "type": "n8n-nodes-base.merge",
      "position": [
        -1712,
        976
      ]
    },
    {
      "id": "a2701092-4d1a-48f3-b3bc-ade5bdfa00bb",
      "name": "Create New Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -1984,
        272
      ]
    },
    {
      "id": "f21db8a7-1a61-4046-abd6-6312203a37fa",
      "name": "Move Created Sheet to Final Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -1520,
        272
      ]
    },
    {
      "id": "7d293b58-2a76-4731-8103-5da138f1393e",
      "name": " Set: Row Data",
      "type": "n8n-nodes-base.set",
      "position": [
        -1328,
        272
      ]
    },
    {
      "id": "24eb5310-0fc2-47ef-a07f-5d54c39a987e",
      "name": " Sheets: Append Row",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -1152,
        272
      ]
    },
    {
      "id": "3eec4b39-7b40-4f50-bf13-0f7ac00ce342",
      "name": " Sheets: Final Append",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -784,
        272
      ]
    },
    {
      "id": "58c09537-c8c7-4e42-9691-90e6731c5838",
      "name": " Sheets: Create Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -1264,
        1280
      ]
    },
    {
      "id": "9570c6e8-5c5c-45e3-9760-2058ac45a9ee",
      "name": " Sheets: Append Row1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -528,
        1280
      ]
    },
    {
      "id": "b3073fc2-5281-4d75-8a58-647ffbfaa8dc",
      "name": "Extract Text from Attachment",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -6400,
        768
      ]
    },
    {
      "id": "340eb3c0-7e59-4da5-a753-a1c0111bba0c",
      "name": "Search: Client Invoices Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -5040,
        768
      ]
    },
    {
      "id": "2a853b8e-941b-4def-ab26-9ab7dcb7ba95",
      "name": "Search: Client Folder by Name",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -4832,
        768
      ]
    },
    {
      "id": "8e38f87b-707e-4e36-aa10-edb7067f6364",
      "name": "Search: File By Start Date Name",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -2176,
        816
      ]
    },
    {
      "id": "20d3361a-0e06-4f7d-af7a-84dd56e50ed5",
      "name": "Search: File By End Date Name",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -2160,
        1040
      ]
    },
    {
      "id": "c7b82a70-5d5b-4448-85ee-2e6f9f420296",
      "name": "Drive: Move Sheet To Final Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -912,
        1280
      ]
    },
    {
      "id": "62b6b38c-d93a-4b31-bbaf-a14b80ed8de1",
      "name": "Set: Empty Row Structure",
      "type": "n8n-nodes-base.set",
      "position": [
        -736,
        1280
      ]
    },
    {
      "id": "a17b04d9-705c-4ed9-acc3-d4b971ad790d",
      "name": "Set: Spreadsheet  (ID & Name)",
      "type": "n8n-nodes-base.set",
      "position": [
        -336,
        1280
      ]
    },
    {
      "id": "058a5baf-6f32-4822-ae06-d0c67f644ca6",
      "name": "Append: Final Row to Existing Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -32,
        1280
      ]
    },
    {
      "id": "d546cefb-f8cb-4385-81f7-02b08f627e13",
      "name": "Check if Year Folder Exists",
      "type": "n8n-nodes-base.if",
      "position": [
        -3664,
        656
      ]
    },
    {
      "id": "a5141e72-4f6c-4334-aac7-1e836af18b3c",
      "name": "Create Client Name Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -4384,
        912
      ]
    },
    {
      "id": "7384fb2c-b9a7-4054-a751-1b872d581848",
      "name": "Check Client Name Folder",
      "type": "n8n-nodes-base.if",
      "position": [
        -4592,
        768
      ]
    },
    {
      "id": "64995379-b50c-4412-92fc-02101b06bd18",
      "name": "Search: Employee Name Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -4320,
        544
      ]
    },
    {
      "id": "43f1592f-8461-433d-bb8a-4533373328bb",
      "name": "Check Employee Name Folder",
      "type": "n8n-nodes-base.if",
      "position": [
        -4128,
        544
      ]
    },
    {
      "id": "18aedc4f-54af-4531-9bb5-0462fcba562c",
      "name": "Create Employee Name Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -4080,
        912
      ]
    },
    {
      "id": "d394c96e-5a7b-4fc1-864d-d3b661133347",
      "name": "Search: Year Folder ",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -3856,
        528
      ]
    },
    {
      "id": "c3ae7f46-6e1a-4e04-a983-1c67840ef848",
      "name": "Create Year Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -3840,
        912
      ]
    },
    {
      "id": "b4ac8818-d950-4f59-b320-40e6ae181170",
      "name": "Create Current Year Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -3472,
        928
      ]
    },
    {
      "id": "ac3907f4-1e21-44bc-8707-0196c641264c",
      "name": "Set Timesheet JSON Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        -5696,
        768
      ]
    },
    {
      "id": "a9f7449f-e724-451f-8e6b-330104591223",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -6480,
        608
      ],
      "parameters": {
        "width": 304,
        "height": 304,
        "content": "## OCR extraction\nSends each attachment to the OCR API and returns plain text. This turns PDFs and images into machine readable text before AI parsing.\n"
      }
    },
    {
      "id": "98a98ac1-856a-4f5d-97d2-645375e4874f",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2512,
        128
      ],
      "parameters": {
        "width": 480,
        "height": 272,
        "content": "## Build invoice dates\nCalculates the invoice date and due date using the timesheet's week end date and PO due date rules. Outputs clean fields used to name and populate the invoice sheet.\n"
      }
    },
    {
      "id": "3b7abbc0-cd8e-4cd8-b34f-3fd2c2d052d5",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3568,
        864
      ],
      "parameters": {
        "width": 304,
        "height": 224,
        "content": "## create new year folder"
      }
    },
    {
      "id": "ec7a2360-1081-4527-9456-a0068c0f56a2",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2016,
        128
      ],
      "parameters": {
        "width": 448,
        "height": 256,
        "content": "## Create invoice sheet\nGenerates the sheet name, creates a new Google Sheet, updates its timezone, and moves it into the correct year folder based on the employee and date range.\n"
      }
    },
    {
      "id": "db62fec3-3831-478c-be6d-0ea4b132ad45",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1200,
        160
      ],
      "parameters": {
        "width": 640,
        "height": 256,
        "content": "## Write invoice row\nInitializes the row structure, maps customer and timesheet fields, and appends the invoice row into the newly created sheet to complete the entry.\n"
      }
    },
    {
      "id": "19828bb4-04c0-4b73-a56e-0befdab104f7",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1760,
        816
      ],
      "parameters": {
        "width": 400,
        "height": 336,
        "content": "## Decide reuse or create sheet\nChecks the merged search results. If a matching sheet exists, route to append a new invoice row. If nothing is found, route to create a fresh sheet for this employee an"
      }
    },
    {
      "id": "4030985b-8b57-40ae-a6a1-864d4def5ace",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -7152,
        608
      ],
      "parameters": {
        "width": 624,
        "height": 320,
        "content": "## Email intake and loop\nListens to Gmail for unread timesheet emails, splits all attachments, and processes each one in a loop so multiple timesheets in the same email are handled independently.\n"
      }
    },
    {
      "id": "b71ffe42-26c6-42b5-850a-835de9182923",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -8240,
        64
      ],
      "parameters": {
        "width": 976,
        "height": 992,
        "content": "Timesheet to Invoice Automation\n\n## How it works\nThe workflow automates converting emailed timesheets into organized invoice sheets.\n\n**1. Email intake**\nPulls unread Gmail messages with timesheet att"
      }
    },
    {
      "id": "fbf95800-fcc9-4776-8141-68dd2c886f0f",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -5536,
        608
      ],
      "parameters": {
        "width": 352,
        "height": 320,
        "content": "## Customer and PO lookup\nLooks up the sender in the Customer POs sheet and pulls account number, PO number, item name, folder name, invoice range, and due date offset that drive the invoice logic.\n"
      }
    },
    {
      "id": "6c262c74-70ca-403d-9887-73fd8630c5bc",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -6144,
        608
      ],
      "parameters": {
        "width": 352,
        "height": 304,
        "content": "## AI timesheet parsing\nOpenAI reads the timesheet text and extracts employee name, client name, week start and end dates, total hours, and current year into clean JSON fields for later use.\n"
      }
    },
    {
      "id": "d1dd448a-edfa-4a62-ad33-8a3e4fdbf605",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -5104,
        624
      ],
      "parameters": {
        "width": 464,
        "height": 304,
        "content": "## Client folder discovery\nSearch Client Invoices folder, finds or creates the client level folder based on the timesheet client name and PO configuration.\n"
      }
    },
    {
      "id": "1eb23006-723d-4afb-8be2-85702d63c6e7",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4384,
        432
      ],
      "parameters": {
        "width": 704,
        "height": 256,
        "content": "## ## File naming and search\n searches Drive for existing sheets with the employee and if it exist get that year's folder"
      }
    },
    {
      "id": "feec06a8-cd41-4a32-88cd-87738b916622",
      "name": "Sticky Note12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4416,
        816
      ],
      "parameters": {
        "width": 704,
        "height": 224,
        "content": "## Create new \ncreate new client name, employee and year named folder\n"
      }
    },
    {
      "id": "5f10a262-9c27-4002-b637-31098a8b73da",
      "name": "HTTP Request(new sheet)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1744,
        272
      ]
    },
    {
      "id": "7ed7ba40-2732-48f3-87eb-5374d850e38e",
      "name": "Sticky Note14",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2624,
        704
      ],
      "parameters": {
        "width": 784,
        "height": 544,
        "content": "## Build file names and search\nGenerates start based and end based file names from employee and week dates, then searches Google Drive for existing spreadsheets that match either name. Both search res"
      }
    },
    {
      "id": "5ce8ea5e-3b9b-4800-8b6a-f43d3f1d03b3",
      "name": "Sticky Note15",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1328,
        1136
      ],
      "parameters": {
        "width": 528,
        "height": 288,
        "content": "## Create invoice sheet\nGenerates the sheet name, creates a new Google Sheet, updates its timezone, and moves it into the correct year folder based on the employee and date range.\n"
      }
    },
    {
      "id": "9c95568f-4f66-428a-a4e4-deae2201b462",
      "name": "HTTP Request1(create sheet)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1088,
        1280
      ]
    },
    {
      "id": "a04d99d7-e658-4738-9d3b-99b921d26689",
      "name": "Sticky Note16",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -560,
        1120
      ],
      "parameters": {
        "width": 752,
        "height": 288,
        "content": "## Write invoice row\n append invoice rows\nFor new sheets, creates the sheet, sets timezone, moves it to the correct year folder, prepares an empty row structure, and writes the first invoice row. For "
      }
    }
  ],
  "connections": {
    "Gmail Trigger": {
      "main": [
        [
          {
            "node": "Split Binary Attachments",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    " Set: Row Data": {
      "main": [
        [
          {
            "node": " Sheets: Append Row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create New Sheet": {
      "main": [
        [
          {
            "node": "HTTP Request(new sheet)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Year Folder": {
      "main": [
        [
          {
            "node": "Check if Year Folder Exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set: Invoice Range": {
      "main": [
        [
          {
            "node": " If: Invoice Range is 15 Days?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    " Sheets: Append Row": {
      "main": [
        [
          {
            "node": " Sheets: Final Append",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    " Sheets: Append Row1": {
      "main": [
        [
          {
            "node": "Set: Spreadsheet  (ID & Name)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search: Year Folder ": {
      "main": [
        [
          {
            "node": "Check if Year Folder Exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    " Sheets: Create Sheet": {
      "main": [
        [
          {
            "node": "HTTP Request1(create sheet)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    " Sheets: Final Append": {
      "main": [
        [
          {
            "node": "Loop: Process Each Attachment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request(new sheet)": {
      "main": [
        [
          {
            "node": "Move Created Sheet to Final Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Client Name Folder": {
      "main": [
        [
          {
            "node": "Search: Employee Name Folder",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create Client Name Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If: File Already Exists?": {
      "main": [
        [
          {
            "node": "Append: Final Row to Existing Sheet",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": " Sheets: Create Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set: Empty Row Structure": {
      "main": [
        [
          {
            "node": " Sheets: Append Row1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Binary Attachments": {
      "main": [
        [
          {
            "node": "Loop: Process Each Attachment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Client Name Folder": {
      "main": [
        [
          {
            "node": "Create Employee Name Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Timesheet JSON Fields": {
      "main": [
        [
          {
            "node": "Get Customer Info From PO Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Employee Name Folder": {
      "main": [
        [
          {
            "node": "Search: Year Folder ",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create Employee Name Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Current Year Folder": {
      "main": [
        [
          {
            "node": "Set: Invoice Range",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if Year Folder Exists": {
      "main": [
        [
          {
            "node": "Set: Invoice Range",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create Current Year Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Employee Name Folder": {
      "main": [
        [
          {
            "node": "Create Year Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request1(create sheet)": {
      "main": [
        [
          {
            "node": "Drive: Move Sheet To Final Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Text from Attachment": {
      "main": [
        [
          {
            "node": "Extract Timesheet Data (OpenAI)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search: Employee Name Folder": {
      "main": [
        [
          {
            "node": "Check Employee Name Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop: Process Each Attachment": {
      "main": [
        [],
        [
          {
            "node": "Extract Text from Attachment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search: Client Folder by Name": {
      "main": [
        [
          {
            "node": "Check Client Name Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search: File By End Date Name": {
      "main": [
        [
          {
            "node": " Merge: Combine Folder Search Results",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Set: Spreadsheet  (ID & Name)": {
      "main": [
        [
          {
            "node": "Append: Final Row to Existing Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    " If: Invoice Range is 15 Days?": {
      "main": [
        [
          {
            "node": "Set Invoice Date & Due Date Days",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Set: File Name from Start & End Based Date Range",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search: Client Invoices Folder": {
      "main": [
        [
          {
            "node": "Search: Client Folder by Name",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Timesheet Data (OpenAI)": {
      "main": [
        [
          {
            "node": "Set Timesheet JSON Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Customer Info From PO Sheet": {
      "main": [
        [
          {
            "node": "Search: Client Invoices Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search: File By Start Date Name": {
      "main": [
        [
          {
            "node": " Merge: Combine Folder Search Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Invoice Date & Due Date Days": {
      "main": [
        [
          {
            "node": "Generate Sheet Name (Employee + Week Start to End Dates)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Drive: Move Sheet To Final Folder": {
      "main": [
        [
          {
            "node": "Set: Empty Row Structure",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Move Created Sheet to Final Folder": {
      "main": [
        [
          {
            "node": " Set: Row Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append: Final Row to Existing Sheet": {
      "main": [
        [
          {
            "node": "Loop: Process Each Attachment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    " Merge: Combine Folder Search Results": {
      "main": [
        [
          {
            "node": "If: File Already Exists?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set: File Name from Start & End Based Date Range": {
      "main": [
        [
          {
            "node": "Search: File By Start Date Name",
            "type": "main",
            "index": 0
          },
          {
            "node": "Search: File By End Date Name",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Sheet Name (Employee + Week Start to End Dates)": {
      "main": [
        [
          {
            "node": "Create New Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}