{
  "name": "Process vendor invoices with UploadToURL, AWS Textract, and Google Sheets",
  "nodes": [
    {
      "id": "d1ba6277-b3f7-487b-a77b-ff5f2c2d1a6d",
      "name": "📋 Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -64,
        64
      ],
      "parameters": {
        "width": 560,
        "height": 532,
        "content": "## invoice data with UploadToURL, AWS Textract, and Google Sheets\nThe Problem: Manually keying data from paper or PDF invoices into spreadsheets is slow and prone to human error.\nThe Solution: An auto"
      }
    },
    {
      "id": "6e2da2c6-3c46-44f8-bb2d-90a50d4b780f",
      "name": "Section 1 — Intake",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        640,
        608
      ],
      "parameters": {
        "width": 1048,
        "height": 579,
        "content": "## 1 — Intake & upload\n\n**Webhook → Validate → Has Remote URL? → Upload to URL (×2) → Extract CDN URL**\n\nAccepts `POST` with `fileUrl` or binary PDF/image. Validates file extension against allowlist ("
      }
    },
    {
      "id": "f64ef54b-433f-4c77-8668-b851e939466f",
      "name": "Section 2 — OCR",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1728,
        560
      ],
      "parameters": {
        "width": 440,
        "height": 621,
        "content": "## 2 — OCR extraction\n\n**AWS Textract → Parse & Validate Extracted Data**\n\nTextract runs `AnalyzeExpense` on the CDN URL and returns structured expense fields. The parse node extracts: vendor name, in"
      }
    },
    {
      "id": "5f416608-8948-4a18-8282-fa11699ac19b",
      "name": "Section 3 — Sheets",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2192,
        560
      ],
      "parameters": {
        "width": 872,
        "height": 749,
        "content": "## 3 — Duplicate check & Sheets write\n\n**Search Sheets → IF Duplicate? → Append Row or Update Row**\n\nSearches the Google Sheet for an existing row matching the invoice number before writing. Duplicate"
      }
    },
    {
      "id": "a93a57c0-2fbe-478c-bb8f-8834c2614eb2",
      "name": "Section 4 — Notify",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3136,
        512
      ],
      "parameters": {
        "width": 744,
        "height": 783,
        "content": "## 4 — Notification & response\n\n**Slack → Build Response → Respond to Webhook**\n\nSlack posts to the finance channel with vendor, amount, due date, status badge, and a direct link to the CDN file. Webh"
      }
    },
    {
      "id": "387f9899-ab39-45c9-962b-e14346742684",
      "name": "Webhook - Receive Invoice",
      "type": "n8n-nodes-base.webhook",
      "position": [
        672,
        912
      ]
    },
    {
      "id": "72b70229-44fe-466e-b905-e9d5ef31a89a",
      "name": "Validate Payload",
      "type": "n8n-nodes-base.code",
      "position": [
        880,
        912
      ]
    },
    {
      "id": "7baa95a9-7c6f-4087-a216-07d673641e1a",
      "name": "Has Remote URL?",
      "type": "n8n-nodes-base.if",
      "position": [
        1104,
        912
      ]
    },
    {
      "id": "1dac0a61-337e-447b-9365-1a7d351c7c8b",
      "name": "Upload to URL - Remote",
      "type": "n8n-nodes-uploadtourl.uploadToUrl",
      "position": [
        1328,
        784
      ]
    },
    {
      "id": "43224235-9279-4ae6-939c-e110767e89d0",
      "name": "Upload to URL - Binary",
      "type": "n8n-nodes-uploadtourl.uploadToUrl",
      "position": [
        1328,
        1024
      ]
    },
    {
      "id": "5f4933ee-dce5-4f2c-8c4a-50134010e4ff",
      "name": "Extract CDN URL",
      "type": "n8n-nodes-base.code",
      "position": [
        1552,
        912
      ]
    },
    {
      "id": "06f9c319-8d0c-4229-941c-be1dedb27ece",
      "name": "AWS Textract - Analyse Expense",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1760,
        912
      ]
    },
    {
      "id": "ec7c192d-43a4-461a-af7b-6e7ab7a42572",
      "name": "Parse & Validate Extracted Data",
      "type": "n8n-nodes-base.code",
      "position": [
        1984,
        912
      ]
    },
    {
      "id": "ccfa60e6-3bb1-42e1-baad-40101ac8dac7",
      "name": "Sheets - Search for Duplicate",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2208,
        912
      ]
    },
    {
      "id": "2decb2b2-38a5-4496-8e6d-4e7ef2a633de",
      "name": "Resolve Write Action",
      "type": "n8n-nodes-base.code",
      "position": [
        2432,
        912
      ]
    },
    {
      "id": "a896e1e7-badf-4f73-856a-1c24dba5c76a",
      "name": "Route Write Action",
      "type": "n8n-nodes-base.switch",
      "position": [
        2640,
        912
      ]
    },
    {
      "id": "6f449dac-6818-4b2a-8010-ce7aa63621b6",
      "name": "Sheets - Append New Invoice",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2864,
        784
      ]
    },
    {
      "id": "6e3ae140-0628-4065-ab0c-95c462149a66",
      "name": "Sheets - Update Incomplete Row",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2864,
        960
      ]
    },
    {
      "id": "e13af7ba-f0c5-446f-847e-72e0b35b174c",
      "name": "Mark as Duplicate",
      "type": "n8n-nodes-base.code",
      "position": [
        2864,
        1152
      ]
    },
    {
      "id": "9c046373-967e-460d-ad0c-f6aa49a9ec8e",
      "name": "Merge Sheets Result",
      "type": "n8n-nodes-base.code",
      "position": [
        3088,
        960
      ]
    },
    {
      "id": "f9d2cf02-9a1f-4651-8f00-7a47930b835b",
      "name": "Slack - Notify Finance",
      "type": "n8n-nodes-base.slack",
      "position": [
        3312,
        864
      ]
    },
    {
      "id": "feedd89b-b558-4d47-95c3-c64f26da22d2",
      "name": "Build Final Response",
      "type": "n8n-nodes-base.code",
      "position": [
        3520,
        960
      ]
    },
    {
      "id": "7bd9385e-5445-408b-a413-157e5ce60323",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        3744,
        960
      ]
    }
  ],
  "connections": {
    "Extract CDN URL": {
      "main": [
        [
          {
            "node": "AWS Textract - Analyse Expense",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Remote URL?": {
      "main": [
        [
          {
            "node": "Upload to URL - Remote",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Upload to URL - Binary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Payload": {
      "main": [
        [
          {
            "node": "Has Remote URL?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark as Duplicate": {
      "main": [
        [
          {
            "node": "Merge Sheets Result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route Write Action": {
      "main": [
        [
          {
            "node": "Sheets - Append New Invoice",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Sheets - Update Incomplete Row",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Mark as Duplicate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Sheets Result": {
      "main": [
        [
          {
            "node": "Slack - Notify Finance",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Final Response": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Resolve Write Action": {
      "main": [
        [
          {
            "node": "Route Write Action",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack - Notify Finance": {
      "main": [
        [
          {
            "node": "Build Final Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload to URL - Binary": {
      "main": [
        [
          {
            "node": "Extract CDN URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload to URL - Remote": {
      "main": [
        [
          {
            "node": "Extract CDN URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook - Receive Invoice": {
      "main": [
        [
          {
            "node": "Validate Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sheets - Append New Invoice": {
      "main": [
        [
          {
            "node": "Merge Sheets Result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sheets - Search for Duplicate": {
      "main": [
        [
          {
            "node": "Resolve Write Action",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AWS Textract - Analyse Expense": {
      "main": [
        [
          {
            "node": "Parse & Validate Extracted Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sheets - Update Incomplete Row": {
      "main": [
        [
          {
            "node": "Merge Sheets Result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse & Validate Extracted Data": {
      "main": [
        [
          {
            "node": "Sheets - Search for Duplicate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}