invoice-reminder-sheets
Sheet-driven invoice reminder for freelancers, consultants, and small businesses. Reads an InvoiceLog Sheet, finds rows whose due_date has passed, and sends a personalized reminder email to each overdue client referencing their specific invoice number, amount, and days past due. Escalates tone across three stages — friendly → follow-up → final — and stamps each row to prevent duplicate chases.
Why this exists
The original invoice-reminder hub workflow reads a local CSV and then sends ONE generic email body ("This is a friendly reminder that your invoice is now 14 days old") regardless of which client is overdue or for how much. That's not a real reminder system — it's a placebo.
This variant fixes both gaps: - The data lives in a Sheet you edit on your phone, not a CSV on the server's filesystem. - The email body includes the actual invoice number, amount, due date, and days past due, addressed to the actual client by name. - The tone escalates: a 7-day-past-due reminder reads differently from a 60-day-past-due one. - A stamp on each row prevents re-chasing every day for the same invoice.
Setup
- Credentials (Credentials view):
-
google-workspace— Google Workspace service-account JSON - Runtime environment (Runtime Environments view):
-
python— auto-created on every install - InvoiceLog Sheet (one-time):
- Create a Sheet with a tab
InvoiceLogand 10 columns:A invoice_no | B client_name | C client_email | D invoice_date E due_date | F amount | G currency | H status I last_reminder | J notes- Row 1 is the header. Data starts at row 2. - You maintain A–G and J. The workflow updates H and I. - Status flow: leave H blank oropenwhen an invoice is sent → workflow sets it toreminded-1after first chase,reminded-2after second,reminded-3+after subsequent → you set it topaidorwritten-offwhen the matter closes. - Edit
workflow.yaml— replace the three placeholders: -<<INVOICE_LOG_SHEET_ID>>— spreadsheet ID from the Sheet's URL -<<YOUR_NAME_OR_BUSINESS>>— used in the email signature -<<OWNER_PUBLISHER>>— user name for the daily "what got sent" summary - Schedule once daily, 9:00 AM (or whenever you'd want to send chase emails).
Reminder cadence
| Status when workflow sees row | Threshold to send | Sets status to | Tone |
|---|---|---|---|
open (or blank) |
days past due ≥ 7 | reminded-1 |
friendly: "this is a friendly reminder…" |
reminded-1 |
14 days since last reminder | reminded-2 |
follow-up: "I sent a reminder a couple weeks ago…" |
reminded-2 |
14 days since last reminder | reminded-3+ |
final: "this is a final reminder, please remit within 7 days…" |
reminded-3+ |
14 days since last reminder | stays reminded-3+ |
final (continues) |
paid, written-off |
— | — | ignored |
Thresholds are constants at the top of the python script — adjust to your collection policy.
Pipeline
- chase —
runtimeenv(python). ReadsInvoiceLog!A2:J, decides per row which reminder stage applies (if any), sends the corresponding personalized email, updates the row's status + last_reminder columns. Prints a summary. - notify-self —
message. Pipes the summary to your owner user so you see, every morning, what got sent (or "No invoices need a reminder today").
Sample summary
INVOICE REMINDERS — Monday, May 11, 2026
Sent 3 reminder(s):
[1st] INV-2026-044 Acme Corp (9 days past due)
[2nd] INV-2026-031 Beta Services (28 days past due)
[FINAL] INV-2026-018 Gamma Engineering (62 days past due)
Customization
- Thresholds —
FIRST_AFTER_DAYS,ESCALATE_AFTER_DAYSat the top of the chase script. Aggressive:5/10. Patient:14/30. Default:7/14. - Email wording — three body templates in the script (one per stage). Edit to match your voice; the placeholders for client name, invoice number, amount, and days past due all stay available.
- CC your accountant on stage-3+ — add
--cc [email protected]to the third stage'sgog gmail sendcall. - Send a copy to yourself — add
--bcc [email protected]to all sends. - Different currencies in one Sheet — already handled via column G; the email body uses the row's currency verbatim.
- Don't escalate past stage-2 — change the third stage's status update to
pausedand have your accountant or attorney take over. The workflow will then skip those rows.
Companion artifacts
quote-followup(mech-eng workflow) — same pattern for outstanding quotesshop-status-digest(mech-eng workflow) — could be extended to count overdue invoices in the morning digest
Verified
gog sheets get/update syntax, gog gmail send --to/--subject/--body flags, and the pipe-separated multi-cell update format all verified against the bundled gog v0.19.0 (2026-06-01); re-verify output shapes on first run. Status-stage state machine logic walked manually against worked examples.
Source
See workflow.yaml.