AutomationFlowsData & Sheets › Generate and Track Invoices with Hubspot, Gmail, Slack, Sheets, and Notion

Generate and Track Invoices with Hubspot, Gmail, Slack, Sheets, and Notion

ByAvkash Kakdiya @itechnotion on n8n.io

This workflow triggers when a HubSpot deal stage changes to Closed Won and automatically generates an invoice. It collects deal and contact data, builds a styled invoice, converts it into a PDF, and sends it to the client. The system logs all invoices and alerts the team, then…

Event trigger★★★★★ complexity32 nodesHubSpot TriggerHTTP RequestGoogle SheetsNotionGmailSlackError Trigger
Data & Sheets Trigger: Event Nodes: 32 Complexity: ★★★★★ Added:

This workflow corresponds to n8n.io template #14289 — we link there as the canonical source.

This workflow follows the Error Trigger → Gmail 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
{
  "nodes": [
    {
      "id": "17153603-4a79-431e-b288-fc6a6bcd0292",
      "name": "\ud83c\udfaf HubSpot - Deal Trigger",
      "type": "n8n-nodes-base.hubspotTrigger",
      "position": [
        3232,
        3104
      ],
      "parameters": {
        "eventsUi": {
          "eventValues": [
            {
              "name": "deal.propertyChange"
            }
          ]
        },
        "additionalFields": {}
      },
      "typeVersion": 1
    },
    {
      "id": "02d82b96-2db2-4350-95bd-7bc93adf6e30",
      "name": "\ud83d\udd00 IF - Is Deal Closed Won?",
      "type": "n8n-nodes-base.if",
      "position": [
        3456,
        3104
      ],
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.propertyName }}",
              "value2": "dealstage"
            },
            {
              "value1": "={{ $json.propertyValue }}",
              "value2": "closedwon"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4f351028-09b3-4464-a2db-82e34de58b07",
      "name": "\ud83c\udff7\ufe0f HTTP - Get Deal Details",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3680,
        3104
      ],
      "parameters": {
        "url": "=https://api.hubapi.com/crm/v3/objects/deals/{{ $json.objectId }}?properties=dealname,amount,dealstage,closedate,hubspot_owner_id,description",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4
    },
    {
      "id": "ab9333b3-fafa-4321-ab6c-7882a225fbca",
      "name": "\ud83d\udd17 HTTP - Get Deal Associations",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3904,
        3104
      ],
      "parameters": {
        "url": "=https://api.hubapi.com/crm/v3/objects/deals/{{ $json.id }}/associations/contacts",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4
    },
    {
      "id": "6501585d-bc0f-4558-9ada-03c805e939a6",
      "name": "\u2699\ufe0f Code - Extract Contact ID",
      "type": "n8n-nodes-base.code",
      "position": [
        4112,
        3104
      ],
      "parameters": {
        "jsCode": "// \u2500\u2500 Extract contact ID from associations response \u2500\u2500\nconst results = $input.first().json.results;\n\nif (!results || results.length === 0) {\n  throw new Error(\n    'No contact is associated with this HubSpot deal. ' +\n    'Please associate at least one contact before marking as Closed Won.'\n  );\n}\n\nconst contactId = results[0].id;\n\n// Pull deal data fetched two nodes ago\nconst deal = $('\ud83c\udff7\ufe0f HTTP - Get Deal Details').first().json;\n\nreturn {\n  contactId,\n  dealId:    deal.id,\n  dealName:  deal.properties.dealname  || 'Professional Services',\n  amount:    deal.properties.amount    || '0',\n  closeDate: deal.properties.closedate || new Date().toISOString().split('T')[0]\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "bd29bc05-f2a9-4a2d-a253-c4a392cbc172",
      "name": "\ud83d\udc64 HTTP - Get Contact Details",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        4336,
        3104
      ],
      "parameters": {
        "url": "=https://api.hubapi.com/crm/v3/objects/contacts/{{ $json.contactId }}?properties=firstname,lastname,email,company,phone,address",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "typeVersion": 4
    },
    {
      "id": "ade25776-aa2f-4e09-8978-b030fd07f4cb",
      "name": "\ud83d\udcc4 Code - Build Invoice + HTML",
      "type": "n8n-nodes-base.code",
      "position": [
        4560,
        3104
      ],
      "parameters": {
        "jsCode": "// \u2500\u2500 Build invoice data + beautifully styled HTML \u2500\u2500\nconst contactProps = $input.first().json.properties;\nconst contactId    = $input.first().json.id;\nconst prev         = $('\u2699\ufe0f Code - Extract Contact ID').first().json;\n\n// \u2500\u2500 Generate invoice number \u2500\u2500\nconst pad = (n) => String(n).padStart(4, '0');\nconst invoiceNumber = 'INV-' + new Date().getFullYear() + '-' + pad(Math.floor(Math.random() * 9000) + 1000);\nconst issueDate     = new Date().toISOString().split('T')[0];\nconst dueDate       = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];\n\n// \u2500\u2500 Contact & deal info \u2500\u2500\nconst firstName    = contactProps.firstname || '';\nconst lastName     = contactProps.lastname  || '';\nconst contactName  = `${firstName} ${lastName}`.trim() || 'Valued Customer';\nconst contactEmail = contactProps.email   || '';\nconst company      = contactProps.company || '';\nconst phone        = contactProps.phone   || 'N/A';\nconst amount       = parseFloat(prev.amount || '0');\nconst dealName     = prev.dealName;\n\nconst fmt = (n) => n.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });\nconst formattedAmount = fmt(amount);\nconst year = new Date().getFullYear();\n\n// \u2500\u2500 Build HTML invoice \u2500\u2500\nconst htmlContent = `<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<style>\n  * { margin:0; padding:0; box-sizing:border-box; }\n  body { font-family:'Segoe UI',Arial,sans-serif; color:#2d3748; background:#fff; }\n  .wrap { max-width:780px; margin:0 auto; padding:48px; }\n  .header { display:flex; justify-content:space-between; align-items:flex-start;\n            padding-bottom:28px; border-bottom:4px solid #4F46E5; margin-bottom:36px; }\n  .brand-name { font-size:24px; font-weight:800; color:#4F46E5; letter-spacing:-0.5px; }\n  .brand-sub  { font-size:12px; color:#718096; margin-top:5px; line-height:1.6; }\n  .inv-badge  { text-align:right; }\n  .inv-label  { font-size:30px; font-weight:900; color:#4F46E5; letter-spacing:4px; }\n  .inv-num    { font-size:15px; color:#718096; margin-top:4px; font-weight:600; }\n  .grid       { display:grid; grid-template-columns:1fr 1fr; gap:20px; margin-bottom:32px; }\n  .box        { background:#F7F8FC; border-radius:10px; padding:20px; }\n  .box h4     { font-size:10px; text-transform:uppercase; letter-spacing:1.5px;\n                color:#A0AEC0; margin-bottom:10px; }\n  .box p      { font-size:13.5px; color:#4A5568; line-height:1.8; }\n  .box .bold  { font-weight:700; font-size:15px; color:#2d3748; }\n  .status-unpaid { display:inline-block; background:#FFF5F5; color:#E53E3E;\n                   padding:2px 10px; border-radius:20px; font-weight:700; font-size:12px; }\n  table       { width:100%; border-collapse:collapse; margin-bottom:8px; }\n  thead tr    { background:#4F46E5; }\n  thead th    { color:#fff; padding:13px 16px; text-align:left;\n                font-size:12px; font-weight:600; letter-spacing:0.8px; text-transform:uppercase; }\n  tbody tr    { border-bottom:1px solid #EDF2F7; }\n  tbody td    { padding:13px 16px; font-size:14px; color:#4A5568; }\n  .sub-row td { padding:8px 16px; color:#718096; font-size:13px; }\n  .total-row td { padding:15px 16px; background:#F7F8FC; font-weight:700;\n                  font-size:16px; border-top:2px solid #4F46E5; }\n  .total-amt  { color:#4F46E5; font-size:20px; }\n  .pay-box    { background:#EBF8FF; border:1px solid #BEE3F8; border-radius:10px;\n                padding:18px 22px; margin:20px 0 32px; }\n  .pay-box h4 { color:#2B6CB0; font-size:13px; font-weight:700; margin-bottom:8px; }\n  .pay-box p  { color:#2C5282; font-size:13px; line-height:1.7; }\n  .footer     { margin-top:36px; padding-top:20px; border-top:1px solid #EDF2F7;\n                text-align:center; color:#A0AEC0; font-size:11.5px; line-height:1.8; }\n</style>\n</head>\n<body>\n<div class=\"wrap\">\n\n  <div class=\"header\">\n    <div>\n      <div class=\"brand-name\">YOUR COMPANY NAME</div>\n      <div class=\"brand-sub\">\n        123 Business St, City, State 12345<br>\n        user@example.com &nbsp;|&nbsp; +1234567890\n      </div>\n    </div>\n    <div class=\"inv-badge\">\n      <div class=\"inv-label\">INVOICE</div>\n      <div class=\"inv-num\">${invoiceNumber}</div>\n    </div>\n  </div>\n\n  <div class=\"grid\">\n    <div class=\"box\">\n      <h4>Bill To</h4>\n      <p class=\"bold\">${contactName}</p>\n      <p>${company}</p>\n      <p>${contactEmail}</p>\n      <p>${phone}</p>\n    </div>\n    <div class=\"box\">\n      <h4>Invoice Details</h4>\n      <p><strong>Invoice No:</strong> ${invoiceNumber}</p>\n      <p><strong>Issue Date:</strong> ${issueDate}</p>\n      <p><strong>Due Date:</strong> ${dueDate}</p>\n      <p><strong>Status:</strong> <span class=\"status-unpaid\">UNPAID</span></p>\n    </div>\n  </div>\n\n  <table>\n    <thead>\n      <tr>\n        <th>Description</th>\n        <th style=\"width:80px\">Qty</th>\n        <th style=\"width:150px\">Unit Price</th>\n        <th style=\"width:150px\">Amount</th>\n      </tr>\n    </thead>\n    <tbody>\n      <tr>\n        <td>${dealName}</td>\n        <td>1</td>\n        <td>$${formattedAmount}</td>\n        <td>$${formattedAmount}</td>\n      </tr>\n      <tr class=\"sub-row\">\n        <td colspan=\"3\" style=\"text-align:right\">Subtotal</td>\n        <td>$${formattedAmount}</td>\n      </tr>\n      <tr class=\"sub-row\">\n        <td colspan=\"3\" style=\"text-align:right\">Tax (0%)</td>\n        <td>$0.00</td>\n      </tr>\n      <tr class=\"total-row\">\n        <td colspan=\"3\" style=\"text-align:right\">Total Amount Due</td>\n        <td class=\"total-amt\">$${formattedAmount}</td>\n      </tr>\n    </tbody>\n  </table>\n\n  <div class=\"pay-box\">\n    <h4>\ud83d\udcb3 Payment Instructions</h4>\n    <p>\n      Please make payment within 30 days of the invoice date.<br>\n      Reference invoice number <strong>${invoiceNumber}</strong> in your payment.<br>\n      Bank Transfer: Account <strong>1234-5678</strong> &nbsp;|&nbsp; Routing: <strong>021000021</strong>\n    </p>\n  </div>\n\n  <div class=\"footer\">\n    Thank you for your business! Questions? Contact user@example.com<br>\n    \u00a9 ${year} Your Company Name. All rights reserved. &nbsp;|&nbsp; Payment terms: Net 30\n  </div>\n\n</div>\n</body>\n</html>`;\n\nreturn {\n  invoice_number:   invoiceNumber,\n  issue_date:       issueDate,\n  due_date:         dueDate,\n  amount,\n  formatted_amount: formattedAmount,\n  deal_name:        dealName,\n  contact_name:     contactName,\n  contact_email:    contactEmail,\n  company,\n  phone,\n  deal_id:    prev.dealId,\n  contact_id: contactId,\n  html_content: htmlContent\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "dc9aab04-faab-41e8-8162-30b298b289e8",
      "name": "\ud83d\udda8\ufe0f HTTP - Generate PDF",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        4784,
        3104
      ],
      "parameters": {
        "url": "https://api.html2pdf.app/v1/generate",
        "method": "POST",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file",
              "outputPropertyName": "invoice_pdf"
            }
          }
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "html",
              "value": "={{ $json.html_content }}"
            },
            {
              "name": "apiKey",
              "value": "REPLACE_HTML2PDF_API_KEY"
            },
            {
              "name": "media_type",
              "value": "print"
            },
            {
              "name": "format",
              "value": "A4"
            },
            {
              "name": "landscape",
              "value": "false"
            }
          ]
        }
      },
      "typeVersion": 4
    },
    {
      "id": "05553481-1cae-48ca-b871-9c66839a79f9",
      "name": "\ud83d\udcca Google Sheets - Log Invoice",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        4992,
        3104
      ],
      "parameters": {
        "columns": {
          "value": {
            "Email": "={{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.contact_email }}",
            "Amount": "={{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.amount }}",
            "Status": "Sent - Awaiting Payment",
            "Company": "={{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.company }}",
            "Due Date": "={{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.due_date }}",
            "Deal Name": "={{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.deal_name }}",
            "Issue Date": "={{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.issue_date }}",
            "Client Name": "={{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.contact_name }}",
            "Invoice Number": "={{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.invoice_number }}",
            "HubSpot Deal ID": "={{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.deal_id }}"
          },
          "mappingMode": "defineBelow"
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "REPLACE_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4
    },
    {
      "id": "4614313b-2803-49e0-8781-d9d0fcf8e8c8",
      "name": "\ud83d\udcd3 Notion - Create Invoice Record",
      "type": "n8n-nodes-base.notion",
      "position": [
        5216,
        3104
      ],
      "parameters": {
        "title": "={{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.invoice_number }} \u2014 {{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.contact_name }}",
        "pageId": {
          "__rl": true,
          "mode": "url",
          "value": ""
        },
        "options": {}
      },
      "credentials": {
        "notionApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "076e9e1e-3b62-4528-9317-f955c7ef385d",
      "name": "\ud83d\udce7 Gmail - Send Invoice Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        5440,
        3104
      ],
      "parameters": {
        "sendTo": "={{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.contact_email }}",
        "message": "=<div style=\"font-family:Arial,sans-serif;color:#2d3748;max-width:600px\">\n  <p>Dear {{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.contact_name }},</p>\n  <p>Thank you for choosing us. Please find attached your invoice <strong>{{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.invoice_number }}</strong> for <strong>${{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.formatted_amount }}</strong>.</p>\n  <table style=\"width:100%;background:#f7f8fc;border-radius:8px;padding:16px;margin:20px 0\">\n    <tr><td style=\"padding:6px 0\"><strong>Invoice #:</strong></td><td>{{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.invoice_number }}</td></tr>\n    <tr><td style=\"padding:6px 0\"><strong>Amount Due:</strong></td><td style=\"color:#4F46E5;font-weight:700\">${{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.formatted_amount }}</td></tr>\n    <tr><td style=\"padding:6px 0\"><strong>Due Date:</strong></td><td>{{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.due_date }}</td></tr>\n  </table>\n  <p>The invoice PDF is attached. Please process payment by the due date and include the invoice number as reference.</p>\n  <p>For questions, simply reply to this email.</p>\n  <p style=\"margin-top:24px\">Best regards,<br><strong>Billing Team</strong><br>Your Company Name</p>\n</div>",
        "options": {},
        "subject": "=Invoice {{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.invoice_number }} \u2014 ${{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.formatted_amount }} Due {{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.due_date }}"
      },
      "typeVersion": 2
    },
    {
      "id": "03e00a09-730a-4d3a-b658-7454f48710cb",
      "name": "\ud83d\udcac Slack - Invoice Sent Alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        5648,
        3104
      ],
      "parameters": {
        "text": "=:white_check_mark: *Invoice Sent Successfully*\n\n*Invoice:* `{{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.invoice_number }}`\n*Client:* {{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.contact_name }} @ {{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.company }}\n*Amount:* *${{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.formatted_amount }}*\n*Deal:* {{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.deal_name }}\n*Due Date:* {{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.due_date }}\n\n:hourglass_flowing_sand: *Auto follow-up* will trigger in 7 days if payment is not confirmed.",
        "otherOptions": {
          "mrkdwn": true
        },
        "authentication": "oAuth2"
      },
      "typeVersion": 2
    },
    {
      "id": "2ebdc39f-f729-4968-ac6c-80a63011c70c",
      "name": "\u23f3 Wait - 7 Day Payment Window",
      "type": "n8n-nodes-base.wait",
      "position": [
        5888,
        3104
      ],
      "parameters": {
        "unit": "days",
        "amount": 7
      },
      "typeVersion": 1
    },
    {
      "id": "5167b736-46a7-467b-b2d2-e0913bec9828",
      "name": "\ud83d\udd0d HTTP - Recheck Deal Stage",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        6096,
        3104
      ],
      "parameters": {
        "url": "=https://api.hubapi.com/crm/v3/objects/deals/{{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.deal_id }}?properties=dealstage,amount,hs_deal_stage_probability",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "typeVersion": 4
    },
    {
      "id": "a21a6f44-0c56-4c72-bc2d-ceef3cd443c1",
      "name": "\ud83d\udd00 IF - Payment Received?",
      "type": "n8n-nodes-base.if",
      "position": [
        6304,
        3104
      ],
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.properties.dealstage }}",
              "value2": "closedwon_paid"
            }
          ]
        },
        "combineOperation": "any"
      },
      "typeVersion": 1
    },
    {
      "id": "ac494063-dcd8-47d8-b263-771f5e940490",
      "name": "\u2705 Slack - Payment Confirmed",
      "type": "n8n-nodes-base.slack",
      "position": [
        6560,
        2912
      ],
      "parameters": {
        "text": "=:moneybag: *Payment Confirmed \u2014 Invoice Closed!*\n\n*Invoice:* `{{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.invoice_number }}`\n*Client:* {{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.contact_name }} @ {{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.company }}\n*Amount Received:* *${{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.formatted_amount }}*\n\n:tada: Deal marked as paid in HubSpot. Great work team!",
        "otherOptions": {
          "mrkdwn": true
        },
        "authentication": "oAuth2"
      },
      "typeVersion": 2
    },
    {
      "id": "d6cea393-d97f-4170-a769-a2f47ee15e21",
      "name": "\ud83d\udce7 Gmail - Follow-up Email #1",
      "type": "n8n-nodes-base.gmail",
      "position": [
        6560,
        3328
      ],
      "parameters": {
        "sendTo": "={{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.contact_email }}",
        "message": "=<div style=\"font-family:Arial,sans-serif;color:#2d3748;max-width:600px\">\n  <p>Dear {{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.contact_name }},</p>\n  <p>I hope you're doing well! This is a friendly reminder that invoice <strong>{{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.invoice_number }}</strong> for <strong>${{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.formatted_amount }}</strong> was due on <strong>{{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.due_date }}</strong>.</p>\n  <p>If you've already sent payment, please disregard this message \u2014 we may be crossing in the post. Otherwise, we'd appreciate your prompt attention.</p>\n  <p>Need to discuss payment terms or have any questions? Simply reply to this email and we'll be happy to help.</p>\n  <p style=\"margin-top:24px\">Warm regards,<br><strong>Billing Team</strong><br>Your Company Name</p>\n</div>",
        "options": {},
        "subject": "=Friendly Reminder: Invoice {{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.invoice_number }} \u2014 Payment Due"
      },
      "typeVersion": 2
    },
    {
      "id": "52083ac6-85bc-45c6-bc10-04beb18a5d4b",
      "name": "\u23f3 Wait - 5 More Days",
      "type": "n8n-nodes-base.wait",
      "position": [
        6784,
        3328
      ],
      "parameters": {
        "unit": "days",
        "amount": 5
      },
      "typeVersion": 1
    },
    {
      "id": "41086544-3a90-4d57-b4c9-f4819ca3ac5a",
      "name": "\ud83d\udd0d HTTP - Final Payment Check",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        7008,
        3328
      ],
      "parameters": {
        "url": "=https://api.hubapi.com/crm/v3/objects/deals/{{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.deal_id }}?properties=dealstage,amount",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "typeVersion": 4
    },
    {
      "id": "fd161811-2aa6-4293-9c74-9bbd6e707f3e",
      "name": "\ud83d\udd00 IF - Still Unpaid? (Escalate)",
      "type": "n8n-nodes-base.if",
      "position": [
        7216,
        3328
      ],
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.properties.dealstage }}",
              "value2": "closedwon_paid",
              "operation": "notEqual"
            }
          ]
        },
        "combineOperation": "any"
      },
      "typeVersion": 1
    },
    {
      "id": "951d1ce9-ccc5-4280-9ccf-00cd2776b379",
      "name": "\ud83d\udea8 Slack - Escalation Alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        7552,
        2976
      ],
      "parameters": {
        "text": "=:rotating_light: *OVERDUE INVOICE \u2014 MANUAL ACTION REQUIRED*\n\n*Invoice:* `{{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.invoice_number }}`\n*Client:* {{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.contact_name }} @ {{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.company }}\n*Overdue Amount:* *${{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.formatted_amount }}*\n*Client Email:* {{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.contact_email }}\n*Original Due Date:* {{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.due_date }}\n*Days Overdue:* 12+\n\n:phone: *Please contact the client directly \u2014 two automated reminders have been sent.*\n:notion: Notion record has been flagged as *OVERDUE*.",
        "otherOptions": {
          "mrkdwn": true
        },
        "authentication": "oAuth2"
      },
      "typeVersion": 2
    },
    {
      "id": "7ac58dd0-1e09-433b-b9c4-6ac905e249ac",
      "name": "\ud83d\udcd3 Notion - Flag as Overdue",
      "type": "n8n-nodes-base.notion",
      "position": [
        7552,
        3184
      ],
      "parameters": {
        "operation": "update"
      },
      "credentials": {
        "notionApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "d69aceed-3c66-4fac-b89b-79d731a2271f",
      "name": "\u2705 Slack - Late Payment Confirmed",
      "type": "n8n-nodes-base.slack",
      "position": [
        7552,
        3376
      ],
      "parameters": {
        "text": "=:moneybag: *Late Payment Received \u2014 Invoice Closed*\n\n*Invoice:* `{{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.invoice_number }}`\n*Client:* {{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.contact_name }} @ {{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.company }}\n*Amount Received:* *${{ $('\ud83d\udcc4 Code - Build Invoice + HTML').item.json.formatted_amount }}*\n\nPayment came in after the follow-up reminder. :slightly_smiling_face: Please update HubSpot manually if needed.",
        "otherOptions": {
          "mrkdwn": true
        },
        "authentication": "oAuth2"
      },
      "typeVersion": 2
    },
    {
      "id": "40077fa5-b256-4c47-a23b-c13140546038",
      "name": "\u26a1 Error Trigger",
      "type": "n8n-nodes-base.errorTrigger",
      "position": [
        3216,
        3728
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "15a3db2e-f1b1-4fe2-a004-e18a86f686d4",
      "name": "\ud83d\udea8 Slack - Workflow Error Alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        3440,
        3728
      ],
      "parameters": {
        "text": "=:x: *INVOICE PIPELINE \u2014 WORKFLOW ERROR*\n\n*Error:* `{{ $json.execution.error.message }}`\n*Failed Node:* {{ $json.execution.lastNodeExecuted }}\n*Workflow:* {{ $json.workflow.name }}\n*Execution ID:* {{ $json.execution.id }}\n*Timestamp:* {{ $now.format('yyyy-MM-dd HH:mm:ss') }}\n\n:arrow_right: Log into N8N and check execution logs for details.\nManual intervention required.",
        "otherOptions": {
          "mrkdwn": true
        },
        "authentication": "oAuth2"
      },
      "typeVersion": 2
    },
    {
      "id": "0a8a475c-9852-40bb-bbd8-e226f2383575",
      "name": "\ud83d\udccb SETUP INSTRUCTIONS",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2224,
        2880
      ],
      "parameters": {
        "width": 780,
        "height": 1020,
        "content": "# Automated Invoice & Follow-Up System\n\n### How it works\nThis workflow triggers when a HubSpot deal is marked as Closed Won. It fetches deal and contact data, generates a styled invoice, converts it into a PDF, logs it in internal systems, and sends it to the client.\n\nAfter sending, the system tracks payment status. If unpaid, it sends reminders and escalates overdue invoices automatically.\n\n### Setup steps\n1. Connect HubSpot trigger and API credentials\n2. Add HTML2PDF API key\n3. Set Google Sheets and Notion database\n4. Connect Gmail and Slack\n5. Update payment stage ID in IF nodes\n6. Activate workflow\n\n### Customization tips\n- Edit invoice design in Code node\n- Adjust wait durations for follow-ups\n- Add more reminders if needed"
      },
      "typeVersion": 1
    },
    {
      "id": "fdd9db77-bc88-48f7-bfcf-d8095afab68b",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3088,
        2864
      ],
      "parameters": {
        "color": 7,
        "width": 1376,
        "height": 704,
        "content": "##  Trigger & Data Collection\nTriggers on deal stage change.\nFetches deal + contact details from HubSpot."
      },
      "typeVersion": 1
    },
    {
      "id": "0e8949e7-6db2-42da-b5ba-cacf017f80d6",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4480,
        2864
      ],
      "parameters": {
        "color": 7,
        "height": 704,
        "content": "## Invoice Generation\nBuilds invoice data and creates styled HTML."
      },
      "typeVersion": 1
    },
    {
      "id": "c132b042-4213-4098-9eb8-e2a08d775afc",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4736,
        2864
      ],
      "parameters": {
        "color": 7,
        "width": 1072,
        "height": 704,
        "content": "## Send & Store Invoice\nConverts to PDF, logs in systems,\nemails client, and alerts team."
      },
      "typeVersion": 1
    },
    {
      "id": "6bb8af1d-e99b-4faa-a3b5-0d23b838b958",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5824,
        2864
      ],
      "parameters": {
        "color": 7,
        "width": 1328,
        "height": 688,
        "content": "## Send & Store Invoice\nConverts to PDF, logs in systems,\nemails client, and alerts team."
      },
      "typeVersion": 1
    },
    {
      "id": "a6b6d2c9-4409-478b-9320-729f4dc12f23",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        7168,
        2864
      ],
      "parameters": {
        "color": 7,
        "width": 720,
        "height": 688,
        "content": "##  Escalation & Errors\nHandles overdue invoices and workflow failures.\nAlerts team and updates records."
      },
      "typeVersion": 1
    },
    {
      "id": "73f010c3-1287-44f8-a0b7-8afbef49ff89",
      "name": "Sticky Note12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3088,
        3600
      ],
      "parameters": {
        "color": 7,
        "width": 576,
        "height": 304,
        "content": "## Error Handling\nCaptures any workflow failure\nand sends alert to Slack for quick action."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "\u26a1 Error Trigger": {
      "main": [
        [
          {
            "node": "\ud83d\udea8 Slack - Workflow Error Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u23f3 Wait - 5 More Days": {
      "main": [
        [
          {
            "node": "\ud83d\udd0d HTTP - Final Payment Check",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83c\udfaf HubSpot - Deal Trigger": {
      "main": [
        [
          {
            "node": "\ud83d\udd00 IF - Is Deal Closed Won?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd00 IF - Payment Received?": {
      "main": [
        [
          {
            "node": "\u2705 Slack - Payment Confirmed",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "\ud83d\udce7 Gmail - Follow-up Email #1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udda8\ufe0f HTTP - Generate PDF": {
      "main": [
        [
          {
            "node": "\ud83d\udcca Google Sheets - Log Invoice",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd00 IF - Is Deal Closed Won?": {
      "main": [
        [
          {
            "node": "\ud83c\udff7\ufe0f HTTP - Get Deal Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd0d HTTP - Recheck Deal Stage": {
      "main": [
        [
          {
            "node": "\ud83d\udd00 IF - Payment Received?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u23f3 Wait - 7 Day Payment Window": {
      "main": [
        [
          {
            "node": "\ud83d\udd0d HTTP - Recheck Deal Stage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83c\udff7\ufe0f HTTP - Get Deal Details": {
      "main": [
        [
          {
            "node": "\ud83d\udd17 HTTP - Get Deal Associations",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udc64 HTTP - Get Contact Details": {
      "main": [
        [
          {
            "node": "\ud83d\udcc4 Code - Build Invoice + HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcac Slack - Invoice Sent Alert": {
      "main": [
        [
          {
            "node": "\u23f3 Wait - 7 Day Payment Window",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udce7 Gmail - Follow-up Email #1": {
      "main": [
        [
          {
            "node": "\u23f3 Wait - 5 More Days",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udce7 Gmail - Send Invoice Email": {
      "main": [
        [
          {
            "node": "\ud83d\udcac Slack - Invoice Sent Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd0d HTTP - Final Payment Check": {
      "main": [
        [
          {
            "node": "\ud83d\udd00 IF - Still Unpaid? (Escalate)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u2699\ufe0f Code - Extract Contact ID": {
      "main": [
        [
          {
            "node": "\ud83d\udc64 HTTP - Get Contact Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcc4 Code - Build Invoice + HTML": {
      "main": [
        [
          {
            "node": "\ud83d\udda8\ufe0f HTTP - Generate PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcca Google Sheets - Log Invoice": {
      "main": [
        [
          {
            "node": "\ud83d\udcd3 Notion - Create Invoice Record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd17 HTTP - Get Deal Associations": {
      "main": [
        [
          {
            "node": "\u2699\ufe0f Code - Extract Contact ID",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd00 IF - Still Unpaid? (Escalate)": {
      "main": [
        [
          {
            "node": "\ud83d\udea8 Slack - Escalation Alert",
            "type": "main",
            "index": 0
          },
          {
            "node": "\ud83d\udcd3 Notion - Flag as Overdue",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "\u2705 Slack - Late Payment Confirmed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcd3 Notion - Create Invoice Record": {
      "main": [
        [
          {
            "node": "\ud83d\udce7 Gmail - Send Invoice Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow triggers when a HubSpot deal stage changes to Closed Won and automatically generates an invoice. It collects deal and contact data, builds a styled invoice, converts it into a PDF, and sends it to the client. The system logs all invoices and alerts the team, then…

Source: https://n8n.io/workflows/14289/ — 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

Generate market research reports from news and competitor sites to Notion and Slack. Uses errorTrigger, httpRequest, notion, googleSheets. Event-driven trigger; 19 nodes.

Error Trigger, HTTP Request, Notion +2
Data & Sheets

Daily Business Report Generator. Uses googleSheets, httpRequest, slack, gmail. Scheduled trigger; 17 nodes.

Google Sheets, HTTP Request, Slack +3
Data & Sheets

This workflow automates end-to-end AI-driven inventory intelligence, transforming Airtable stock data into optimized reorder recommendations, daily operational summaries, and instant Slack alerts. It

Lm Chat Azure Open Ai, Airtable, Google Sheets +6
Data & Sheets

This guide will walk you through setting up your n8n workflow. By the end, you'll have a fully automated system for managing your recruitment pipeline.

Google Calendar Trigger, Slack, HTTP Request +4
Data & Sheets

Meeting Notes Generator. Uses httpRequest, slack, notion, googleSheets. Webhook trigger; 17 nodes.

HTTP Request, Slack, Notion +2