Part 5 of 7 · Invoice chaser series ~5 min read

How a chase stops on payment

Acme Co. just paid invoice #1042. The most important thing the chaser can do now is the simplest: stop. No more reminders, no awkward “you owe us” email landing the morning after the money cleared. This post walks through how the chaser notices payment and shuts the chase down — and the three things the owner can do from the daily review when an invoice needs a human: pause, mark disputed, and write off.

Key takeaways

  • Payment is detected from the paid column and the accounting feed; the chase stops on the next tick.
  • Three owner actions on the daily review: pause (hold), mark disputed (stop and flag), write off (close out).
  • Each action updates the invoice state and writes an audit row.
  • Pause is bounded — you can only pause a few times before the chaser resumes anyway.
  • The owner’s buttons are a Slack interactive message backed by a Function URL.

Payment stops the chase, then three owner actions

Payment stops the chase, plus three owner actions A diagram showing one input on the left flowing through a small interactive Slack panel, then branching into three action paths. Far left: a "Daily review in Slack" box showing the chaser's summary for an overdue invoice — number, customer, amount, days past due, link to the PDF — with three Slack-button placeholders below: Pause, Disputed, Write off. The owner taps one button. Above all of it, the most common outcome is automatic: when the paid column flips or the accounting feed reports a payment, the chaser sets the invoice state to paid and the chase stops with no button needed. The middle column shows the three manual branches. Branch one, Pause: opens a Slack modal asking how many days to hold (default 7); on save, a Function URL Lambda writes a paused-until row to the ic-state DynamoDB table that suppresses reminders for that invoice until the pause ends. The cadence itself isn't changed. Pause can only be applied a limited number of times per invoice (default three) before the next tick ignores it and resumes. Branch two, Disputed: stops chasing entirely and flags the invoice for a human; the Function URL Lambda sets the state to disputed and posts a note to the finance channel so somebody picks it up. Branch three, Write off: closes the invoice out; the state is set to written-off, the chaser never touches it again, and the row is marked closed in the sheet via the Sheets API. The right side shows the convergence: every action — including the automatic paid stop — writes a row to the ic-audit DynamoDB table with timestamp, invoice id, action, by-user, and notes. A note at the bottom: payment stops the chase automatically — the buttons are for the invoices that need a human, not the ones that just got paid. Daily review number, amount, days [Pause] [Disputed] [Write off] Action 1 Pause • Modal: hold N days (default 7) • ic-state row suppresses reminders until it ends Action 2 Disputed • Stop chasing entirely flag for a human • State set to disputed, posts to finance channel Action 3 Write off • Close the invoice out chaser never touches it • Marked closed in sheet — via the Sheets API Audit trail DynamoDB ic-audit timestamp · invoice_id action · by-user notes Payment stops the chase automatically — the buttons are for invoices that need a human.
Fig 5. Payment stops the chase automatically; three owner actions cover the rest. Pause holds without dismissing. Disputed stops chasing and flags a human. Write off closes the invoice. Every action — including the automatic paid stop — writes to the audit trail.

The automatic stop (the most common by far)

Most invoices end the happy way: the customer pays. The chaser learns about payment two ways. The Drive sheet has a paid column that your accounting export keeps up to date; when it flips to yes, the next tick reads it and sets the invoice state to paid. And if your accounting tool can post payment events to the same kind of webhook used for intake in Part 2, the state flips the same minute the money is recorded — no waiting for the next sync.

When an invoice goes to paid, three things happen, in order. First, the live cadence rows in ic-sends are copied to ic-sends-archive with a chase id, and the live chase is cleared so no further reminders fire. Second, a action: paid row is written to ic-audit with the date and the amount. Third, an optional short thank-you can go out via SES — a one-line “Thanks, we’ve received payment for invoice #1042” that closes the loop warmly. The customer never gets another reminder about an invoice they’ve already settled.

This is the path that matters most, and it needs zero human action. The buttons below are for the invoices that don’t just get paid.

Action 1: pause (the deferral)

Some invoices aren’t paid yet but also shouldn’t be chased right now. The customer asked for a few extra days. The contact is on leave and the backup hasn’t taken over. You’re mid-conversation about the scope and don’t want an automated nudge cutting across it. The owner isn’t ready to stop chasing for good — they just need the chaser quiet for a week.

Pause opens a small modal asking for the number of days, with a 7-day default and a max of 14. On save, a row is written to ic-state with (invoice_id, paused_until). The next day’s tick reads that row in the “already paid or paused?” check from Part 3 and treats the invoice as current until the pause ends. When the pause ends, the chaser re-evaluates the cadence from where it was — if the invoice is now well past the escalation step, the next move is an escalation.

Pause is bounded. The rules doc has a configurable max_pauses_per_chase setting (default three). After that many pauses on the same invoice, further pause attempts are rejected with a “You’ve hit the pause cap on this invoice; please escalate or write it off” reply, and the next tick resumes normally. This is a soft constraint that exists because the most dangerous failure mode is repeatedly snoozing a debt into oblivion.

Action 2: mark disputed (stop and flag)

Sometimes the customer isn’t late — they’re unhappy. They say the work wasn’t finished, the amount is wrong, or they never agreed to that line. Chasing a disputed invoice with cheerful reminders makes a tense situation worse and can cost you the relationship.

Mark disputed sets the ic-state status to disputed, which stops every reminder for that invoice immediately, and posts a note to the finance channel so a human picks it up. The expiry — sorry, the amount and due date — isn’t changed; the invoice is simply taken out of the chaser’s hands until somebody resolves the dispute and either marks it paid, writes it off, or clears the dispute flag so chasing can resume. A disputed invoice that later gets cleared resets cleanly on the next tick.

Action 3: write off (close it out)

Some invoices are never going to be paid. The customer folded. The amount is too small to be worth a fight. A goodwill gesture was agreed. Whatever the reason, the owner wants the invoice off the chase list for good without pretending it was paid.

Write off sets the ic-state status to written-off, marks the row closed in the Drive sheet via the Sheets API, and the chaser never touches it again. The amount is recorded in the audit trail as written off, not paid, so the monthly summary in Part 6 reports it honestly — a written-off invoice with a note (“written off by Sam on 2026-04-15, customer insolvent”) so the trail isn’t a mystery at year-end. Writing off is deliberately a distinct action from marking paid, because the two mean very different things to your books.

Every action is logged, every action is reversible

The ic-audit table records every paid, pause, disputed, and write-off with the user who took the action, the timestamp, and a snapshot of the row before and after. If a wrong status gets set (an invoice marked paid that wasn’t, an invoice written off in error), a team member can run an “undo last action” through a small admin command that reads the previous-state snapshot and restores the row. The undo is itself an audit row, so the trail of edits stays clean.

This kind of reversibility matters most for the money decisions you’ll be asked about later. When the accountant reconciles at year-end, or a customer insists they paid, the audit trail is the only memory anyone has of what actually happened to that invoice and who decided it.

Next post: the cost breakdown. The whole pipeline above runs in coffee-money territory at SMB volume; Part 6 explains exactly where the dollars go and why it’s one of the cheapest systems in the series.

All posts