{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "9d642cd1-88d1-4bc2-9ef6-2b570db71ce5",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1552,
        -784
      ],
      "parameters": {
        "width": 400,
        "height": 796,
        "content": "## How it works\n\nThis workflow generates professional invoices instantly when triggered by payment gateways, CRM systems, or forms. It validates invoice data, auto-generates unique invoice numbers, calculates line items and taxes, adds your company branding and bank details, creates a PDF with payment status badge (Paid/Unpaid/Partial), archives it to Google Drive, and emails it to the customer. Team notifications route through Slack based on payment status\u2014paid invoices get success alerts while unpaid/partial invoices get reminders with due dates for collections follow-up.\n\n## Setup steps\n\n1. **Configure webhook** - Connect from your payment system (Stripe/PayPal), CRM, or form tool\n2. **Customize company data** - Edit branding, bank details, and tax IDs in \"Enrich with Company Data\" node\n3. **Set tax rates** - Adjust default tax percentage in \"Validate Invoice Data\" node (currently 18%)\n4. **Add HTML to PDF API** - Get key at htmlcsstoimage.com (1-5\u00a2 per invoice)\n5. **Connect Google Drive** - Authenticate for invoice archival\n6. **Connect Gmail** - Authenticate for customer email delivery\n7. **Add Slack webhooks** - Get URLs from Slack for both notification nodes\n8. **Test with sample data** before connecting live payment system\n\n\ud83d\udca1 **Required data:** customerName, customerEmail, items array (description, quantity, rate), paymentStatus (paid/unpaid/partial)"
      },
      "typeVersion": 1
    },
    {
      "id": "c14e603f-a354-4d88-acf1-9add2a915a6c",
      "name": "Webhook Trigger",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -944,
        -80
      ],
      "parameters": {
        "path": "invoice-generator",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 1
    },
    {
      "id": "7d53dd09-7f7f-4d00-8d13-f53892f61223",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -944,
        -240
      ],
      "parameters": {
        "color": 7,
        "width": 588,
        "height": 384,
        "content": "## Data Processing\n\nReceives invoice data, validates required fields, auto-generates invoice numbers, calculates line items/subtotals/taxes, adds company branding and bank details, then creates professional HTML with payment status badge and itemized pricing."
      },
      "typeVersion": 1
    },
    {
      "id": "969158b3-3974-4206-a232-f52304683a09",
      "name": "Validate Invoice Data",
      "type": "n8n-nodes-base.code",
      "position": [
        -784,
        -32
      ],
      "parameters": {
        "jsCode": "// Validate incoming invoice data\nconst item = $input.first().json;\n\n// Required fields validation\nconst requiredFields = ['customerName', 'customerEmail', 'items', 'paymentStatus'];\nconst missingFields = requiredFields.filter(field => !item[field] || (typeof item[field] === 'string' && item[field].trim() === ''));\n\n// Validate items array\nif (!item.items || !Array.isArray(item.items) || item.items.length === 0) {\n  missingFields.push('items (must be array with at least one item)');\n}\n\nif (missingFields.length > 0) {\n  throw new Error(`Missing required fields: ${missingFields.join(', ')}`);\n}\n\n// Validate email format\nconst emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\nif (!emailRegex.test(item.customerEmail)) {\n  throw new Error('Invalid email format for customerEmail');\n}\n\n// Validate payment status\nconst validStatuses = ['paid', 'unpaid', 'partial'];\nif (!validStatuses.includes(item.paymentStatus.toLowerCase())) {\n  throw new Error('Invalid paymentStatus. Must be: paid, unpaid, or partial');\n}\n\n// Validate and calculate items\nfor (let i = 0; i < item.items.length; i++) {\n  const lineItem = item.items[i];\n  if (!lineItem.description || !lineItem.quantity || !lineItem.rate) {\n    throw new Error(`Item ${i + 1} missing required fields (description, quantity, rate)`);\n  }\n  \n  // Ensure numeric values\n  lineItem.quantity = parseFloat(lineItem.quantity);\n  lineItem.rate = parseFloat(lineItem.rate);\n  \n  // Calculate amount\n  item.items[i].amount = lineItem.quantity * lineItem.rate;\n}\n\n// Generate invoice number if not provided\nif (!item.invoiceNumber) {\n  const date = new Date();\n  const year = date.getFullYear();\n  const month = String(date.getMonth() + 1).padStart(2, '0');\n  const random = Math.floor(Math.random() * 10000).toString().padStart(4, '0');\n  item.invoiceNumber = `INV-${year}${month}-${random}`;\n}\n\n// Set invoice date if not provided\nif (!item.invoiceDate) {\n  item.invoiceDate = new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' });\n}\n\n// Calculate due date if not provided (default 30 days)\nif (!item.dueDate) {\n  const dueDays = item.paymentTermsDays || 30;\n  const dueDate = new Date();\n  dueDate.setDate(dueDate.getDate() + dueDays);\n  item.dueDate = dueDate.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' });\n}\n\n// Calculate subtotal\nitem.subtotal = item.items.reduce((sum, lineItem) => sum + lineItem.amount, 0);\n\n// Apply discount if provided\nitem.discountAmount = parseFloat(item.discountAmount) || 0;\nconst afterDiscount = item.subtotal - item.discountAmount;\n\n// Calculate tax (default 18% if not provided)\nitem.taxRate = parseFloat(item.taxRate) || 18;\nitem.taxAmount = (afterDiscount * item.taxRate) / 100;\n\n// Calculate total\nitem.total = afterDiscount + item.taxAmount;\n\n// Set currency defaults\nitem.currency = item.currency || 'USD';\nitem.currencySymbol = item.currencySymbol || '$';\n\n// Payment terms\nitem.paymentTerms = item.paymentTerms || 'Payment due within 30 days';\n\nreturn { json: item };"
      },
      "typeVersion": 2
    },
    {
      "id": "92f92526-75c7-47c9-9183-39a9a5de3735",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        384,
        -320
      ],
      "parameters": {
        "color": 7,
        "width": 424,
        "height": 496,
        "content": "## Smart Notifications\n\nRoutes Slack alerts based on payment status. Paid invoices get success notifications. Unpaid/partial invoices get reminders with due dates, enabling accounting team to prioritize collections follow-up."
      },
      "typeVersion": 1
    },
    {
      "id": "2624ead6-7e79-4b13-80ba-0a753d39d17b",
      "name": "Enrich with Company Data",
      "type": "n8n-nodes-base.code",
      "position": [
        -624,
        -80
      ],
      "parameters": {
        "jsCode": "// Add company information and branding\nconst item = $input.first().json;\n\n// Company information (customize these)\nconst companyDefaults = {\n  companyName: item.companyName || 'Media Jade',\n  companyAddress: item.companyAddress || '456 Company Street',\n  companyCity: item.companyCity || 'San Francisco, CA 94105',\n  companyEmail: item.companyEmail || 'user@example.com',\n  companyPhone: item.companyPhone || '+1234567890',\n  companyWebsite: item.companyWebsite || 'www.mediajde.com',\n  companyLogo: item.companyLogo || '',\n  \n  // Tax registration numbers\n  taxId: item.taxId || 'TAX-123456789',\n  gstNumber: item.gstNumber || 'GST-987654321',\n  \n  // Bank details for payment\n  bankName: item.bankName || 'Chase Bank',\n  accountNumber: item.accountNumber || '****1234',\n  routingNumber: item.routingNumber || '****5678',\n  swiftCode: item.swiftCode || 'CHASUS33',\n  \n  // Payment links\n  paymentLink: item.paymentLink || '',\n  \n  // Customer defaults\n  customerCompany: item.customerCompany || '',\n  customerAddress: item.customerAddress || '',\n  customerCity: item.customerCity || '',\n  customerPhone: item.customerPhone || '',\n  \n  // Invoice notes\n  notes: item.notes || 'Thank you for your business!',\n  termsConditions: item.termsConditions || 'Payment is due within the specified terms. Late payments may incur additional charges.'\n};\n\nreturn { json: { ...item, ...companyDefaults } };"
      },
      "typeVersion": 2
    },
    {
      "id": "232fc78f-fbfd-444e-9a8a-ee9639d9e10d",
      "name": "Generate Invoice HTML",
      "type": "n8n-nodes-base.code",
      "position": [
        -432,
        -80
      ],
      "parameters": {
        "jsCode": "// Generate professional invoice HTML\nconst item = $input.first().json;\n\n// Payment status styling\nconst getStatusColor = (status) => {\n  const colors = {\n    'paid': { bg: '#10b981', text: 'PAID' },\n    'unpaid': { bg: '#ef4444', text: 'UNPAID' },\n    'partial': { bg: '#f59e0b', text: 'PARTIALLY PAID' }\n  };\n  return colors[status.toLowerCase()] || colors['unpaid'];\n};\n\nconst statusStyle = getStatusColor(item.paymentStatus);\n\nconst html = `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Invoice - ${item.invoiceNumber}</title>\n    <style>\n        @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');\n        * { margin: 0; padding: 0; box-sizing: border-box; }\n        body { font-family: 'Inter', sans-serif; line-height: 1.6; color: #1f2937; background: #ffffff; }\n        .container { max-width: 800px; margin: 0 auto; padding: 40px; }\n        .header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 40px; padding-bottom: 20px; border-bottom: 3px solid #3b82f6; }\n        .company-info { flex: 1; }\n        .logo { max-width: 160px; height: auto; margin-bottom: 15px; }\n        .company-name { color: #3b82f6; font-size: 26px; font-weight: 700; margin-bottom: 8px; }\n        .company-details { font-size: 13px; color: #6b7280; line-height: 1.7; }\n        .invoice-badge { text-align: right; }\n        .invoice-title { background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); color: white; padding: 12px 25px; border-radius: 8px; font-size: 22px; font-weight: 700; letter-spacing: 1.5px; margin-bottom: 12px; }\n        .invoice-number { font-size: 15px; color: #1f2937; font-weight: 600; margin-bottom: 8px; }\n        .payment-status { display: inline-block; padding: 6px 16px; border-radius: 20px; font-size: 12px; font-weight: 700; letter-spacing: 1px; color: white; background: ${statusStyle.bg}; margin-top: 8px; }\n        .info-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin-bottom: 40px; }\n        .info-card { background: #f8fafc; padding: 20px; border-radius: 10px; border: 1px solid #e2e8f0; }\n        .info-card h3 { color: #3b82f6; font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 1.2px; margin-bottom: 12px; border-bottom: 2px solid #3b82f6; padding-bottom: 8px; }\n        .info-card p { font-size: 13px; color: #4b5563; margin: 6px 0; }\n        .info-card .name { font-size: 16px; font-weight: 600; color: #1f2937; margin-bottom: 4px; }\n        .items-table { width: 100%; border-collapse: separate; border-spacing: 0; margin-bottom: 25px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.06); border-radius: 10px; overflow: hidden; }\n        .items-table thead { background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); }\n        .items-table th { padding: 14px; text-align: left; font-weight: 600; font-size: 13px; color: white; text-transform: uppercase; }\n        .items-table tbody tr { background: white; }\n        .items-table tbody tr:nth-child(even) { background: #f9fafb; }\n        .items-table td { padding: 14px; border-bottom: 1px solid #e5e7eb; font-size: 13px; color: #374151; }\n        .items-table tbody tr:last-child td { border-bottom: none; }\n        .text-right { text-align: right; }\n        .summary-section { margin-left: auto; width: 350px; }\n        .summary-row { display: flex; justify-content: space-between; padding: 10px 0; font-size: 14px; color: #4b5563; }\n        .summary-row.subtotal { font-weight: 500; border-top: 1px solid #e5e7eb; padding-top: 12px; }\n        .summary-row.total { border-top: 3px solid #3b82f6; margin-top: 12px; padding-top: 15px; font-weight: 700; font-size: 18px; color: #1e40af; background: #eff6ff; padding: 15px; border-radius: 8px; }\n        .payment-info { margin-top: 40px; padding: 25px; background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%); border-left: 5px solid #10b981; border-radius: 8px; }\n        .payment-info h3 { color: #065f46; font-size: 16px; font-weight: 700; margin-bottom: 15px; }\n        .payment-info p { color: #047857; font-size: 13px; margin: 6px 0; }\n        .payment-info strong { color: #064e3b; }\n        .notes-section { margin-top: 30px; padding: 20px; background: #fef3c7; border-left: 4px solid #f59e0b; border-radius: 6px; }\n        .notes-section h3 { color: #92400e; font-size: 14px; font-weight: 700; margin-bottom: 10px; }\n        .notes-section p { color: #78350f; font-size: 13px; line-height: 1.6; }\n        .footer { margin-top: 40px; padding-top: 20px; border-top: 2px solid #e5e7eb; text-align: center; color: #6b7280; font-size: 12px; }\n        .footer p { margin: 5px 0; }\n        @media print { body { print-color-adjust: exact; -webkit-print-color-adjust: exact; } }\n    </style>\n</head>\n<body>\n    <div class=\"container\">\n        <div class=\"header\">\n            <div class=\"company-info\">\n                ${item.companyLogo ? `<img src=\"${item.companyLogo}\" alt=\"${item.companyName}\" class=\"logo\">` : `<h1 class=\"company-name\">${item.companyName}</h1>`}\n                <div class=\"company-details\">\n                    ${item.companyAddress}<br>\n                    ${item.companyCity}<br>\n                    ${item.companyEmail} | ${item.companyPhone}<br>\n                    ${item.companyWebsite}\n                </div>\n            </div>\n            <div class=\"invoice-badge\">\n                <div class=\"invoice-title\">INVOICE</div>\n                <div class=\"invoice-number\">${item.invoiceNumber}</div>\n                <div class=\"payment-status\">${statusStyle.text}</div>\n            </div>\n        </div>\n\n        <div class=\"info-grid\">\n            <div class=\"info-card\">\n                <h3>Bill To</h3>\n                <p class=\"name\">${item.customerName}</p>\n                ${item.customerCompany ? `<p><strong>${item.customerCompany}</strong></p>` : ''}\n                <p>${item.customerEmail}</p>\n                ${item.customerPhone ? `<p>${item.customerPhone}</p>` : ''}\n                ${item.customerAddress ? `<p>${item.customerAddress}</p>` : ''}\n                ${item.customerCity ? `<p>${item.customerCity}</p>` : ''}\n            </div>\n            <div class=\"info-card\">\n                <h3>Invoice Details</h3>\n                <p><strong>Invoice Date:</strong> ${item.invoiceDate}</p>\n                <p><strong>Due Date:</strong> ${item.dueDate}</p>\n                <p><strong>Payment Terms:</strong> ${item.paymentTerms}</p>\n                ${item.purchaseOrderNumber ? `<p><strong>PO Number:</strong> ${item.purchaseOrderNumber}</p>` : ''}\n            </div>\n        </div>\n\n        <table class=\"items-table\">\n            <thead>\n                <tr>\n                    <th style=\"width: 50%;\">Description</th>\n                    <th class=\"text-right\" style=\"width: 15%;\">Quantity</th>\n                    <th class=\"text-right\" style=\"width: 17%;\">Rate</th>\n                    <th class=\"text-right\" style=\"width: 18%;\">Amount</th>\n                </tr>\n            </thead>\n            <tbody>\n                ${item.items.map(lineItem => `\n                <tr>\n                    <td>${lineItem.description}</td>\n                    <td class=\"text-right\">${lineItem.quantity}</td>\n                    <td class=\"text-right\">${item.currencySymbol}${lineItem.rate.toFixed(2)}</td>\n                    <td class=\"text-right\"><strong>${item.currencySymbol}${lineItem.amount.toFixed(2)}</strong></td>\n                </tr>\n                `).join('')}\n            </tbody>\n        </table>\n\n        <div class=\"summary-section\">\n            <div class=\"summary-row subtotal\">\n                <span>Subtotal:</span>\n                <span>${item.currencySymbol}${item.subtotal.toFixed(2)}</span>\n            </div>\n            ${item.discountAmount > 0 ? `\n            <div class=\"summary-row\">\n                <span>Discount:</span>\n                <span>-${item.currencySymbol}${item.discountAmount.toFixed(2)}</span>\n            </div>\n            ` : ''}\n            <div class=\"summary-row\">\n                <span>Tax (${item.taxRate}%):</span>\n                <span>${item.currencySymbol}${item.taxAmount.toFixed(2)}</span>\n            </div>\n            <div class=\"summary-row total\">\n                <span>Total Amount:</span>\n                <span>${item.currencySymbol}${item.total.toFixed(2)}</span>\n            </div>\n        </div>\n\n        <div class=\"payment-info\">\n            <h3>\ud83d\udcb3 Payment Information</h3>\n            <p><strong>Bank Name:</strong> ${item.bankName}</p>\n            <p><strong>Account Number:</strong> ${item.accountNumber}</p>\n            <p><strong>Routing Number:</strong> ${item.routingNumber}</p>\n            ${item.swiftCode ? `<p><strong>SWIFT Code:</strong> ${item.swiftCode}</p>` : ''}\n            ${item.taxId ? `<p><strong>Tax ID:</strong> ${item.taxId}</p>` : ''}\n            ${item.gstNumber ? `<p><strong>GST Number:</strong> ${item.gstNumber}</p>` : ''}\n            ${item.paymentLink ? `<p style=\"margin-top: 12px;\"><strong>\ud83d\udcb0 Pay Online:</strong> <a href=\"${item.paymentLink}\" style=\"color: #047857; text-decoration: underline;\">${item.paymentLink}</a></p>` : ''}\n        </div>\n\n        ${item.notes ? `\n        <div class=\"notes-section\">\n            <h3>\ud83d\udcdd Notes</h3>\n            <p>${item.notes}</p>\n        </div>\n        ` : ''}\n\n        <div class=\"footer\">\n            <p><strong>${item.companyName}</strong></p>\n            <p>${item.termsConditions}</p>\n            <p style=\"margin-top: 10px;\">Questions? Contact us at ${item.companyEmail} or ${item.companyPhone}</p>\n        </div>\n    </div>\n</body>\n</html>\n`;\n\nreturn {\n  json: {\n    html: html,\n    invoiceNumber: item.invoiceNumber,\n    customerName: item.customerName,\n    customerEmail: item.customerEmail,\n    total: item.total,\n    currency: item.currency,\n    paymentStatus: item.paymentStatus,\n    fileName: `Invoice_${item.invoiceNumber}_${item.customerName.replace(/[^a-zA-Z0-9]/g, '_')}.pdf`,\n    ...item\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "88557c37-4406-49ea-92fb-1f96d7127f8d",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -272,
        -272
      ],
      "parameters": {
        "color": 7,
        "width": 280,
        "height": 340,
        "content": "## PDF & Storage\n\nConverts HTML to print-ready PDF with preserved formatting, then archives to Google Drive with descriptive filename for searchability, compliance, and easy sharing."
      },
      "typeVersion": 1
    },
    {
      "id": "fa21eb40-1c81-4c0c-8517-6b3305ba136f",
      "name": "HTML to PDF",
      "type": "n8n-nodes-htmlcsstopdf.htmlcsstopdf",
      "position": [
        -256,
        -80
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "268db052-2990-4760-8cc0-457aa25b3fdc",
      "name": "Save to Google Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -96,
        -80
      ],
      "parameters": {
        "name": "={{ $('Generate Invoice HTML').item.json.fileName }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "root"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "f1e750d4-15f7-4b59-8b9c-33e252677333",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        64,
        -288
      ],
      "parameters": {
        "color": 7,
        "width": 280,
        "height": 368,
        "content": "## Customer Delivery\n\nEmails invoice PDF to customer with payment instructions, bank details, and due date reminder. Instant delivery improves cash flow by reducing payment delays."
      },
      "typeVersion": 1
    },
    {
      "id": "eaa80439-09ea-4ccc-91b1-030cc0b1e149",
      "name": "Is Payment Received?",
      "type": "n8n-nodes-base.if",
      "position": [
        432,
        -80
      ],
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $('Generate Invoice HTML').item.json.paymentStatus }}",
              "value2": "paid",
              "operation": "equals"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f05925be-b9d1-428b-8e0a-a55c29854209",
      "name": "Notify Team - Paid",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        656,
        -176
      ],
      "parameters": {
        "url": "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK",
        "options": {},
        "jsonBody": "={\n  \"text\": \"\u2705 Invoice Paid & Delivered!\",\n  \"blocks\": [\n    {\n      \"type\": \"section\",\n      \"text\": {\n        \"type\": \"mrkdwn\",\n        \"text\": \"*\ud83d\udcb0 Payment Received*\\n\\n*Invoice:* {{ $('Generate Invoice HTML').item.json.invoiceNumber }}\\n*Customer:* {{ $('Generate Invoice HTML').item.json.customerName }}\\n*Amount:* {{ $('Generate Invoice HTML').item.json.currency }} {{ $('Generate Invoice HTML').item.json.total }}\\n*Status:* PAID\\n\\n<{{ $('Save to Google Drive').item.json.webViewLink }}|View Invoice in Drive>\"\n      }\n    }\n  ]\n}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.1
    },
    {
      "id": "bed6dcd1-1c79-4fa9-8ac3-7f65e6168505",
      "name": "Notify Team - Unpaid",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        656,
        32
      ],
      "parameters": {
        "url": "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK",
        "options": {},
        "jsonBody": "={\n  \"text\": \"\u23f3 Invoice Sent - Payment Pending\",\n  \"blocks\": [\n    {\n      \"type\": \"section\",\n      \"text\": {\n        \"type\": \"mrkdwn\",\n        \"text\": \"*\ud83d\udce4 Invoice Sent*\\n\\n*Invoice:* {{ $('Generate Invoice HTML').item.json.invoiceNumber }}\\n*Customer:* {{ $('Generate Invoice HTML').item.json.customerName }}\\n*Amount:* {{ $('Generate Invoice HTML').item.json.currency }} {{ $('Generate Invoice HTML').item.json.total }}\\n*Status:* {{ $('Generate Invoice HTML').item.json.paymentStatus }}\\n*Due Date:* {{ $('Generate Invoice HTML').item.json.dueDate }}\\n\\n<{{ $('Save to Google Drive').item.json.webViewLink }}|View Invoice in Drive>\"\n      }\n    }\n  ]\n}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.1
    },
    {
      "id": "3d20247f-67bf-40de-a517-591f63408bcd",
      "name": "Send to Customer",
      "type": "n8n-nodes-base.gmail",
      "position": [
        144,
        -80
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    }
  ],
  "connections": {
    "HTML to PDF": {
      "main": [
        [
          {
            "node": "Save to Google Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook Trigger": {
      "main": [
        [
          {
            "node": "Validate Invoice Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send to Customer": {
      "main": [
        [
          {
            "node": "Is Payment Received?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Payment Received?": {
      "main": [
        [
          {
            "node": "Notify Team - Paid",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Notify Team - Unpaid",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save to Google Drive": {
      "main": [
        [
          {
            "node": "Send to Customer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Invoice HTML": {
      "main": [
        [
          {
            "node": "HTML to PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Invoice Data": {
      "main": [
        [
          {
            "node": "Enrich with Company Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Enrich with Company Data": {
      "main": [
        [
          {
            "node": "Generate Invoice HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}