Skip to main content

Terms, Reminders and Credits

Payment terms​

Terms & Reminders sets the global due-date rule, which each customer can override.

Terms are a relationship with the party that is invoiced, so they belong to the customer rather than to a site: two branches of one enterprise cannot promise different due dates on one document.

Due dates can be expressed as days from the invoice date, or as a day of the following month. The computed due date is printed on the invoice and is required before an invoice can be pushed to an accounting package.

An invoice with no due date is a push blocker rather than being pushed with a guessed one.

Reminders​

Reminders chase unpaid invoices on a schedule you define: a list of offsets relative to the due date, each with its own message.

A typical schedule is a courtesy notice three days before the due date, a first reminder on the day after, then escalating notices at seven, fourteen and thirty days.

Reminders are configured globally and overridden per customer, since the reminder chases a document and a document belongs to one party.

What stops a reminder​

  • The invoice is paid. Payment sync from the accounting package is what keeps this accurate, so verify sync is running before enabling reminders. A card payment cancels the remaining reminders as soon as the Stripe webhook lands, which is seconds for a card and days for a bank debit.
  • The invoice is void.
  • The tenant has no billing recipients.
  • The invoice was externally delivered and the tenant is configured for the accounting package to chase it.
The reminder hour is a floor

Reminder ticks run hourly from container boot. A reminder configured for 09:00 is sent somewhere within that hour, not exactly at 09:00. It is never sent early.

A pass that correctly skips everything logs nothing

If a reminder pass evaluates every invoice and correctly decides to send none, it writes no log line. An absence of reminder logging therefore means either "nothing was due" or "the tick did not run", and the two are not distinguishable from the log alone. Check docker compose logs api for scheduler activity generally.

Overdue alerts​

Two detectors watch due dates:

  • invoice_overdue — past due by more than the grace period. Default grace is three days, because post takes a day and a bank transfer takes three, and an alert on the morning after every due date is an alert nobody reads.
  • invoice_overdue_unsent — past due and never sent, which is a different and more urgent problem.

Severity escalates from medium to high after the escalation threshold, default fourteen days. Both thresholds are configurable under Detection.

Credits​

A credit is money you owe the customer: a service failure, a billing error, a goodwill gesture.

  • Credits apply after tax, because the amount is money already owed and taxing it again would be wrong.
  • Credits attach to an invoice as an adjustment link, not as a decrement of a balance. Voiding the invoice therefore restores the credit rather than destroying it.
  • Credit application is audited.

Credits and external tax​

Credits can only be raised in Vodia Billing when Vodia Billing owns the tax: self-billed tenants, and Xero tenants.

On a QuickBooks tenant the credit control is greyed out and the API refuses the request. Raise the credit note in QuickBooks, which owns the total.

Payments​

Payments arrive three ways.

Synced from the accounting package, on an interval configured under Settings. Each synced payment records a reference naming the invoice.

Recorded by hand for self-billed tenants, from the invoice.

Paid online by card or bank debit through Stripe, where the customer is unbound and online payment is switched on for them. The row is written when the money actually arrives, which is seconds after checkout for a card and days for a bank debit.

For QuickBooks tenants, the QuickBooks total is the authority for what is owed, so paid and unpaid state follows QuickBooks rather than the internally computed figure.

Refunds are not credits​

A credit reduces what the customer owes. A refund restores it: the money went back, so the invoice is unpaid again and will be chased again.

A Stripe refund therefore arrives as a negative row in the payment ledger — a reversing entry — rather than as a credit or as the deletion of the original payment. If the refund was a goodwill gesture rather than a correction, raise a credit note as well, or the reminder ladder will chase money you gave back. An alert says so at the time, with the new outstanding figure in it.

A row that came from Stripe cannot be unapplied by hand. Refund it in the Stripe dashboard and the reversal arrives here on its own.

Worked examples​

Payment terms​

Global default, overridable per customer:

RuleInvoice datedDue
Net 142026-09-012026-09-15
Net 302026-09-012026-10-01
Day 20 of following month2026-09-012026-10-20

An invoice with no computed due date cannot be pushed to an accounting package. It is reported as a blocker rather than pushed with a guessed date.

A reminder schedule​

OffsetMessage
-3 daysCourtesy notice: invoice due Friday
+1 dayFirst reminder
+7 daysSecond reminder
+14 daysEscalation — account may be suspended
+30 daysFinal notice

Applied to INV-00151, dated 2026-09-01 with Net 14 terms:

Due 2026-09-15

2026-09-12 courtesy notice sent
2026-09-16 first reminder sent
2026-09-19 payment received -> remaining reminders cancelled
2026-09-22 second reminder SKIPPED (paid)

Payment sync from the accounting package is what makes that cancellation work. Verify sync is running before you enable reminders, or a paid customer gets chased.

Overdue alerts on the same invoice, unpaid​

overdueGraceDays: 3, overdueEscalateDays: 14:

2026-09-15   due
2026-09-16 nothing — inside grace
2026-09-18 nothing — inside grace
2026-09-19 invoice_overdue 4 days severity medium
2026-09-29 invoice_overdue 14 days severity high (escalated)

Three days of grace exists because post takes a day and a bank transfer takes three. An alert on the morning after every due date is an alert nobody reads.

An invoice that was never sent​

invoice_overdue_unsent   INV-00157   due 2026-09-15, never sent   high

A different and more urgent problem than an unpaid invoice: the customer cannot pay something they never received. Usually a missing recipient or an SMTP failure at the send stage.

A credit, and a void restoring it​

2026-09-05   Credit 50.00 issued to Acme Corp
reason: outage 2026-08-22, 4 hours
2026-09-05 Credit applied to INV-00151
887.29 - 50.00 = 837.29 due

2026-09-08 INV-00151 VOIDED (wrong tax profile)
credit of 50.00 RESTORED to Acme Corp

2026-09-08 INV-00159 issued, 887.29
credit of 50.00 applied -> 837.29 due

The credit survived the void because it is an adjustment link, not a decrement of a balance. A system that had subtracted 50.00 from a running balance would have lost it.

Credits on a QuickBooks tenant​

POST /api/credits  { tenant: "acme-qbo.example.com", amount: 5000 }
409 Conflict — tenant tax is owned by QuickBooks Online.
Raise the credit note in QuickBooks.

The control is greyed out in the interface and the API refuses it. A credit computed against a total Vodia Billing does not own would disagree with the accounting record.