{
  "name": "Share time-limited preview links with UploadToURL, SendGrid, and Google Sheets",
  "nodes": [
    {
      "id": "17c1d5d4-e36e-4a9b-b940-00c41735e55e",
      "name": "📋 Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -48,
        96
      ],
      "parameters": {
        "width": 560,
        "height": 520,
        "content": "## Share time-limited preview links with UploadToURL, SendGrid, and Google Sheets\nThe Problem: Standard email attachments stay accessible forever, creating security risks and offering no tracking for "
      }
    },
    {
      "id": "f3a0fb13-3e1d-42ea-8502-0ce4b5685712",
      "name": "Section 1 — Upload",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        688,
        640
      ],
      "parameters": {
        "width": 920,
        "height": 493,
        "content": "## 1 — Upload & link generation\n\n**Webhook → Validate → Has Remote URL? → Upload to URL (×2) → Extract CDN URL → Generate Link Record**\n\nValidates recipient email format and expiry hours (1–168 range)"
      }
    },
    {
      "id": "351cb3b9-79c6-45fd-8eac-815e2f593050",
      "name": "Section 2 — Log & Send",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1632,
        704
      ],
      "parameters": {
        "width": 440,
        "height": 419,
        "content": "## 2 — Log & send\n\n**Sheets - Log Active Link → SendGrid - Send Preview Email**\n\nGoogle Sheets records the link immediately as `active` before the email is sent — so there's always a record even if Se"
      }
    },
    {
      "id": "cdfd8480-5a9f-4729-a72a-8951574114c0",
      "name": "Section 3 — Wait & Expire",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2544,
        544
      ],
      "parameters": {
        "width": 712,
        "height": 690,
        "content": "## 3 — Wait & expire\n\n**Wait Node (configurable duration) → Sheets - Mark Expired → SendGrid - Expiry Notice**\n\nThe Wait node pauses this execution instance for the exact `expiryHours` value. After re"
      }
    },
    {
      "id": "82015827-6144-492b-abff-bee0b98eb1c2",
      "name": "Wait node note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2096,
        688
      ],
      "parameters": {
        "width": 356,
        "height": 430,
        "content": "## ⚙️ Wait node note\n\nThis workflow uses n8n's **Wait** node to pause execution between send and expiry. Each webhook submission runs as its own execution instance — multiple links can be in-flight si"
      }
    },
    {
      "id": "4571c524-549e-4598-a56f-0e15afbf052e",
      "name": "Webhook - Create Burner Link",
      "type": "n8n-nodes-base.webhook",
      "position": [
        688,
        928
      ]
    },
    {
      "id": "a72350ee-bfc4-4799-9566-cefec13ed12e",
      "name": "Validate Payload",
      "type": "n8n-nodes-base.code",
      "position": [
        832,
        928
      ]
    },
    {
      "id": "765d6d43-5953-41cb-8fb9-78749f4c4ca2",
      "name": "Has Remote URL?",
      "type": "n8n-nodes-base.if",
      "position": [
        976,
        928
      ]
    },
    {
      "id": "4c1525aa-a68f-4ff4-978a-f114f70da134",
      "name": "Upload to URL - Remote",
      "type": "n8n-nodes-uploadtourl.uploadToUrl",
      "position": [
        1152,
        816
      ]
    },
    {
      "id": "995e4b82-2dde-4a1f-9be7-5ba662423746",
      "name": "Upload to URL - Binary",
      "type": "n8n-nodes-uploadtourl.uploadToUrl",
      "position": [
        1152,
        992
      ]
    },
    {
      "id": "d10b01dc-82f6-4a59-8204-ab2b51d3ed6a",
      "name": "Extract CDN URL",
      "type": "n8n-nodes-base.code",
      "position": [
        1328,
        928
      ]
    },
    {
      "id": "b8c5df77-1f69-4c7f-a708-52a1e11f5346",
      "name": "Generate Link Record & Email HTML",
      "type": "n8n-nodes-base.code",
      "position": [
        1456,
        928
      ]
    },
    {
      "id": "2407e4af-6584-4f00-a08c-94e36d36284a",
      "name": "Sheets - Log Active Link",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1712,
        928
      ]
    },
    {
      "id": "aa27043d-01a4-4efa-ada6-81ce4ce6a8ff",
      "name": "SendGrid - Send Preview Email",
      "type": "n8n-nodes-base.sendGrid",
      "position": [
        1920,
        928
      ]
    },
    {
      "id": "b9cbd2f6-b0af-4f65-a6a0-2f7c09258e14",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        2192,
        928
      ]
    },
    {
      "id": "8807a34e-c45c-4b40-9af5-81c5904704ac",
      "name": "Wait - Until Link Expires",
      "type": "n8n-nodes-base.wait",
      "position": [
        2624,
        928
      ]
    },
    {
      "id": "6ddd47c7-58c0-4094-9834-965a45279237",
      "name": "Sheets - Mark Link Expired",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2832,
        928
      ]
    },
    {
      "id": "95a593f7-9ccf-4fbf-b5bf-be34023acc05",
      "name": "SendGrid - Notify Client Expired",
      "type": "n8n-nodes-base.sendGrid",
      "position": [
        3056,
        816
      ]
    },
    {
      "id": "a4a50667-1ff6-4330-8b6f-8cbb28a1e69c",
      "name": "SendGrid - Agency Summary Email",
      "type": "n8n-nodes-base.sendGrid",
      "position": [
        3072,
        1040
      ]
    }
  ],
  "connections": {
    "Extract CDN URL": {
      "main": [
        [
          {
            "node": "Generate Link Record & Email HTML",
            "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
          }
        ]
      ]
    },
    "Respond to Webhook": {
      "main": [
        [
          {
            "node": "Wait - Until Link Expires",
            "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
          }
        ]
      ]
    },
    "Sheets - Log Active Link": {
      "main": [
        [
          {
            "node": "SendGrid - Send Preview Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait - Until Link Expires": {
      "main": [
        [
          {
            "node": "Sheets - Mark Link Expired",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sheets - Mark Link Expired": {
      "main": [
        [
          {
            "node": "SendGrid - Notify Client Expired",
            "type": "main",
            "index": 0
          },
          {
            "node": "SendGrid - Agency Summary Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook - Create Burner Link": {
      "main": [
        [
          {
            "node": "Validate Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SendGrid - Send Preview Email": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Link Record & Email HTML": {
      "main": [
        [
          {
            "node": "Sheets - Log Active Link",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}