Zum Hauptinhalt springen

Worked Example

One tenant, one month, every figure worked out by hand. This is the invoice the Quick Start builds towards, and the same example is referenced throughout the rest of the documentation.

Do this arithmetic yourself on your own first invoice. It is the only way to know a tax profile is right, and it takes ten minutes.

The setup

Partner: Northwind Telecom, billing in USD.

Tenant: hq.northwind-example.com, timezone America/New_York, account reference NW-1041.

Sell plan — "Business Standard USD":

destination,prefix,charge_type,rate,connect_fee,increment_initial,increment_step,included,high_risk
US National,1,per_minute,0.012,0,60,60,,
US Toll Free,1800,free,0,0,0,0,true,
US Premium,1900,per_minute,2.50,0.75,60,60,,true
United Kingdom,44,per_minute,0.035,0,30,6,,
UK Mobile,4477,per_minute,0.14,0,30,6,,
Catch-all,*,per_minute,0.50,0,60,60,,true

Recurring rates on the same plan:

BasisSubtype / prefixFrequencyRate
entityext:usermonthly12.00
entityhuntmonthly5.00
number1206monthly1.50
flat"Managed support plan"monthly150.00

Tax profile — "US Telecom", applied to the tenant:

ComponentKindRateApplies toCounts
Sales Taxpercent8.25%usage, recurring, goods
USFpercent1%usage
PUCpercent2%usage
911 Feeflat0.35recurringentity

One-time charge: one desk handset from the catalogue, $89.00, approved.

Step 1: rating individual calls

Rating happens per call leg, at ingest. Three examples from the month.

A UK landline call, 1 minute 43 seconds

Number:      442079460958
Matched: United Kingdom (prefix 44)
Charge type: per_minute at 0.035
Increments: 30 initial, 6 step

103 seconds of talk time. The first increment is 30 seconds, then 6-second steps for the remaining 73 seconds:

ceil(73 / 6) = 13 steps
30 + (13 x 6) = 108 seconds billed
108 / 60 = 1.80 minutes
1.80 x 0.035 = 0.063 -> 0.06

The same duration on a US national call

Number:      12065550143
Matched: US National (prefix 1)
Charge type: per_minute at 0.012
Increments: 60 initial, 60 step
103 seconds rounds up to 120 seconds billed
120 / 60 = 2.00 minutes
2.00 x 0.012 = 0.024 -> 0.02

Identical talk time, different billed duration. Increments are the single most common reason two billing systems disagree. Check them before anything else.

A premium call, 45 seconds

Number:      19005551234
Matched: US Premium (prefix 1900)
Charge type: per_minute at 2.50, connect fee 0.75
Increments: 60 initial, 60 step
High risk: yes
45 seconds rounds up to 60 seconds = 1.00 minute
1.00 x 2.50 = 2.50
plus connect fee 0.75
= 3.25

Note the connect fee is charged once, on top of the per-minute amount, and only because the call was answered. It is the second most common cause of a reconciliation mismatch.

This call also arms the fraud detectors, because the rate row is marked high_risk. See Fraud and Alerts.

Step 2: the month's usage

Aggregated across every rated leg in the period:

DestinationMinutesRateAmount
US National1,240.000.01214.88
United Kingdom86.000.0353.01
UK Mobile12.000.141.68
US Toll Free (inbound)318.00included0.00
Usage subtotal19.57

Inbound toll-free calls appear on the invoice with no amount, so the customer can see the traffic without being charged for it.

Step 3: recurring quantities

Quantities come from the daily snapshots, and the rule is the highest count observed in the period — not the count on the last day, and not an average.

Extension counts through August:

Aug 1-11:   38 extensions
Aug 12-25: 42 extensions <- peak
Aug 26-31: 40 extensions

The customer is billed for 42. They had 42. A customer who adds ten seats for a fortnight and removes them is billed for having had them.

BasisItemQuantityRateAmount
entityext:user4212.00504.00
entityhunt35.0015.00
numberDIDs matching 1206181.5027.00
flatManaged support plan1150.00150.00
Recurring subtotal696.00

Step 4: goods

ItemQuantityRateAmount
Desk handset189.0089.00
Goods subtotal89.00

One-time charges must be approved first. An unapproved charge blocks finalization rather than being silently dropped.

Step 5: the three tax buckets

usage      19.57
recurring 696.00
goods 89.00
---------------
subtotal 804.57

Subtotals are rounded to cents before tax is computed, which is why the printed lines always sum to the total.

Step 6: tax, component by component

Sales Tax, 8.25%, on all three buckets:

804.57 x 0.0825 = 66.377025  ->  66.38

USF, 1%, on usage only:

19.57 x 0.01 = 0.1957  ->  0.20

PUC, 2%, on usage only:

19.57 x 0.02 = 0.3914  ->  0.39

911 Fee, 0.35 flat, counting entity lines on the recurring bucket:

The quantity is the entity line quantity on this invoice, not the licensed seat count:

42 (ext:user) + 3 (hunt) = 45 entity units
45 x 0.35 = 15.75

Note that the DID line and the flat support plan are recurring but not entities, so they do not attract the 911 fee. That is what counts: entity means.

Tax total:

66.38 + 0.20 + 0.39 + 15.75 = 82.72

Step 7: the invoice

Usage                                    19.57
Recurring 696.00
Goods 89.00
---------
Subtotal 804.57

Sales Tax 8.25% 66.38
USF 1% (usage) 0.20
PUC 2% (usage) 0.39
911 Fee 0.35 x 45 entities 15.75
---------
Tax 82.72

TOTAL USD 887.29

Check it: 804.57 + 82.72 = 887.29.

Variation: a 10% usage discount

Discounts apply before tax, and reach each bucket's base individually. A 10% discount on usage therefore reduces the base that USF and PUC are computed on, not just the sales tax base.

Usage                                    19.57
Usage discount 10% -1.96
---------
Usage net 17.61
Recurring 696.00
Goods 89.00
---------
Subtotal 802.61

Sales Tax 8.25% x 802.61 66.22
USF 1% x 17.61 0.18
PUC 2% x 17.61 0.35
911 Fee 0.35 x 45 15.75
---------
Tax 82.50

TOTAL USD 885.11

USF fell from 0.20 to 0.18 and PUC from 0.39 to 0.35, because the discount reduced the usage base. A system that discounted only the final total would have got both of those wrong.

The discount travels to Xero and QuickBooks as its own negative line, so the accounting package also taxes the discounted base.

Variation: a $50 credit

Credits apply after tax, because a credit is money already owed and taxing it twice would be wrong.

Subtotal                                804.57
Tax 82.72
---------
Invoice total 887.29
Credit applied -50.00
---------
AMOUNT DUE USD 837.29

The credit is recorded as an adjustment link, not as a decrement of a balance. If this invoice is later voided, the $50 credit is restored and can be applied to the next one.

Variation: an inclusion allowance

Suppose the toll-free destination is placed in an inclusion group instead:

Group"US Toll Free"
DestinationsUS Toll Free (1800)
Allowance500 minutes per period
Overflow rate0.008 per minute
Alert at400 minutes

With 640 minutes used in the period:

Allowance         500.00 min   included    0.00
Overflow 140.00 min x 0.008 1.12

Overflow uses the group's overflow rate only — the destination's own connect fee is not applied to overflow minutes.

The invoice prints an inclusion table showing the allowance, the usage and the overflow, so the customer can see why they were charged $1.12 for calls that are nominally free.

At 400 minutes an inclusion_allowance alert fires, which is the point at which you can still call the customer before they are surprised.

What this looks like in the export file

The same invoice as charge rows for a payment system. One row per charge, sell-only, no tax and no totals:

seq,type,tenant,account_ref,period,description,quantity,unit,amount,currency
1041,USAGE,hq.northwind-example.com,NW-1041,2026-08,US National,1240.00,min,14.88,USD
1041,USAGE,hq.northwind-example.com,NW-1041,2026-08,United Kingdom,86.00,min,3.01,USD
1041,USAGE,hq.northwind-example.com,NW-1041,2026-08,UK Mobile,12.00,min,1.68,USD
1041,USAGE,hq.northwind-example.com,NW-1041,2026-08,US Toll Free,318.00,min,0.00,USD
1041,RECURRING,hq.northwind-example.com,NW-1041,2026-08,Extensions,42,ea,504.00,USD
1041,RECURRING,hq.northwind-example.com,NW-1041,2026-08,Hunt groups,3,ea,15.00,USD
1041,RECURRING,hq.northwind-example.com,NW-1041,2026-08,DID numbers,18,ea,27.00,USD
1041,RECURRING,hq.northwind-example.com,NW-1041,2026-08,Managed support plan,1,ea,150.00,USD
1041,ONE_TIME,hq.northwind-example.com,NW-1041,2026-08,Desk handset,1,ea,89.00,USD

Included calls are exported as 0.00 rows rather than omitted, so the receiving system sees the traffic. Tax and invoice totals are never exported — this is a charge feed, not an invoice feed.

What this looks like in Xero

Vodia Billing computes the tax, and Xero records it. The invoice arrives with four tax lines carrying the figures above, and Xero's total is $887.29 — the same number, because Xero is recording what it was given.

A divergence alert on a Xero tenant is therefore a real problem worth investigating.

What this looks like in QuickBooks Online

QuickBooks computes its own tax. The lines arrive without the tax components, QuickBooks applies its own rules, and the QuickBooks total may come out at, say, $881.60 rather than $887.29.

That is expected and correct. QuickBooks is the tax authority for that tenant, so its figure is the one the customer sees, pays, and is chased for. Payment tracking follows the QuickBooks total.

Reconciling against your old system

If your previous system produced a different number for this same month, work through it in this order:

  1. Increments. Compare the billed duration of one specific call, not the monthly total. The 103-second example above bills as 108 seconds on 30/6 and 120 seconds on 60/60. Across a thousand calls that is a visible gap.
  2. Connect fees. Charged once per answered call. Easy to omit from a sheet and invisible in a monthly total.
  3. Which rate row matched. Longest-prefix matching may pick a more specific row than the old system did. 4477 beats 44. Use Rate Test on the number.
  4. Timezone at period boundaries. A tenant in the wrong timezone moves calls near midnight on the 1st and the 31st into the adjacent invoice.
  5. Recurring quantity. Highest count observed, not the count on the last day. A system that sampled month-end would have billed 40, not 42.
  6. Tax base. Whether discounts reduced the tax base, and whether usage-only components were computed on usage alone.

Running in parallel