Zum Hauptinhalt springen

Invoices

Lifecycle

An invoice moves through four states.

Draft — generated for a period. Recurring charges are created from snapshots, usage is gathered, tax is computed, guards are evaluated. A draft can be regenerated freely and holds no invoice number.

Finalized — the invoice is fixed. It receives its number, its detail is frozen, and it becomes the document you send.

Sent — emailed to the tenant's billing recipients, or handed to the accounting package that emails it.

Void — cancelled. The number is retained. Any credits applied to it are restored.

Vodia Billing 10

Vodia Billing 101

Guards

Finalization is blocked, per tenant, by any of these:

  • Unreviewed trunks with traffic in the period
  • Unrated legs — calls that matched no rate row
  • Unapproved one-time charges
  • Unpriced recurring subtypes — an entity type with no rate at any frequency
  • No billing recipients, when the run is set to email
  • A duplicate invoice for the same period
  • A sibling invoice already pushed to the accounting package

Blocked tenants are reported and skipped. They never stop the rest of the run and never consume an invoice number.

Guards are re-checked at finalization, not just at draft time, so a blocker that appeared in between still stops that tenant.

Numbering

Invoice numbers are fleet-wide and gapless. There is one sequence across every tenant and every system.

The number is allocated as the last step of a successful finalization. A failure part-way through therefore does not burn a number. A void retains its number, because a gap in a numbered sequence is an accounting problem and a voided document is a legitimate record.

Because the sequence is gapless, bill runs finalize tenants sequentially rather than in parallel.

Periods are cut on call start

An invoice period includes a call if the leg started inside it, not if the call was rated inside it.

This matters in three places. Archive recovery imports rate calls today that happened last month, and they must land on last month's invoice. An invoice must be reproducible from the same rule that produced it. And the frozen call detail must agree with the totals above it.

Frozen detail

At finalization, the invoice's line summary, inclusion summary and call detail are frozen onto the invoice document. Later changes to rate sheets, tax profiles or plan configuration cannot alter an issued invoice.

Inbound calls appear in the frozen call detail with no amount, so a customer can see the call happened without being charged for it.

Templates and languages

Settings → Templates holds the invoice template library. Each template carries branding, business identity, footer text and a language.

Thirteen languages are supported: English, Catalan, German, Greek, Spanish, Finnish, French, Italian, Japanese, Dutch, Portuguese, Russian and Turkish. Translation falls back to English per key, so a partially translated template renders rather than showing blanks.

Assign a template per tenant. Tenants with none inherit the default.

Each invoice can carry a share link: a URL the customer can open to see the invoice and its call detail without logging in.

  • Invoice-scoped, so one link exposes one invoice
  • Revocable at any time
  • Audited on creation and on revocation
  • Carries no cost and no margin data, ever

Invoice emails include a link to the call detail derived from the share URL, so the customer can drill into the calls behind a usage line.

PDF

Print the invoice page from the browser. There is no separate PDF renderer, and browser print output is what the invoice layout is designed against.

One-time charges

Raised per tenant, priced from the Catalogue or entered directly. One-time charges must be approved before they appear on an invoice; an unapproved charge blocks finalization rather than being silently dropped.

One-time charges fall in the goods tax bucket.

Reclassifying a call

Spend → reclassify re-rates a single leg against any destination on the tenant's sell plan. This is the "mark as international" case: a number the sheet priced as national that should not have been.

The original rating is preserved on the record and the change is audited. It is refused once the call has been invoiced, because at that point the invoice is the document and changing the call underneath it would make the two disagree.

Voiding

Voiding an invoice retains its number, restores any credits that were applied to it, and is audited. An invoice already pushed to an accounting package must also be voided or credited there; Vodia Billing does not reach into the accounting package to reverse it.

Worked examples

A finalized invoice

INVOICE INV-00151                        Northwind Telecom
1 Example Plaza, Seattle WA
Bill to: Acme Corp Tax ID 00-0000000
NW-1041
Issued: 2026-09-01
Period: 2026-08-01 to 2026-08-31 Due: 2026-09-15

USAGE
US National 1,240.00 min 0.012 14.88
United Kingdom 86.00 min 0.035 3.01
UK Mobile 12.00 min 0.14 1.68
US Toll Free (inbound) 318.00 min included 0.00
--------
19.57

RECURRING
Extensions 42 12.00 504.00
Hunt groups 3 5.00 15.00
DID numbers 18 1.50 27.00
Managed support plan 1 150.00 150.00
--------
696.00

ONE-TIME
Desk handset 1 89.00 89.00
--------
89.00

Subtotal 804.57
Sales Tax 8.25% 66.38
USF 1% 0.20
PUC 2% 0.39
911 Fee x45 15.75
--------
TOTAL USD 887.29

1,338 calls in this period. Full call detail: <share link>

Inbound calls appear with no amount, so the customer sees the traffic without being charged for it. Full arithmetic in Worked Example.

Reading the blockers on a draft

Draft: hq.northwind-example.com  2026-08
BLOCKED (3)
unreviewed_trunk carrier-secondary (412 legs, 1,204 min)
unrated_legs 7 legs to prefix 351
unpriced_recurring attendant (2 instances, no rate at any frequency)
not_due (1)
Annual licence — billing month September

Three blockers and one note. The not_due line is not a problem: an annual charge outside its billing month is reported so you can see it exists.

Each blocker has one fix:

unreviewed_trunk    -> Trunks: classify carrier-secondary
unrated_legs -> Plans: add a destination for prefix 351 (Portugal)
unpriced_recurring -> Plans -> Recurring: add a rate for `attendant`

Numbering across a run

Bill run 2026-08, finalize stage
hq.northwind-example.com INV-00151 887.29 sent
branch.northwind-example.com BLOCKED — no recipients
west.northwind-example.com INV-00152 1,204.60 sent
east.northwind-example.com INV-00153 531.40 SEND FAILED (SMTP timeout)
south.northwind-example.com INV-00154 642.15 sent

Note what happened to the numbers. branch was blocked at prepare and consumed none. east finalized successfully as INV-00153 and then failed at the send stage, so its number and its invoice both stand — only the email failed. A tenant that failed during finalization would have consumed no number at all, because the number is allocated as the last step of a successful finalization.

Retrying the run re-sends only east, because send state is per invoice.

A void

INV-00151   887.29   VOID   2026-09-03  (wrong tax profile applied)
credit of 50.00 restored to Acme Corp

The number is retained. A gap in a numbered sequence is an accounting problem, and a voided document is a legitimate record. The credit that had been applied comes back and can go on the replacement invoice.