T

TechIdea

Ecosystem

Back to n8n Projects
Intermediate Level

n8n Invoice Payment Chase Automation Project: Step-by-Step Tutorial

Automate overdue invoice reminders by scheduling daily checks of accounting spreadsheets, filtering overdue clients, and sending personalized chase emails.

The Problem

Automate overdue invoice reminders by scheduling daily checks of accounting spreadsheets, filtering overdue clients, and sending personalized chase emails.

Real-World Use Case

Automate overdue invoice reminders by scheduling daily checks of accounting spreadsheets, filtering overdue clients, and sending personalized chase emails.

Technology Stack

Familiarity with n8n Schedule trigger nodes

Prerequisite

Understanding of IF conditional nodes in n8n

Prerequisite

Connected Gmail or SMTP node credentials

Prerequisite

Architecture & Design

Folder Structure

n8n_workflows/
├── payment_chase.json
└── README.md

Step-by-Step Implementation

1

Configure Schedule trigger node to run every morning at 9:00 AM.

### Step 1: Schedule Trigger Setup Add Schedule trigger node. Configure cron expression for daily morning execution.

n8n
{
  "name": "Overdue Invoice Payment Chase",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 9
            }
          ]
        }
      },
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1,
      "position": [
        200,
        300
      ]
    },
    {
      "parameters": {
        "operation": "read",
        "sheetId": "spreadsheet_id_here"
      },
      "name": "Read Invoices",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 2,
      "position": [
        420,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.status }}",
              "value2": "Overdue"
            }
          ]
        }
      },
      "name": "Check Overdue",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        640,
        300
      ]
    },
    {
      "parameters": {
        "recipient": "={{ $json.client_email }}",
        "subject": "Overdue Invoice Reminder - #{{ $json.invoice_id }}",
        "body": "Hi {{ $json.client_name }},\n\nThis is a reminder that invoice #{{ $json.invoice_id }} for ${{ $json.amount }} is overdue. Please arrange payment.\n\nThank you!"
      },
      "name": "Send Gmail",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2,
      "position": [
        880,
        200
      ]
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Read Invoices",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Invoices": {
      "main": [
        [
          {
            "node": "Check Overdue",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Overdue": {
      "main": [
        [
          {
            "node": "Send Gmail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Code Explanation

Implementation step

2

Fetch invoice records from Google Sheets.

### Step 2: Data Fetching & Filter Logic Add Google Sheets node to read rows, then add IF node evaluating status.

n8n
{
  "name": "Overdue Invoice Payment Chase",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 9
            }
          ]
        }
      },
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1,
      "position": [
        200,
        300
      ]
    },
    {
      "parameters": {
        "operation": "read",
        "sheetId": "spreadsheet_id_here"
      },
      "name": "Read Invoices",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 2,
      "position": [
        420,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.status }}",
              "value2": "Overdue"
            }
          ]
        }
      },
      "name": "Check Overdue",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        640,
        300
      ]
    },
    {
      "parameters": {
        "recipient": "={{ $json.client_email }}",
        "subject": "Overdue Invoice Reminder - #{{ $json.invoice_id }}",
        "body": "Hi {{ $json.client_name }},\n\nThis is a reminder that invoice #{{ $json.invoice_id }} for ${{ $json.amount }} is overdue. Please arrange payment.\n\nThank you!"
      },
      "name": "Send Gmail",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2,
      "position": [
        880,
        200
      ]
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Read Invoices",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Invoices": {
      "main": [
        [
          {
            "node": "Check Overdue",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Overdue": {
      "main": [
        [
          {
            "node": "Send Gmail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Code Explanation

Implementation step

3

Add IF node checking if due date is in the past and payment status is 'Unpaid'.

### Step 3: Email Action Add Gmail node. Map client name and invoice amount into email body.

n8n
{
  "name": "Overdue Invoice Payment Chase",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 9
            }
          ]
        }
      },
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1,
      "position": [
        200,
        300
      ]
    },
    {
      "parameters": {
        "operation": "read",
        "sheetId": "spreadsheet_id_here"
      },
      "name": "Read Invoices",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 2,
      "position": [
        420,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.status }}",
              "value2": "Overdue"
            }
          ]
        }
      },
      "name": "Check Overdue",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        640,
        300
      ]
    },
    {
      "parameters": {
        "recipient": "={{ $json.client_email }}",
        "subject": "Overdue Invoice Reminder - #{{ $json.invoice_id }}",
        "body": "Hi {{ $json.client_name }},\n\nThis is a reminder that invoice #{{ $json.invoice_id }} for ${{ $json.amount }} is overdue. Please arrange payment.\n\nThank you!"
      },
      "name": "Send Gmail",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2,
      "position": [
        880,
        200
      ]
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Read Invoices",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Invoices": {
      "main": [
        [
          {
            "node": "Check Overdue",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Overdue": {
      "main": [
        [
          {
            "node": "Send Gmail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Code Explanation

Implementation step

4

Route true matches to Gmail node sending reminder template.

### Step 4: Edge Cases Add error handling to ensure failing email sends don't crash subsequent row processing.

n8n
{
  "name": "Overdue Invoice Payment Chase",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 9
            }
          ]
        }
      },
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1,
      "position": [
        200,
        300
      ]
    },
    {
      "parameters": {
        "operation": "read",
        "sheetId": "spreadsheet_id_here"
      },
      "name": "Read Invoices",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 2,
      "position": [
        420,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.status }}",
              "value2": "Overdue"
            }
          ]
        }
      },
      "name": "Check Overdue",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        640,
        300
      ]
    },
    {
      "parameters": {
        "recipient": "={{ $json.client_email }}",
        "subject": "Overdue Invoice Reminder - #{{ $json.invoice_id }}",
        "body": "Hi {{ $json.client_name }},\n\nThis is a reminder that invoice #{{ $json.invoice_id }} for ${{ $json.amount }} is overdue. Please arrange payment.\n\nThank you!"
      },
      "name": "Send Gmail",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2,
      "position": [
        880,
        200
      ]
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Read Invoices",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Invoices": {
      "main": [
        [
          {
            "node": "Check Overdue",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Overdue": {
      "main": [
        [
          {
            "node": "Send Gmail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Code Explanation

Implementation step

5

Route false matches to no-op termination.

### Step 4: Edge Cases Add error handling to ensure failing email sends don't crash subsequent row processing.

n8n
{
  "name": "Overdue Invoice Payment Chase",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 9
            }
          ]
        }
      },
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1,
      "position": [
        200,
        300
      ]
    },
    {
      "parameters": {
        "operation": "read",
        "sheetId": "spreadsheet_id_here"
      },
      "name": "Read Invoices",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 2,
      "position": [
        420,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.status }}",
              "value2": "Overdue"
            }
          ]
        }
      },
      "name": "Check Overdue",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        640,
        300
      ]
    },
    {
      "parameters": {
        "recipient": "={{ $json.client_email }}",
        "subject": "Overdue Invoice Reminder - #{{ $json.invoice_id }}",
        "body": "Hi {{ $json.client_name }},\n\nThis is a reminder that invoice #{{ $json.invoice_id }} for ${{ $json.amount }} is overdue. Please arrange payment.\n\nThank you!"
      },
      "name": "Send Gmail",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2,
      "position": [
        880,
        200
      ]
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Read Invoices",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Invoices": {
      "main": [
        [
          {
            "node": "Check Overdue",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Overdue": {
      "main": [
        [
          {
            "node": "Send Gmail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Code Explanation

Implementation step

Common Errors

Date formatting mismatch.

Ensure spreadsheet dates match n8n ISO evaluation format.

Security & Performance

Click Execute Workflow manually to verify spreadsheet parsing.

Check that emails are sent only to overdue records.


Send SMS notification via Twilio node.

Update CRM status to 'Chasing' upon email send.

Interview Questions

Q: Can I customize email text per client?

A: Yes, using n8n expressions to inject client names and amounts dynamically.

Growth Newsletter

Get practical AI tools, SEO tips, and growth guides weekly.

Join creators, students, and businesses scaling with TechIdea.