Stop Chasing Unpaid Invoices Manually — Automate It with n8n

작성자

카테고리:

← 피드로
DEV Community · AgoraIntelligence · 2026-07-27 개발(SW)

Stop Chasing Unpaid Invoices Manually — Automate It with n8n

If you’re a freelancer or small business owner, you know the drill: invoice sent, due date passes, silence. You draft a polite reminder, send it, wait. Draft a firmer one. Hate yourself a little. Repeat.

This tutorial shows how to build a fully automated invoice follow-up system with n8n that sends escalating reminders on its own — and stops the moment someone pays.

The Problem with Manual Follow-Up

Manual invoice chasing fails in predictable ways:

  • You forget (you’re busy running the actual business)
  • You remember at 11pm and decide to send it “tomorrow”
  • Tomorrow you forget again
  • 45 days overdue you finally send a strongly-worded email that damages the relationship

Automation solves all three failure modes. The system doesn’t forget, doesn’t feel awkward, and stops exactly when it should.

How the Workflow Works

The system reads a Google Sheets invoice list every morning and applies simple date logic:

For each invoice where status = "unpaid":
  - 3 days overdue → send reminder_1 (friendly)
  - 7 days overdue → send reminder_2 (firmer)
  - 14+ days overdue → send reminder_3 (urgent) + Slack alert to you
  - Already sent today → skip

Enter fullscreen mode Exit fullscreen mode

When you mark an invoice as paid in the sheet, the system automatically stops. No code needed.

The Google Sheets Structure

Create a sheet with these exact headers:

client_name client_email amount currency invoice_date due_date status last_email_sent notes Acme Corp [email protected] 2500 EUR 2026-07-01 2026-07-15 unpaid
  • status: unpaid / paid / disputed / skip
  • last_email_sent: filled automatically by the workflow
  • notes: optional context for the AI-generated emails

The Three Email Tiers

Tier 1 — Friendly Reminder (3 days overdue)

Subject: Invoice {{invoice_number}} — Just a quick reminder

Hi {{client_name}},

I hope all is well. I wanted to send a friendly reminder that invoice 
{{invoice_number}} for {{amount}} {{currency}} was due on {{due_date}}.

If payment has already been sent, please disregard this message. 
If you have any questions, I'm happy to help.

Best regards,
{{your_name}}

Enter fullscreen mode Exit fullscreen mode

Tier 2 — Direct Follow-Up (7 days overdue)

Subject: Invoice {{invoice_number}} — Payment overdue

Hi {{client_name}},

I'm following up on invoice {{invoice_number}} for {{amount}} {{currency}}, 
which was due on {{due_date}} and remains outstanding.

Could you confirm when we can expect payment? 
If there's an issue I can help resolve, please let me know.

{{your_name}}

Enter fullscreen mode Exit fullscreen mode

Tier 3 — Escalation (14+ days overdue)

Subject: Urgent: Invoice {{invoice_number}} — 14 days overdue

Hi {{client_name}},

Invoice {{invoice_number}} for {{amount}} {{currency}} is now 14 days overdue.
This is my final reminder before I escalate this matter further.

Please arrange payment by {{date_5_days_from_now}} or contact me to discuss.

{{your_name}}

Enter fullscreen mode Exit fullscreen mode

At Tier 3, the workflow also sends a Slack message to alert you that this invoice needs your personal attention.

Key n8n Nodes

1. Schedule Trigger — runs every day at 8am

2. Google Sheets Read — reads all rows where status = unpaid

Uses HTTP Request to Sheets API v4 (not the native node — it’s unreliable for filtered reads):

GET https://sheets.googleapis.com/v4/spreadsheets/{{SHEET_ID}}/values/Sheet1!A:I

Enter fullscreen mode Exit fullscreen mode

3. Code Node — Calculate Days Overdue

const today = new Date();
return items.map(item => {
  const dueDate = new Date(item.json.due_date);
  const daysOverdue = Math.floor((today - dueDate) / (1000 * 60 * 60 * 24));
  const lastSent = item.json.last_email_sent 
    ? new Date(item.json.last_email_sent) 
    : null;
  const sentToday = lastSent && lastSent.toDateString() === today.toDateString();

  return {
    json: {
      ...item.json,
      daysOverdue,
      sentToday,
      tier: daysOverdue >= 14 ? 3 : daysOverdue >= 7 ? 2 : daysOverdue >= 3 ? 1 : 0
    }
  };
});

Enter fullscreen mode Exit fullscreen mode

4. IF Node — filters to tier > 0 AND NOT sentToday

5. Switch Node — routes to the correct email template based on tier

6. Gmail/SMTP Send — sends the email

7. Google Sheets Update — marks last_email_sent with today’s date

8. IF Node (Tier 3 only) — sends Slack alert

The Stop Logic

This is the most important part: the system never emails a paid client.

The workflow reads the status column first. If status is paid, disputed, or skip, the row is filtered out before any date calculation. Change the status in the sheet → emails stop immediately, no workflow restart needed.

Results: What to Expect

From building this for several service businesses:

  • Average days-to-payment drops from 28 to 11 when automated reminders are active
  • Fewer awkward conversations — clients treat automated reminders differently than personal ones
  • Zero maintenance once set up — it just runs every morning

The psychological trick: clients know automated systems don’t hold grudges. They pay the automated reminder without the social friction of ignoring a personal message.

Costs

  • n8n: $0 self-hosted
  • Gmail API: Free (standard Gmail limits apply)
  • Google Sheets: Free
  • Slack: Free for basic webhooks

Total: $0/month if you’re already using these tools.

Get the Ready-to-Import Workflow

The complete workflow JSON — with all nodes configured, the Sheets template, and Gmail/SMTP setup guide — is available at n8nmarkets.com. Search “Invoice Chaser Auto Follow-Up”.

Includes: workflow JSON, Google Sheets template with exact headers, 3 email templates in English and Spanish, and a troubleshooting guide for common Gmail OAuth issues.

What’s your current average days-to-payment? And has automated follow-up changed that number for you? Curious to see real data in the comments.

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다