Overdue Invoice Chaser
A self-built project modelled on a real accounting firm brief: chase overdue invoices without anyone remembering to. The workflow reads QuickBooks every morning, works out how far past due each invoice is, and sends a stage-appropriate email with a tone that hardens as the days pass. Anything still unpaid at day 14 stops getting emails and gets escalated to a human via Slack. Every action is logged.

The premise
No client commissioned this one. I set myself a brief that mirrors what a small accounting firm managing invoices for multiple business clients would actually ask for, then built it under the same constraints real client work carries: it has to survive missing data, API failures, and running unattended at 9 AM when nobody is watching.
That last constraint is the one most portfolio automations quietly skip. A workflow that only works on the happy path is a demo. A workflow that tells you when it breaks is a system.
The starting point. Five invoices, four overdue by different margins.The problem
Roughly 60% of invoices are paid late, and chasing them is work nobody wants to own. It is repetitive, mildly uncomfortable, and easy to forget. The invoice that slipped everyone's mind for three weeks is the one that hurts cash flow most.
Manual chasing also tends to be inconsistent. The same client gets a sharp email one month and nothing at all the next, depending on who noticed and what kind of day they were having. Inconsistent chasing trains clients to pay late.
What it does
Every morning at 9 AM, the workflow pulls every unpaid invoice from QuickBooks and calculates how many days past due each one is. Then it routes.
At day 1, a friendly reminder goes out. The tone assumes the invoice was overlooked, because usually it was. At day 3, a firmer follow-up that references the first message. At day 7, a final notice: direct, specific about consequences, still professional.
At day 14, the emails stop. Sending a fourth automated message to someone two weeks overdue is not a workflow problem anymore, it is a relationship problem. Instead, the invoice is logged as escalated and a Slack alert goes to the team so a person picks it up.




Every stage writes a row to Airtable: invoice number, client, amount, days overdue, stage, whether an email was sent, and when.

How it's built
A schedule trigger fires daily at 9 AM. The QuickBooks node fetches unpaid invoices, filtered on balance rather than status, since QuickBooks has no simple unpaid flag and the UI's filter is doing balance math underneath. A code node calculates days overdue and flattens each invoice into a clean object.
An IF node then checks something easy to forget: does this client actually have an email on file? If not, the invoice diverts to its own logging path flagged for manual review. Without that branch, invoices with no email address would silently never get chased and nobody would ever know.
Past that check, a switch node routes on days overdue into four branches. Three send emails via Gmail. The fourth logs and alerts. Every branch writes to Airtable.
Ten nodes. Four routes, two logging paths, one escalation.Treating it like production
Retries on every external call. QuickBooks, Gmail, Airtable and Slack each get three attempts with a five second gap. Transient API failures are normal and shouldn't kill a run. Every node continues on error except the QuickBooks fetch, which stops the workflow: if there is no invoice data at all, there is nothing meaningful to continue with.
A dedicated error handler. A second workflow listens for failures in the first and posts the workflow name, failed node, error message and timestamp to a separate #automation-errors Slack channel. This runs unattended at 9 AM. If it breaks quietly, invoices go unchased for days before anyone notices. Silent failure is the real risk with scheduled automation, not the failure itself.


I tested this by deliberately breaking the QuickBooks credential and letting a scheduled run fail on its own. Worth knowing: n8n's Error Trigger only fires on automatic executions, so manually clicking Execute will never test your error path. That is an easy way to ship an error handler that has never actually run.
A handover document. Every decision, bug and known limitation written down. Which brings me to the part most case studies leave out.
What I didn't build, and why that's in the document
Three gaps are documented rather than hidden.
The routing matches days overdue exactly: 1, 3, 7, 14. If the workflow misses a day, an invoice skips that stage permanently. Range-based routing would fix it but introduces double-send risk if a day gets checked twice. That is a call the person who owns this in production should make, not one I should quietly make for them.
There is no duplicate-send protection. Re-run the workflow manually on the same day and clients get a second copy of the same email. Fixing it means checking Airtable for an existing row before each send.
The day 7 email's language about pausing services and referring to collections is placeholder text. Those are contractual claims. No automation builder should be inventing them on a client's behalf.
Writing down what you didn't build is more useful than pretending the gaps don't exist. The person who inherits this needs to know where the edges are.
Two things that cost the most time
The Slack node posted messages as my personal account rather than the app, despite the app having its own name and icon. The chat:write scope was sitting under User Token Scopes instead of Bot Token Scopes. Moving it and reinstalling didn't fix it either. Rather than keep debugging credential handling, I swapped to a raw HTTP request to Slack's chat.postMessage with the bot token in a header. Worked first try. When a native integration's auth behaviour won't pin down quickly, going direct to the REST API is usually faster than winning the argument.
The second one nearly shipped. The Day 3 email had Day 7's subject line and tone, a copy-paste error while building the third Gmail node. All three templates share the same HTML structure so it was invisible on inspection. Only caught it by comparing a full end-to-end run's actual inbox output against the specified templates. A final-notice email with collections language would have gone to a client three days late. Testing branches in isolation is not the same as testing the whole thing at once.
See it running
The result
Invoices get chased on schedule, in a consistent tone, whether or not anyone remembers. Nothing slips because someone was busy. The team only gets involved at day 14, when a human actually needs to be.
And when it breaks, it says so.
How many of your invoices are quietly sitting past due right now?
Tell me your accounting tool, your payment terms, and how you'd want the follow-ups to sound. I'll build something that chases on schedule and tells you when it can't.
More projects

HubSpot Lead Enrichment
Triggers the moment a new contact lands in HubSpot, researches their company automatically, and updates the record with everything the sales team needs before they make the first call.

AI CV Screener
Reads every CV in a Google Drive folder, scores each one against the job criteria, and outputs a ranked list to Google Sheets. No manual shortlisting.