Zum Hauptinhalt springen

Rate Plans and Sheets

A rate plan is a set of destinations with prices. Tenants get a sell plan (what the customer pays) and optionally a cost plan (what you pay).

Vodia Billing 11 Vodia Billing 12 Vodia Billing 13

Rate sheet format

CSV, parsed by header name. Column order is free and unrecognised columns are ignored, so you can upload a carrier sheet with extra columns untouched.

ColumnRequiredDefaultNotes
destinationyesThe label printed on the invoice, e.g. "Australia Mobile"
prefixyesDigits, or * for a tagged catch-all
charge_typeyesper_minute, per_call or free
rateyesCurrency units; per minute, or flat for per_call
connect_feeno0Charged once per answered call
increment_initialno60Seconds in the first billing increment
increment_stepno60Seconds per increment thereafter
min_durationno0Calls shorter than this are not charged
includednofalseOn a sell-side free row, marks a plan inclusion
high_risknofalseArms the fraud detectors for this destination

Matching

Calls match on longest prefix. A sheet with 61, 614 and 6141 prices an Australian mobile against 6141 if present, 614 otherwise, 61 as a last resort.

* is a catch-all. Use it deliberately: a * row priced above zero means no call is ever unrated, which sounds safe but hides a missing destination.

Increments

increment_initial and increment_step are how carriers actually bill. 30/6 means a 31-second call bills as 36 seconds. 60/60 means every call rounds up to the next whole minute. 1/1 is per-second.

Increments are the single most common source of disagreement when reconciling against another billing system. Check them first.

The sanity ceiling

Rate sheet import refuses any row above RATE_SANITY_CEILING currency units per minute, default 10. It exists to catch a sheet uploaded in cents as if it were dollars, which is a hundredfold overbill that otherwise looks like perfectly valid data.

Raise it in .env if you legitimately sell destinations above that price.

Uploading

Upload runs as a dry run first. The result reports:

  • Rows parsed, rows rejected, and why each was rejected
  • Destinations added, changed and removed
  • The largest price movements, so a decimal-point error is visible

Only after reviewing the dry run do you commit.

An upload supersedes the whole sheet. Rating history is never rewritten, so an invoice issued last month can always be reproduced exactly as it was issued, even after the sheet under it has changed.

Inclusion groups

An inclusion group is an allowance: a set of destinations, a number of included minutes, and an overflow rate for minutes beyond the allowance.

Configured on the rate plan:

  • Label — printed on the invoice, e.g. "1300 numbers"
  • Destinations — which rate rows the allowance covers
  • Allowance minutes — included minutes per period
  • Overflow rate — per-minute price beyond the allowance
  • Alert threshold — raise an alert when the tenant crosses this much of the allowance
  • Scope — per customer, or per extension

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, what was used and what overflowed.

Recurring rates

Plans → Recurring prices the non-call items. Each row has a basis and a frequency. See Recurring Charges.

Catalogue

Catalogue is a hardware and one-off price list: handsets, licences, installation fees, anything you sell as a one-time charge. Items are picked from the catalogue when raising a one-time charge on a tenant, so the price and description are consistent across invoices.

One-time charges must be approved before they appear on an invoice. An unapproved charge blocks finalization rather than being quietly dropped.

Rate Test

Rate Test answers "what would this number cost this tenant". Enter a number, a tenant and a duration, and it reports the matched row on both the sell and cost sides, the increments applied, connect fee, and final price.

Use it before the first invoice, and use it every time you upload a sheet.

Worked examples

A complete minimal rate sheet

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

What the dry run tells you

Dry run: Business Standard USD
Rows parsed: 6
Rows rejected: 0
Destinations: +6 added, 0 changed, 0 removed
Largest rate: 2.50/min (US Premium) — under ceiling of 10.00

A rejected row is reported with its line number and the reason. Common ones: a charge_type that is not one of the three permitted values, a non-numeric rate, a missing prefix, or a rate above RATE_SANITY_CEILING.

Longest prefix in practice

Given the sheet above, a call to +44 7700 900123:

Candidate rows:  44 (United Kingdom), 4477 (UK Mobile)
Matched: 4477 — longer prefix wins
Rate: 0.14/min

Remove the 4477 row and the same call bills at 0.035. That is a factor of four, and it is why a missing mobile row is worth finding on a dry run rather than on an invoice.

Increments, worked

A 1 minute 43 second call is 103 seconds of talk time.

IncrementsBilled secondsWorking
60/60120rounds up to the next whole minute
30/610830 + ceil(73/6) x 6 = 30 + 78
1/1103per-second

At 0.035/min those are 0.07, 0.06 and 0.06. At scale the difference between 60/60 and 1/1 on short calls is substantial: a thousand 30-second calls bill as 1,000 minutes on 60/60 and 500 on 1/1.

Connect fee, worked

A 45-second premium call at 2.50/min with a 0.75 connect fee, on 60/60:

45s rounds to 60s = 1.00 min
1.00 x 2.50 = 2.50
connect fee 0.75
-----
3.25

The connect fee is charged once, only on an answered call, and in addition to the per-minute amount.

An inclusion group, worked

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

With 640 minutes used:

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.

About the catch-all row

A * row priced at 0.50 means no call is ever unrated. That sounds safe, and it is a trap: an unrated call blocks finalization and makes you look at it, whereas a catch-all silently prices a missing destination at a number you invented.

Price the catch-all deliberately high and mark it high_risk, so a call landing on it is both expensive enough to notice and loud enough to alert. Or omit it and let unrated calls block the invoice.

→ Full arithmetic for a complete invoice: Worked Example