Skip to main content
Every invoice has a status, and that status only ever moves through a fixed, validated set of transitions — nothing in the bot changes an invoice’s status ad hoc. Attempting an invalid move (marking a draft paid, voiding something already refunded) is rejected outright rather than silently accepted.

The states

Void and Refunded are terminal — nothing moves out of either state.

What each status means

How a transition actually happens

Every status change goes through the same conditional update: it only applies if the invoice is still in the status it was expected to be in at that moment. If two admins act on the same invoice at nearly the same time — say, one voids it while another marks it paid — only the first one to land actually applies; the second gets a clear “this invoice already changed” error instead of silently overwriting the first. The commands and buttons that drive transitions:
  • /invoice create (via the builder’s confirm step) or /payment — Draft → Sent, in the same step that creates the invoice.
  • /invoice mark-paid, or a confirmed crypto verification via /invoice verify — → Paid. See Payment methods for what verification actually checks before this happens.
  • /invoice void — → Void, from Draft, Sent, Pending, or Overdue.
  • /invoice refund — Paid → Refunded.
Voiding an invoice also cancels any active, unpaid payment instructions attached to it (an in-flight crypto quote, for example), so nothing stays waiting on a payment that will never be accepted.

Deleting vs. voiding

/invoice delete permanently removes an invoice, but only works on one that’s currently Draft or Void — anything that’s been Sent has to be voided first. This keeps a voided invoice’s record around by default; delete is a separate, deliberate step.