Home / Recipes / Job complete → invoice → payment-link reminder ladder
Problem 3: Invoices sit unpaid for weeks
Job complete → invoice → payment-link reminder ladder
When an invoice is created in Jobber, the customer gets a text with a pay link (a single-use Stripe Payment Link for the exact balance, or Jobber's own client-hub link). Unpaid invoices get reminders on day 3, 7 and 14; at day 21 the owner gets a list instead of the customer getting more texts.
The problem
Slow payment ties up cash you've already earned. Industry surveys put the average at 38 days to get paid.
- Average 38 days to payment; about 80% of contractors name timely billing as a top strategy. Source: ServiceTitan press release: technology adoption and bid conversion (Software vendor survey)
- Chasing unpaid invoices comes up in plumbers' threads about admin load (anecdotal). Source: r/Plumbing thread: biggest admin headache (Anecdote (Reddit); read via search summary, not opened directly)
Who it's for
Shops that bill after the job and wait on homeowners or property managers to pay. Works with Stripe or with Jobber Payments. Jobber Connect and up already include automatic invoice reminders; this recipe adds texted pay links, partial-payment handling and an owner hand-off.
Tools and monthly cost
| Tool | Official price |
|---|---|
| Twilio US SMS, sent or received | $0.0083 per 160-character segment, plus carrier fees of about $0.0035-$0.005 per segment pricing page |
| Stripe card payments (Payment Links have no extra fee) | 2.9% + 30c per successful US card payment pricing page |
| Jobber Payments (alternative to Stripe) | 2.9% + 30c per card payment, 1% ACH (per Jobber pricing page) pricing page |
| n8n | Community Edition: free if you self-host (you pay for the server). n8n Cloud: from EUR 20 / month (Starter) or EUR 50 (Pro) pricing page |
| Jobber (you probably already pay for it) | Core from $29 / month billed annually ($49 monthly); Connect from $99 (built-in quote and invoice follow-ups); Grow from $149 pricing page |
Example month: Illustrative arithmetic. Assume 50 invoices a month, half paid after the first text and the rest getting 2 reminders: about 125 texts of 2 segments = 250 segments x $0.0083 = $2.08 plus about $0.90-$1.25 carrier fees. No AI is used. Card fees are the same 2.9% + 30c whether you use Stripe or Jobber Payments, and you would pay them anyway once a customer pays by card. Plus n8n and the shared Twilio number.
Setup
- In Jobber's Developer Center, subscribe your app to the INVOICE_CREATE webhook and point it at the workflow's Jobber webhook URL. Jobber signs each delivery with your client secret; set JOBBER_CLIENT_SECRET so the workflow can verify it.
- Choose PAYMENT_MODE=stripe (needs a Stripe secret key; links are single-use and carry the Jobber invoice id in metadata) or PAYMENT_MODE=jobber (uses the invoice's client-hub link, no Stripe).
- Import workflow.json, set business name, time zone, owner phone and Twilio values, and adjust reminder days (3 / 7 / 14) and the 21-day hand-off in 'Decide reminders'.
- When a payment comes in, record it in Jobber as usual (or via Stripe's Jobber integration); the daily sweep reads the balance from Jobber and stops when it's zero. In Stripe mode a paid link also stops reminders right away, and the owner gets one text to record that payment in Jobber.
- Check the invoices query filter in GraphiQL, then send yourself a test invoice before turning the schedule on.
Download
Download invoice-payment-reminders.zip
Contains the n8n workflow, AI prompts, the mock data, the test runner with its last results, and the mock server we tested against. All keys in .env.example are fake.
Test result
Every workflow was imported into n8n 2.45.4 and run end to end on our test machine. Twilio, Jobber and Stripe were replaced by a local mock server that accepts the same request shapes as their documented APIs and records every call. The AI steps used a small local model (Qwen2.5-3B-Instruct, 4-bit) and the speech-to-text steps used Whisper base.en running locally. Mock data (customers, quotes, invoices, recordings) is invented. Nothing was sent to a real phone, customer or account.
Stripe mode: 9/9 scenarios passed (run 2026-10-27)
| PASS | W1 | Jobber INVOICE_CREATE (signed) for today's water-heater job -> Stripe link for $489.00 -> text to customer |
| PASS | W2 | Jobber retries the same delivery (at-least-once): no second text |
| PASS | W3 | Forged call with a wrong signature: ignored, Jobber not even queried |
| PASS | W4 | Webhook for an invoice that is already paid: no text |
| PASS | S1 | Daily sweep Oct 27: first reminders on 3/7/14-day-old invoices (partial payment billed at its $150 balance), 21-day one to owner, paid + opted-out skipped |
| PASS | S1b | Sweep re-run the same day: nothing sent twice |
| PASS | S2 | Oct 30: tankless invoice paid in the meantime (stops); today's invoice gets reminder 1 reusing its link; 7+ day ones get reminder 2 |
| PASS | S3 | Nov 3: customer paid part of #2201 by check (balance $200): new link for the new balance; #2188 hits day 21 -> owner, no more texts |
| PASS | S4 | Nov 10: last automatic reminders; #2195 reaches day 21 -> owner |
Jobber Payments mode: 5/5 scenarios passed (run 2026-10-27)
| PASS | W1 | Jobber INVOICE_CREATE (signed) for today's water-heater job -> Stripe link for $489.00 -> text to customer |
| PASS | W2 | Jobber retries the same delivery (at-least-once): no second text |
| PASS | W3 | Forged call with a wrong signature: ignored, Jobber not even queried |
| PASS | S1 | Daily sweep Oct 27: first reminders on 3/7/14-day-old invoices (partial payment billed at its $150 balance), 21-day one to owner, paid + opted-out skipped |
| PASS | S2 | Oct 30: tankless invoice paid in the meantime (stops); today's invoice gets reminder 1 reusing its link; 7+ day ones get reminder 2 |
Live Stripe test mode (Jobber + Twilio mocked): 8/8 scenarios passed (run 2026-10-27)
| PASS | L1 | invoice created -> real test-mode payment link |
| PASS | L2 | paid with test card 4242 on the real Checkout page |
| PASS | L3 | sweep S1 (2026-10-27) |
| PASS | L3 | sweep S1b (2026-10-27) |
| PASS | L3 | sweep S2 (2026-10-30) |
| PASS | L3 | sweep S3 (2026-11-03) |
| PASS | L3 | sweep S4 (2026-11-10) |
| PASS | L4 | owner told once that #2210 was paid by Stripe link |
Actual output from the test run
First text in scenario W1 (Stripe mode). Names and numbers are invented.
to +15555550148: Hi Kevin, thanks for choosing Ridgeline Heating & Plumbing. Your invoice #2210 (water heater thermocouple + relight) for $489.00 is ready. Pay securely here: https://buy.stripe.com/test_c2d42cb2cbbb Reply STOP to opt out.
Verified live in Stripe test mode (2026-10-27)
Real Stripe API in test mode (sandbox, no real money). Jobber and Twilio were still mocked.
- Real Stripe test-mode sandbox: a new invoice (#2210, $489.00) created a real Price and single-use Payment Link with the Jobber invoice id in metadata, and the first text carried the real buy.stripe.com link.
- The link was paid on Stripe's real Checkout page with test card 4242 4242 4242 4242; the Checkout Session came back complete and paid ($489.00) and Stripe switched the single-use link off.
- Paid detection: Jobber (mocked) still showed #2210 unpaid, yet the next four daily sweeps sent it no reminders, and the owner got exactly one 'paid by Stripe link' text.
- Partial payment on #2201: a new $200.00 link was created and the old link was set to inactive in Stripe.
- All other invoices followed the same reminder ladder as the mock run (8/8 live steps passed). Jobber and Twilio stayed mocked; no real money, no texts or emails to anyone.
Verified with mocks
- Signed Jobber webhook accepted; forged signature rejected before Jobber is queried; duplicate deliveries (Jobber retries) send only one text.
- Already-paid, zero-balance and opted-out invoices skipped.
- Stripe mode: price + single-use Payment Link created for the exact balance; the same link is reused while the balance is unchanged and a new one is made after a partial payment ($150 paid, new $200 link), with the old link switched off.
- Jobber mode: same flow using the client-hub link, no Stripe calls (5/5 scenarios).
- Reminder ladder over simulated dates, invoice paid mid-ladder stops, day-21 owner digest sent once.
Documented from official API docs only
Built to the vendor's documentation but not run against a live account. Check these on yours.
- Jobber webhook payload, HMAC-SHA256 signature header and the 1-second acknowledgement rule (Jobber docs).
- Jobber invoices query filter syntax: assumed from a community schema copy. Check in GraphiQL.
Limitations
- Stripe paid detection reads up to 100 completed checkouts from the last 35 days per sweep; a busier account needs pagination. It was tested with a USD card payment only (Stripe may show customers abroad their local currency).
- Texts include a link, so each is 2 SMS segments.