AutomationFlowsAI & RAG › Send and Track Slack Invoice Requests with Gemini, Google Sheets and Gmail

Send and Track Slack Invoice Requests with Gemini, Google Sheets and Gmail

Byiamvaar @iamvaar on n8n.io

Youtube Video: https://youtu.be/42-oHh9w9Eo This workflow listens for Slack @mentions, uses Google Gemini to classify the request and extract invoice details, then reads and updates Google Sheets, generates invoice PDFs with PdfBro, sends invoices or reminders via Gmail, and…

Event trigger★★★★★ complexityAI-powered36 nodesSlack TriggerGoogle SheetsAgentGoogle Gemini ChatOutput Parser StructuredSlackN8N Nodes PdfbroGmail
AI & RAG Trigger: Event Nodes: 36 Complexity: ★★★★★ AI nodes: yes Added:
Send and Track Slack Invoice Requests with Gemini, Google Sheets and Gmail — n8n workflow card showing Slack Trigger, Google Sheets, Agent integration

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

This workflow follows the Agent → 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
{
  "id": "25LdTcsIANMqpXZr",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Invoice Generation from slack",
  "tags": [],
  "nodes": [
    {
      "id": "df47865c-6d43-4e13-8a72-e0d2a7d9096a",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        320,
        -48
      ],
      "parameters": {
        "width": 480,
        "height": 976,
        "content": "## Untitled workflow\n\n### How it works\n\n1. The workflow triggers when a message is received in Slack.\n2. An AI Agent powered by Google Gemini processes the incoming message and structures the output.\n3. The response is evaluated and routed to one of three specific branches using a Switch node.\n4. Each branch fetches data from Google Sheets and performs a conditional check.\n5. Depending on the branch and condition, the workflow can generate PDFs, send emails via Gmail, and send Slack notifications.\n6. The first branch additionally updates the Google Sheet record after successfully sending an email.\n\n### Setup steps\n\n- [ ] Connect your Slack account in the Slack Trigger and Slack message nodes.\n- [ ] Configure the Google Gemini Chat Model with your Google API credentials.\n- [ ] Authenticate the Google Sheets nodes with your Google workspace account.\n- [ ] Add credentials for PdfBro to enable document generation.\n- [ ] Connect your Gmail account in the Gmail nodes to allow sending emails.\n\n@[youtube](42-oHh9w9Eo)"
      },
      "typeVersion": 1
    },
    {
      "id": "f02bf841-9a59-4d55-b073-b96bca2d99dc",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        944,
        160
      ],
      "parameters": {
        "color": 7,
        "height": 320,
        "content": "## Receive Slack input\n\nTriggers the workflow when a specified Slack event occurs."
      },
      "typeVersion": 1
    },
    {
      "id": "54ad51e1-f574-4a37-bfd0-fe93245e4a18",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1216,
        160
      ],
      "parameters": {
        "color": 7,
        "width": 384,
        "height": 688,
        "content": "## Process AI response\n\nAnalyzes the message using an AI Agent and formats the output."
      },
      "typeVersion": 1
    },
    {
      "id": "d5fa075f-02d2-46d4-af9b-5ec2ab17e558",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1632,
        160
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 352,
        "content": "## Evaluate and route data\n\nChecks conditional logic and branches the execution path."
      },
      "typeVersion": 1
    },
    {
      "id": "61cef101-d1da-4f76-9545-4330ca382695",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2240,
        -320
      ],
      "parameters": {
        "color": 7,
        "width": 672,
        "height": 416,
        "content": "## First branch validation\n\nFetches data from Google Sheets and validates it, sending a Slack message if conditions aren't met."
      },
      "typeVersion": 1
    },
    {
      "id": "016fb74d-9172-4fdb-9055-6d528d1d1310",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2944,
        -320
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 400,
        "content": "## First branch document generation\n\nUses custom code to prepare data, generates a PDF, and sends it via Gmail."
      },
      "typeVersion": 1
    },
    {
      "id": "d8d731bb-7298-4f65-8d54-ab8034259299",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3616,
        -320
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 400,
        "content": "## First branch records update\n\nAppends or updates a row in Google Sheets and sends a final Slack confirmation."
      },
      "typeVersion": 1
    },
    {
      "id": "1b661786-655d-4b07-80a5-f7b242a43643",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2240,
        192
      ],
      "parameters": {
        "color": 7,
        "width": 672,
        "height": 400,
        "content": "## Second branch validation\n\nRetrieves sheet data for the second branch and checks conditions, sending a Slack message on failure."
      },
      "typeVersion": 1
    },
    {
      "id": "390ff2dc-60b5-46f1-90a1-09ce197d398c",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2944,
        192
      ],
      "parameters": {
        "color": 7,
        "width": 672,
        "height": 304,
        "content": "## Second branch document generation\n\nGenerates a PDF document, emails it via Gmail, and confirms completion via Slack."
      },
      "typeVersion": 1
    },
    {
      "id": "f9f42735-356d-4bd0-bb15-f50b7367cf2c",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2240,
        672
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 304,
        "content": "## Third branch validation\n\nFetches relevant Google Sheets data for the third branch and runs a conditional check."
      },
      "typeVersion": 1
    },
    {
      "id": "5ed0e45e-ef93-4c89-8518-dbf07248db08",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2672,
        672
      ],
      "parameters": {
        "color": 7,
        "height": 576,
        "content": "## Third branch notifications\n\nSends specific Slack messages based on the outcome of the conditional check."
      },
      "typeVersion": 1
    },
    {
      "id": "6f4aed92-0d6d-44d6-9811-a6c36791c167",
      "name": "Slack Trigger",
      "type": "n8n-nodes-base.slackTrigger",
      "position": [
        1024,
        336
      ],
      "parameters": {
        "options": {},
        "trigger": [
          "app_mention"
        ],
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0B8VH1M5PX",
          "cachedResultName": "general"
        }
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "25babe12-ea55-4a40-af6f-0c52108f8b66",
      "name": "Route by Intent",
      "type": "n8n-nodes-base.switch",
      "position": [
        1920,
        304
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Send Invoice",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "6ccb4b46-4510-44c1-8e4e-173265184fff",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.output.intention }}",
                    "rightValue": "SEND_INVOICE"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Remind Invoice",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "ad88b917-e2ce-4f45-91f2-57387385afbb",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.output.intention }}",
                    "rightValue": "REMIND_INVOICE"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Check Invoice Status",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "4a6dc9a6-a127-4db3-9d2e-e50e2711ff02",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.output.intention }}",
                    "rightValue": "CHECK_STATUS"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.4
    },
    {
      "id": "1cd40742-85f5-4dcb-a951-1111234617cb",
      "name": "Read Client Bill Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2288,
        -160
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{ $json.output.targetEmail }}",
              "lookupColumn": "email"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1MT2UWqd35kUyFfWwwck1wfD2mwrpbCMTWyOkOapJ5fw/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1MT2UWqd35kUyFfWwwck1wfD2mwrpbCMTWyOkOapJ5fw",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1MT2UWqd35kUyFfWwwck1wfD2mwrpbCMTWyOkOapJ5fw/edit?usp=drivesdk",
          "cachedResultName": "Client Bill"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7,
      "alwaysOutputData": true
    },
    {
      "id": "72349024-a8a1-4b2f-a5a4-052291915073",
      "name": "Intent Classifier Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1264,
        336
      ],
      "parameters": {
        "text": "=User Message: {{ $json.text }}\n\nYou are an intent-and-entity extractor for a Slack invoicing bot. You will receive a raw Slack message. Extract the following fields and return ONLY the structured output \u2014 do not explain, do not add commentary.\n\nCURRENT DATE: {{ $now.toISODate() }} (YYYY-MM-DD). Use this as \"today\" for all relative date resolution.\n\n\n## Step 1 \u2014 Detect intention from the user message\nClassify into exactly one of:\n- SEND_INVOICE \u2014 sending/creating/issuing a new invoice (covers typos: sned, snd, invoic, inv, bil)\n- REMIND_INVOICE \u2014 following up / chasing / nudging about an invoice\n- CHECK_STATUS \u2014 checking if an invoice is paid/pending/status\n- UNKNOWN_INTENT \u2014 none of the above clearly apply\n\nTolerate typos and casual phrasing. If multiple intents seem to apply, pick the one that matches the main verb of the sentence, not a subordinate clause.\n\n## Step 2 \u2014 Extract email\nFind the recipient's email address. If a Slack link like `<mailto:x@y.com|x@y.com>` is present, use the address inside it. Otherwise find any valid email pattern in the text. If no email is present, return null. Never invent an email.\n\n## Step 3 \u2014 Extract due date\nOnly applies when intention is SEND_INVOICE intent\nOtherwise leave dueDate and dueDateRaw as null.\n\nRules, in order:\n1. If the message contains an explicit date (e.g. \"19th jun 2026\", \"jun 19\", \"06/19/2026\"), resolve it to YYYY-MM-DD.\n   - If a year is stated, use it exactly as stated.\n   - If NO year is stated, use the CURRENT YEAR from the date given above. Do NOT roll forward to next year even if that date has already passed this year \u2014 this is for invoices being created right now, so a past-seeming date this year is intentional (e.g. already overdue), not a mistake.\n2. If the message expresses vague uncertainty around a date (e.g. \"maybe\", \"around\", \"roughly\") but a concrete date is still present, extract the concrete date anyway and ignore the hedge word \u2014 do not let hedge words like \"maybe\" leak into the date value.\n3. If NO date is mentioned at all, set dueDate to today's date (the CURRENT DATE given above).\n4. If a date-like phrase is present but cannot be resolved into a real calendar date (invalid day/month combo, ambiguous fragment), set dueDate to null and explain the issue in parseError. Do not guess.\n\nPut the exact matched date phrase from the original text (if any) in dueDateRaw, and the resolved ISO date in dueDate.\n\n\n## Output\nReturn only the structured JSON matching the schema. No prose, no markdown fences, no extra fields.",
        "options": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "retryOnFail": true,
      "typeVersion": 3.1
    },
    {
      "id": "4d3e35e8-baad-4b18-a291-d88e82970672",
      "name": "Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1264,
        560
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-3.1-flash-lite"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "d2bb0457-2a42-4b62-968d-5a4aaa79f46b",
      "name": "Parse Structured Output",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1392,
        560
      ],
      "parameters": {
        "autoFix": true,
        "jsonSchemaExample": "{\n  \"intention\": \"SEND_INVOICE\",\n  \"targetEmail\": \"user@example.com\",\n  \"dueDate\": \"2026-06-19\",\n  \"dueDateRaw\": \"19th jun 2026\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "123ea8fb-54b6-409f-bb01-85a1c17cd1b9",
      "name": "Check Intent Found",
      "type": "n8n-nodes-base.if",
      "position": [
        1680,
        336
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "43ca6a20-9a20-4424-8fed-efaeb97964ff",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.output.intention }}",
              "rightValue": "UNKNOWN_INTENT"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "f88e8505-782e-4c15-b2f9-9c21682beba7",
      "name": "Check If Email Exists",
      "type": "n8n-nodes-base.if",
      "position": [
        2512,
        -160
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "eacca21d-8c52-4059-bdd3-7a4aaa902b72",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.email }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "0e74ea9c-0120-4338-a37d-cf6a8bcbee04",
      "name": "Post Email Missing to Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        2704,
        -80
      ],
      "parameters": {
        "text": "User not found check with the email",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0B8VH1M5PX",
          "cachedResultName": "general"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "0ae38689-99ed-43fa-9585-aad37a1649d9",
      "name": "Generate PDF Invoice",
      "type": "n8n-nodes-pdfbro.pdfBro",
      "position": [
        3216,
        -176
      ],
      "parameters": {
        "dueDate": "={{ $('Intent Classifier Agent').item.json.output.dueDate }}",
        "operation": "invoice",
        "clientName": "={{ $json.client_name }}",
        "quickItems": "={{ $json['active services with bill'] }}",
        "clientEmail": "={{ $json.email }}",
        "companyName": "Blankarray",
        "clientAddress": "={{ $json.client_address }}",
        "invoiceNumber": "={{ `INV-${Date.now()}-${Math.random().toString(36).substring(2, 5).toUpperCase()}` }}",
        "companyAddress": "Nashvalie, USA",
        "invoiceTemplate": "classic"
      },
      "typeVersion": 1
    },
    {
      "id": "9fb627fa-cff1-4179-ae31-2da0c393dc3d",
      "name": "Send PDF via Gmail",
      "type": "n8n-nodes-base.gmail",
      "position": [
        3440,
        -176
      ],
      "parameters": {
        "sendTo": "={{ $('Format Invoice Data').item.json.email }}",
        "message": "=<!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 Enclosed</title>\n</head>\n<body style=\"margin: 0; padding: 0; background-color: #f8fafc; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased;\">\n\n    <table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" style=\"background-color: #f8fafc; padding: 40px 20px;\">\n        <tr>\n            <td align=\"center\">\n                \n                <!-- Main Email Card -->\n                <table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" style=\"max-width: 600px; background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);\">\n                    \n                    <!-- Header -->\n                    <tr>\n                        <td align=\"center\" style=\"background-color: #0f172a; padding: 40px 20px;\">\n                            <h1 style=\"color: #ffffff; font-size: 24px; font-weight: 300; letter-spacing: 2px; margin: 0; text-transform: uppercase;\">\n                                Invoice Enclosed\n                            </h1>\n                        </td>\n                    </tr>\n\n                    <!-- Body Content -->\n                    <tr>\n                        <td style=\"padding: 48px 40px; color: #334155; font-size: 16px; line-height: 1.6;\">\n                            \n                            <p style=\"margin-top: 0; font-size: 18px; color: #0f172a;\">\n                                Hello <strong>{{ $('Format Invoice Data').item.json.client_name }}</strong>,\n                            </p>\n                            \n                            <p style=\"margin-bottom: 24px;\">\n                                Thank you for your continued partnership. Please find your latest invoice attached to this email for your review and records.\n                            </p>\n\n                            <p style=\"margin-bottom: 12px; font-weight: 500; color: #0f172a;\">\n                                Summary of Active Services:\n                            </p>\n\n                            <!-- Dynamic Services Block -->\n                            <div style=\"background-color: #f1f5f9; border-left: 4px solid #3b82f6; padding: 20px; border-radius: 0 6px 6px 0; margin-bottom: 32px;\">\n                                <p style=\"margin: 0; font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; font-size: 14px; color: #475569; white-space: pre-line; line-height: 1.8;\">\n                                    {{ $('Format Invoice Data').item.json['active services with bill'] }}\n                                </p>\n                            </div>\n\n                            <p style=\"margin-bottom: 32px;\">\n                                If you require any clarification regarding these services or the attached invoice, please reply directly to this email and our team will be happy to assist you.\n                            </p>\n\n                            <!-- Sign Off -->\n                            <p style=\"margin: 0; color: #0f172a;\">\n                                Best regards,<br>\n                                <strong>Your Company Name</strong>\n                            </p>\n\n                        </td>\n                    </tr>\n                    \n                    <!-- Footer -->\n                    <tr>\n                        <td align=\"center\" style=\"background-color: #f8fafc; padding: 24px 40px; border-top: 1px solid #e2e8f0;\">\n                            <p style=\"margin: 0; color: #94a3b8; font-size: 13px; line-height: 1.5;\">\n                                &copy; 2026 Your Company Name. All rights reserved.<br>\n                                123 Business Avenue, Suite 100, Tech District\n                            </p>\n                        </td>\n                    </tr>\n                    \n                </table>\n\n            </td>\n        </tr>\n    </table>\n\n</body>\n</html>",
        "options": {
          "attachmentsUi": {
            "attachmentsBinary": [
              {}
            ]
          },
          "appendAttribution": false
        },
        "subject": "Your Invoice At Blankarray"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "34fc47f8-b0b6-44b8-83c1-7dfcaa5ac7e6",
      "name": "Update Invoice Record",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3664,
        -176
      ],
      "parameters": {
        "columns": {
          "value": {
            "name": "={{ $('Read Client Bill Sheet').item.json.client_name }}",
            "email": "={{ $('Read Client Bill Sheet').item.json.email }}",
            "items": "={{ $('Format Invoice Data').item.json['active services with bill'] }}",
            "status": "UNPAID",
            "due_date": "={{ $('Intent Classifier Agent').item.json.output.dueDate }}",
            "invoice_id": "={{ $('Generate PDF Invoice').item.json.invoiceNumber }}",
            "total_amount": "={{ $('Generate PDF Invoice').item.json.subtotal }}",
            "client_address": "={{ $('Read Client Bill Sheet').item.json.client_address }}"
          },
          "schema": [
            {
              "id": "name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "client_address",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "client_address",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "invoice_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "invoice_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "total_amount",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "total_amount",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "items",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "items",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "due_date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "due_date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "invoice_id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1fk__S1VCacA0HFMhA6yY-Xu--uBFrvB4jinOw1J9mV4/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1fk__S1VCacA0HFMhA6yY-Xu--uBFrvB4jinOw1J9mV4",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1fk__S1VCacA0HFMhA6yY-Xu--uBFrvB4jinOw1J9mV4/edit?usp=drivesdk",
          "cachedResultName": "Client Invoices"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "30eaeb30-9d44-4617-ae88-f5b7449a2503",
      "name": "Gemini Parser Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1392,
        752
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-3.1-flash-lite"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "73912726-56ca-444c-907d-f2652b59c46e",
      "name": "Read Client Invoices Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2288,
        336
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{ $json.output.targetEmail }}",
              "lookupColumn": "email"
            },
            {
              "lookupValue": "UNPAID",
              "lookupColumn": "status"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1fk__S1VCacA0HFMhA6yY-Xu--uBFrvB4jinOw1J9mV4/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1fk__S1VCacA0HFMhA6yY-Xu--uBFrvB4jinOw1J9mV4",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1fk__S1VCacA0HFMhA6yY-Xu--uBFrvB4jinOw1J9mV4/edit?usp=drivesdk",
          "cachedResultName": "Client Invoices"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7,
      "alwaysOutputData": true
    },
    {
      "id": "4f3d06bd-1992-4e36-8101-f3d46b58e575",
      "name": "Check Invoice Email Exists",
      "type": "n8n-nodes-base.if",
      "position": [
        2512,
        336
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "eacca21d-8c52-4059-bdd3-7a4aaa902b72",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.email }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "b344be9a-6534-43e2-a516-8bf395042df4",
      "name": "Post Invoice Email Missing to Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        2736,
        416
      ],
      "parameters": {
        "text": "User not found check with the email or no unpaid invoices are there",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0B8VH1M5PX",
          "cachedResultName": "general"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "ab3d072d-8ce7-42e8-9c5e-0ec6b6956c4e",
      "name": "Generate Invoice PDF",
      "type": "n8n-nodes-pdfbro.pdfBro",
      "position": [
        2992,
        320
      ],
      "parameters": {
        "terms": "Payment is Already in DUE.",
        "dueDate": "={{ $('Intent Classifier Agent').item.json.output.dueDate }}",
        "operation": "invoice",
        "clientName": "={{ $json.name }}",
        "quickItems": "={{ $json.items }}",
        "clientEmail": "={{ $json.email }}",
        "companyName": "Blankarray",
        "clientAddress": "={{ $json.client_address }}",
        "invoiceNumber": "={{ $json.invoice_id }}",
        "companyAddress": "Nashvalie, USA",
        "invoiceTemplate": "classic"
      },
      "typeVersion": 1
    },
    {
      "id": "529fe7df-bf6e-4cb2-b67b-ec29a630b399",
      "name": "Send Invoice via Gmail",
      "type": "n8n-nodes-base.gmail",
      "position": [
        3216,
        320
      ],
      "parameters": {
        "sendTo": "={{ $('Check Invoice Email Exists').item.json.email }}",
        "message": "=<!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    <!--[if mso]>\n    <noscript>\n    <xml>\n    <o:OfficeDocumentSettings>\n      <o:PixelsPerInch>96</o:PixelsPerInch>\n    </o:OfficeDocumentSettings>\n    </xml>\n    </noscript>\n    <![endif]-->\n    <style>\n        /* Fallback for clients that strip inline styles */\n        body { margin: 0; padding: 0; width: 100%; background-color: #f4f4f5; }\n        table, td, div, h1, p { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; }\n    </style>\n</head>\n<body style=\"margin: 0; padding: 0; width: 100%; word-break: break-word; -webkit-font-smoothing: antialiased; background-color: #f4f4f5;\">\n    \n    <!-- Main Background Wrapper -->\n    <table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"background-color: #f4f4f5; margin: 0; padding: 0;\">\n        <tr>\n            <td align=\"center\" style=\"padding: 40px 20px;\">\n                \n                <!-- Central White Container -->\n                <table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"max-width: 600px; background-color: #ffffff; border-radius: 8px; border: 1px solid #e5e7eb; overflow: hidden; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);\">\n                    \n                    <!-- Header -->\n                    <tr>\n                        <td style=\"background-color: #0f172a; padding: 30px 40px; text-align: center;\">\n                            <h1 style=\"margin: 0; color: #ffffff; font-size: 24px; font-weight: 600; letter-spacing: 0.5px;\">Gentle Reminder</h1>\n                        </td>\n                    </tr>\n                    \n                    <!-- Body Content -->\n                    <tr>\n                        <td style=\"padding: 40px;\">\n                            <p style=\"margin: 0 0 20px 0; font-size: 16px; color: #374151; line-height: 24px;\">Hi {{ $('Check Invoice Email Exists').item.json.name }},</p>\n                            \n                            <p style=\"margin: 0 0 20px 0; font-size: 16px; color: #374151; line-height: 24px;\">I hope this email finds you well and you're having a great week.</p>\n                            \n                            <p style=\"margin: 0 0 24px 0; font-size: 16px; color: #374151; line-height: 24px;\">This is just a friendly note to remind you that your payment for invoice <strong>{{ $('Check Invoice Email Exists').item.json.invoice_id }}</strong> is currently <strong>{{ $('Check Invoice Email Exists').item.json.status }}</strong>. We have attached a copy of the invoice to this email for your convenience.</p>\n\n                            <!-- Invoice Details Call-Out Box -->\n                            <table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"background-color: #f8fafc; border-radius: 6px; border: 1px solid #cbd5e1; margin-bottom: 28px;\">\n                                <tr>\n                                    <td style=\"padding: 24px;\">\n                                        <table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\n                                            <tr>\n                                                <td style=\"padding-bottom: 16px; border-bottom: 1px solid #e2e8f0;\">\n                                                    <span style=\"font-size: 13px; color: #64748b; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px;\">Amount Due</span><br>\n                                                    <span style=\"font-size: 28px; color: #0f172a; font-weight: bold; line-height: 1.2;\">${{ $('Check Invoice Email Exists').item.json.total_amount }}</span>\n                                                </td>\n                                            </tr>\n                                            <tr>\n                                                <td style=\"padding: 16px 0; border-bottom: 1px solid #e2e8f0;\">\n                                                    <table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\n                                                        <tr>\n                                                            <td align=\"left\" style=\"font-size: 14px; color: #64748b; width: 50%;\">Due Date:</td>\n                                                            <td align=\"right\" style=\"font-size: 15px; color: #0f172a; font-weight: 600; width: 50%;\">{{ $('Check Invoice Email Exists').item.json.due_date }}</td>\n                                                        </tr>\n                                                    </table>\n                                                </td>\n                                            </tr>\n                                            <tr>\n                                                <td style=\"padding-top: 16px;\">\n                                                    <span style=\"font-size: 13px; color: #64748b; display: block; margin-bottom: 8px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px;\">Services / Items</span>\n                                                    <span style=\"font-size: 15px; color: #334155; line-height: 1.6; display: block;\">{{ $('Check Invoice Email Exists').item.json.items }}</span>\n                                                </td>\n                                            </tr>\n                                        </table>\n                                    </td>\n                                </tr>\n                            </table>\n\n                            <p style=\"margin: 0 0 20px 0; font-size: 16px; color: #374151; line-height: 24px;\">If you have already processed this payment, please accept our sincere thanks and simply disregard this message.</p>\n                            \n                            <p style=\"margin: 0 0 28px 0; font-size: 16px; color: #374151; line-height: 24px;\">Please review the attached invoice, and let us know if you have any questions or need further assistance.</p>\n\n                            <p style=\"margin: 0; font-size: 16px; color: #374151; line-height: 24px;\">Best regards,<br><strong style=\"color: #0f172a;\">[Vaar, Blankarray]</strong></p>\n                        </td>\n                    </tr>\n                    \n                    <!-- Footer -->\n                    <tr>\n                        <td style=\"background-color: #f8fafc; padding: 24px 40px; text-align: center; border-top: 1px solid #e2e8f0;\">\n                            <p style=\"margin: 0; font-size: 13px; color: #64748b; line-height: 20px;\">You are receiving this email regarding your account with [Blankarray].</p>\n                            <p style=\"margin: 4px 0 0 0; font-size: 13px; color: #64748b; line-height: 20px;\">[Nash]</p>\n                        </td>\n                    </tr>\n                    \n                </table>\n            </td>\n        </tr>\n    </table>\n</body>\n</html>",
        "options": {
          "attachmentsUi": {
            "attachmentsBinary": [
              {}
            ]
          },
          "appendAttribution": false
        },
        "subject": "Invoice Reminder"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "beed6959-8914-4e52-89d6-d7831071ca68",
      "name": "Read Archived Invoices Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2288,
        800
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{ $json.output.targetEmail }}",
              "lookupColumn": "email"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1fk__S1VCacA0HFMhA6yY-Xu--uBFrvB4jinOw1J9mV4/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1fk__S1VCacA0HFMhA6yY-Xu--uBFrvB4jinOw1J9mV4",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1fk__S1VCacA0HFMhA6yY-Xu--uBFrvB4jinOw1J9mV4/edit?usp=drivesdk",
          "cachedResultName": "Client Invoices"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7,
      "alwaysOutputData": true
    },
    {
      "id": "27ff5c29-70d2-44cf-a7a9-cef3227e0db6",
      "name": "Check Archive Email Exists",
      "type": "n8n-nodes-base.if",
      "position": [
        2512,
        800
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "eacca21d-8c52-4059-bdd3-7a4aaa902b72",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.email }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "251a0778-d450-46d1-a792-8e9ece1c6798",
      "name": "Post Archive Email Missing to Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        2736,
        1088
      ],
      "parameters": {
        "text": "User not found check with the email or no unpaid invoices are there",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0B8VH1M5PX",
          "cachedResultName": "general"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "39a07e1e-74bf-4fc1-8906-b24ad3ba4c2d",
      "name": "Confirm Update to Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        3872,
        -176
      ],
      "parameters": {
        "text": "=Invoice Sent to {{ $('Intent Classifier Agent').item.json.output.targetEmail }} totaling {{ $('Generate PDF Invoice').item.json.subtotal }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0B8VH1M5PX",
          "cachedResultName": "general"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "b31c4a60-83ae-4c5c-b79d-d4f1087a7291",
      "name": "Confirm Invoice Sent to Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        3472,
        320
      ],
      "parameters": {
        "text": "=Reminder Sent For  {{ $('Intent Classifier Agent').item.json.output.targetEmail }}\n\nInvoice totaling is {{ $('Read Client Invoices Sheet').item.json.total_amount }}$",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0B8VH1M5PX",
          "cachedResultName": "general"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "67932621-0f26-4251-8f15-2406a120608b",
      "name": "Post Archive Success to Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        2752,
        864
      ],
      "parameters": {
        "text": "=The attached Invoices is \n\nInvoice totaling is ${{ $json.total_amount }}\n\nInvoice Status is {{ $json.status }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0B8VH1M5PX",
          "cachedResultName": "general"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "c664ddba-64b3-4571-a5d8-9f5d380d9381",
      "name": "Format Invoice Data",
      "type": "n8n-nodes-base.code",
      "position": [
        2992,
        -176
      ],
      "parameters": {
        "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n  item.json.myNewField = 1;\n}\n\nreturn $input.all();"
      },
      "typeVersion": 2
    }
  ],
  "active": true,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "398a215c-cb21-4af2-a169-c8863ada696e",
  "nodeGroups": [],
  "connections": {
    "Slack Trigger": {
      "main": [
        [
          {
            "node": "Intent Classifier Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by Intent": {
      "main": [
        [
          {
            "node": "Read Client Bill Sheet",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Read Client Invoices Sheet",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Read Archived Invoices Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Intent Classifier Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Check Intent Found": {
      "main": [
        [
          {
            "node": "Route by Intent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send PDF via Gmail": {
      "main": [
        [
          {
            "node": "Update Invoice Record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Invoice Data": {
      "main": [
        [
          {
            "node": "Generate PDF Invoice",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini Parser Model": {
      "ai_languageModel": [
        [
          {
            "node": "Parse Structured Output",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Generate Invoice PDF": {
      "main": [
        [
          {
            "node": "Send Invoice via Gmail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate PDF Invoice": {
      "main": [
        [
          {
            "node": "Send PDF via Gmail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check If Email Exists": {
      "main": [
        [
          {
            "node": "Format Invoice Data",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Post Email Missing to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Invoice Record": {
      "main": [
        [
          {
            "node": "Confirm Update to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Client Bill Sheet": {
      "main": [
        [
          {
            "node": "Check If Email Exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Invoice via Gmail": {
      "main": [
        [
          {
            "node": "Confirm Invoice Sent to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Intent Classifier Agent": {
      "main": [
        [
          {
            "node": "Check Intent Found",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Structured Output": {
      "ai_outputParser": [
        [
          {
            "node": "Intent Classifier Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Check Archive Email Exists": {
      "main": [
        [
          {
            "node": "Post Archive Success to Slack",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Post Archive Email Missing to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Invoice Email Exists": {
      "main": [
        [
          {
            "node": "Generate Invoice PDF",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Post Invoice Email Missing to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Client Invoices Sheet": {
      "main": [
        [
          {
            "node": "Check Invoice Email Exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Archived Invoices Sheet": {
      "main": [
        [
          {
            "node": "Check Archive Email Exists",
            "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

Youtube Video: https://youtu.be/42-oHh9w9Eo This workflow listens for Slack @mentions, uses Google Gemini to classify the request and extract invoice details, then reads and updates Google Sheets, generates invoice PDFs with PdfBro, sends invoices or reminders via Gmail, and…

Source: https://n8n.io/workflows/17192/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

This workflow watches Gmail for emails with the subject “Trade Instruction”, uses Google Gemini to extract structured trade fields, validates the result, logs valid trades to Google Sheets, replies to

Google Gemini Chat, Gmail Trigger, Agent +4
AI & RAG

CV → Match → Screen → Decide, all automated

HTTP Request, Information Extractor, Google Sheets +7
AI & RAG

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

HTTP Request, Google Sheets, OpenRouter Chat +5
AI & RAG

This workflow connects Slack with Google Workspace, Cal.com, OpenWeather, and Google Gemini to act as a Slack-based assistant for Gmail, Calendar, Docs, Sheets, Drive, and Contacts, and to post an aut

Slack Trigger, Agent, Google Gemini Chat +12
AI & RAG

This workflow receives a meeting voice recording via webhook, transcribes it with Deepgram, and uses Google Gemini to extract client details and next-step tasks. It then updates GoHighLevel, posts a t

High Level, Agent, Google Gemini Chat +5