Skip to content

After this module you can chase every unpaid invoice politely and on time, without ever double-sending, and get a weekly accounts-receivable summary.

What it does

Entry What happens
Weekdays 9 AM (Stripe) or POST /webhook/ar/run (invoices in the body) Load open invoices (Stripe REST API via HTTP Request with the Stripe credential), work out days past due in your timezone, pick the one reminder that's due (3 days before → due today → +3 → +10 → final at +21 with the owner in cc → escalate to the owner at +30), send it with Gmail, record it, and build an aging summary (emailed on Mondays)
POST /webhook/ar/pause Pause an invoice until a date (promise to pay) or indefinitely (dispute); resume: true undoes it
GET /webhook/ar/status?invoice_id=… Reminder history for one invoice

Rules: skip paid/void, balances under $5, invoices with no due date, and customers on the do-not-chase list; at least 3 days between emails; if runs were missed, send only the latest stage (no burst); escalate only 7 days after the final notice. Body options: now (inject the clock), dry_run, record_only (mark as sent without emailing, for importing existing invoices), summary, source: "stripe".

Flow

Weekdays 9 AM / Chase Run API ─┐
Pause API ─────────────────────┼→ Settings → Route ─run→ Invoices from API? ─no→ Get Stripe Invoices ─┐
Status API ────────────────────┘                  │                         └yes──────────────────────┴→ Normalize Invoices → Plan Reminders
                                                  │     → Send Now? → Send Reminder (Gmail) → Record and Summarize → respond (API) / Email A/R Summary (Mondays)
                                                  ├pause→ Pause Invoice → respond
                                                  └status→ Invoice Status → respond

Verification status (n8n 2.43.6)

  • 30 behavior checks (60 assertions) without credentials: stage selection and catch-up, skip rules, email content (amount, date, pay link), aging buckets and summary, Monday summary, a full 30-day timeline (via record_only + injected clock), 3-day gap, final → escalate after 7 days, pause/dispute/resume, Stripe-format mapping (cents, unix dates, hosted link), Gmail and Stripe failures reported, failed sends retried next run.
  • Not run with Gmail or Stripe credentials (WITH_CREDS=1 TEST_EMAIL=… [STRIPE=1] ./test/test.sh). The Stripe request has not been made against a real account.

Files

File Tier Purpose
lesson.md Free Step-by-step build, tone guidance
workflow/starter.json Free Triggers, Stripe fetch, normalization
workflow/learner.json Learner Finished workflow
workflow/code/ Learner Readable copies of the Code nodes
exercises.md Learner Practice tasks
solutions.md Learner Exercise solutions
notes.md Private Learning log
sell/ Private Offer, video script, blog post