DEV Community

T.M. Gunderson
T.M. Gunderson

Posted on

I Built a Working Invoice Follow-Up Agent in n8n (Here's the Full Workflow JSON)

Every "AI for small business" article gives you prompts. Here's something more useful: a complete, working n8n workflow you can import and run today.

The problem it solves: small businesses have an average of $47K in outstanding receivables, and 39% of invoices are paid late (FreshBooks data). Following up manually works, but nobody does it consistently.

This automation watches your inbox for unpaid invoices, drafts polite follow-up emails, and logs everything to a spreadsheet. Total setup time: 20 minutes.


What You'll Need

  • n8n (self-hosted or cloud — free tier works)
  • Gmail (the inbox receiving invoice replies)
  • Google Sheets (for the tracking log)
  • OpenAI API key (for drafting follow-up emails)

That's it. No Zapier, no Make, no paid integrations. Just n8n + Gmail + Sheets + OpenAI.


The Workflow Logic

Every 6 hours
  → Check Gmail for invoice-related emails from last 7 days
  → For each email:
      → OpenAI: "Is this about an unpaid or overdue invoice?"
      → If YES:
          → OpenAI: "Draft a polite follow-up email"
          → Save draft to Gmail (doesn't auto-send — you review first)
          → Log to Google Sheet: sender, amount, days overdue, follow-up sent
      → If NO:
          → Skip
Enter fullscreen mode Exit fullscreen mode

Key design choice: it saves drafts, not sends emails. You review each one before it goes out. No risk of sending something embarrassing to a client.


The Full n8n Workflow JSON

Copy this entire block and import it into n8n (Settings → Import Workflow):

{
  "name": "Invoice Follow-Up Agent",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [6]
        }
      },
      "id": "cron-trigger",
      "name": "Every 6 Hours",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.1,
      "position": [240, 300]
    },
    {
      "parameters": {
        "operation": "search",
        "searchQuery": "subject:(invoice OR payment OR billing OR overdue OR past due) newer_than:7d",
        "returnAll": false,
        "limit": 20
      },
      "id": "gmail-search",
      "name": "Search Invoices",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [460, 300]
    },
    {
      "parameters": {
        "operation": "classify",
        "model": "gpt-4o-mini",
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "You are an assistant that classifies emails. Respond with ONLY 'YES' or 'NO'."
            },
            {
              "role": "user",
              "content": "Is this email about an unpaid, overdue, or past-due invoice that needs follow-up?\n\nSubject: {{ $json.subject }}\n\nFrom: {{ $json.from }}\n\nBody: {{ $json.text }}" 
            }
          ]
        },
        "options": {
          "temperature": 0.1
        }
      },
      "id": "classify-invoice",
      "name": "Is Unpaid Invoice?",
      "type": "n8n-nodes-base.openAi",
      "typeVersion": 1.6,
      "position": [680, 300]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.message.content }}",
              "operation": "equals",
              "value2": "YES"
            }
          ]
        }
      },
      "id": "filter-yes",
      "name": "Only Unpaid",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [900, 300]
    },
    {
      "parameters": {
        "operation": "generate",
        "model": "gpt-4o-mini",
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "You are a professional, friendly business assistant. Write concise follow-up emails about overdue invoices. Never be aggressive or threatening. Assume positive intent — they probably forgot. Keep emails under 100 words."
            },
            {
              "role": "user",
              "content": "Draft a polite follow-up email for this overdue invoice:\n\nSubject: {{ $('Search Invoices').item.json.subject }}\nFrom: {{ $('Search Invoices').item.json.from }}\nBody: {{ $('Search Invoices').item.json.text }}\n\nRequirements:\n- Reference the invoice specifically\n- Assume they forgot (not avoiding)\n- Ask for expected payment date\n- Keep it under 100 words\n- Professional but warm tone"
            }
          ]
        },
        "options": {
          "temperature": 0.7
        }
      },
      "id": "draft-email",
      "name": "Draft Follow-Up",
      "type": "n8n-nodes-base.openAi",
      "typeVersion": 1.6,
      "position": [1120, 200]
    },
    {
      "parameters": {
        "operation": "create",
        "to": "={{ $('Search Invoices').item.json.from }}",
        "subject": "={{ 'Re: ' + $('Search Invoices').item.json.subject }}",
        "body": "={{ $json.message.content }}",
        "options": {
          "draft": true
        }
      },
      "id": "save-draft",
      "name": "Save Gmail Draft",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [1340, 200]
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": "YOUR_SPREADSHEET_ID",
        "sheetName": "Invoice Follow-Ups",
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Date": "={{ $now.toFormat('yyyy-MM-dd HH:mm') }}",
            "Sender": "={{ $('Search Invoices').item.json.from }}",
            "Subject": "={{ $('Search Invoices').item.json.subject }}",
            "Follow-Up Draft": "={{ $('Draft Follow-Up').item.json.message.content.substring(0, 100) }}",
            "Status": "Draft saved — awaiting review"
          }
        }
      },
      "id": "log-sheet",
      "name": "Log to Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.3,
      "position": [1560, 200]
    }
  ],
  "connections": {
    "Every 6 Hours": {
      "main": [
        [
          {
            "node": "Search Invoices",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search Invoices": {
      "main": [
        [
          {
            "node": "Is Unpaid Invoice?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Unpaid Invoice?": {
      "main": [
        [
          {
            "node": "Only Unpaid",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Only Unpaid": {
      "main": [
        [
          {
            "node": "Draft Follow-Up",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Draft Follow-Up": {
      "main": [
        [
          {
            "node": "Save Gmail Draft",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Gmail Draft": {
      "main": [
        [
          {
            "node": "Log to Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Setup Instructions

1. Import the Workflow

In n8n: Menu → Import from Clipboard → paste the JSON above.

2. Connect Your Credentials

You'll need three credentials in n8n:

Credential Where to Get It
Gmail OAuth2 n8n → Credentials → Gmail → Connect (uses same auth as gog)
OpenAI API platform.openai.com/api-keys
Google Sheets OAuth2 n8n → Credentials → Google Sheets → Connect

3. Create the Tracking Sheet

Make a Google Sheet with these columns:

  • Date | Sender | Subject | Follow-Up Draft | Status

Copy the Spreadsheet ID from the URL (the long string between /d/ and /edit) and paste it into the documentId field in the "Log to Sheet" node.

4. Customize the Gmail Search

The default search finds emails from the last 7 days with "invoice", "payment", "billing", "overdue", or "past due" in the subject. Adjust the search query to match your business:

subject:(invoice OR payment OR billing OR overdue OR past due) newer_than:7d
Enter fullscreen mode Exit fullscreen mode

Common tweaks:

  • Add your business name: subject:(invoice OR payment) from:(*@clientdomain.com)
  • Look in body too: remove subject: prefix
  • Change time range: newer_than:14d for two weeks

5. Test Before Activating

Click "Execute Workflow" in n8n to run it once manually. Check:

  • Did it find relevant emails?
  • Did the AI classify them correctly?
  • Are the draft emails professional and accurate?
  • Is the Google Sheet logging correctly?

When you're happy, Activate the workflow. It runs every 6 hours automatically.


Cost Breakdown

Component Cost
n8n (self-hosted) Free
Gmail Free
Google Sheets Free
OpenAI API (gpt-4o-mini) ~$0.01 per email classified + $0.02 per draft = ~$3/month for 20 invoices

Total: ~$3/month to follow up on every overdue invoice automatically.

Compare that to the average small business with $47K in outstanding receivables and 39% late payment rate. If this automation gets even one invoice paid 2 weeks faster per month, it pays for itself 50x over.


What This Doesn't Do (Honest Limitations)

This workflow doesn't:

  • Auto-send emails (you review drafts first — by design)
  • Track payment status in accounting software (you'd need a QuickBooks/Xero integration for that)
  • Handle complex payment disputes (the AI drafts follow-ups, not negotiations)
  • Work for businesses that don't communicate with clients via email

For businesses that need full invoice tracking with accounting software integration, the Contractor Estimating Kit includes a complete invoice tracking template that connects to QuickBooks.


Why This Approach Works

I've tried the "just use prompts" approach. It doesn't stick because you have to remember to run the prompt, paste the email, and send the follow-up manually. The whole point of automation is that it happens without you thinking about it.

The n8n approach works because:

  1. It runs on a schedule — no remembering required
  2. It saves drafts, not sends — you stay in control
  3. It logs everything — you can see what's been followed up on
  4. It costs $3/month — less than a coffee

This is one of 5 "boring automations" that have the highest ROI for small businesses. The Boring Automation Pack has the other 4 (email triage, appointment confirmations, review requests, and client onboarding) as complete n8n workflows.


Next Steps

  1. Copy the workflow JSON
  2. Import into n8n
  3. Connect Gmail + OpenAI + Sheets credentials
  4. Test once manually
  5. Activate and let it run

If you build this, I'd love to hear how it works for you. Drop a comment with what you automated and what broke — that's how we all learn.


We're SMB Scale Up — building practical AI tools and automations for small businesses. The AI Automation Cheat Sheet has 10 more workflows you can set up this week. Free download.

Honest note: We've made closer to $0 than we'd like to admit from these tools. We're sharing what we're learning as we build, not claiming expertise from a thriving business. Take every recommendation with appropriate skepticism.

Top comments (0)