Log inTalk to us
Billing and settlement

Tax: per-location tax lines

You are the seller: you charge the tax, file it and stay responsible for it. Ivora provides the tools. It computes the tax lines you configure on a location and shows them on quotes, bills, receipts, webhooks, the running cost and OCPI. Ivora does not guarantee that a configuration or a preset is legally correct or current. Check what applies to your charging at each location.

A location without tax lines has no tax. Its bills price exactly as before, to the byte.

Tax lines

PUT /v1/tenants/{tenant_id}/locations/{location_id}/tax replaces a location's configuration. It needs stations:admin: team owners and admins, Ivora staff, and API keys created with that scope. GET on the same path reads it. DELETE removes every line. Each change is audit-logged with the caller.

{
  "price_mode": "tax_exclusive",
  "lines": [
    {"name": "GST", "type": "percent", "rate": 5, "registration_number": "123456789RT0001"},
    {"name": "QST", "type": "percent", "rate": 9.975, "registration_number": "1234567890TQ0001"}
  ]
}
FieldMeaning
namePrinted on receipts: GST, HST, PST, QST, state sales tax, county, city, EV excise. Unique per location
typepercent: a percentage of the components the line taxes. per_kwh: minor units of the bill's (its tariff's) currency per kWh delivered; 2.6 is 2.6 cents per kWh in USD
rateAt most 4 decimal places. percent: 0 to 100. per_kwh: 0 to 1000
registration_numberOptional: your registration number for this tax, printed on receipts
orderOptional: the lines apply in ascending order; lines without one keep their place after those with one
compoundpercent lines: the base includes the earlier lines' tax (Quebec's QST compounded on GST before 2013). Never on the first line or a per_kwh line
excluded_componentspercent lines: tariff components the line does not tax: ENERGY, TIME, PARKING_TIME or FLAT. Empty taxes all of them

At most 10 lines. An invalid configuration returns 422 tax_invalid with each problem in details.errors. A replay with the same Idempotency-Key returns the current configuration.

Price mode

price_modeTariff pricesWhat the driver pays
tax_exclusive (default, the US norm)Exclude taxThe tariff's total plus every line
tax_inclusiveInclude every lineThe tariff's total; the lines are taken out of it

Calculation

Tax is computed from the tariff snapshot that the bill took when it was created, after the tariff's elements and billing rules:

  1. The tariff's total is the exact element subtotal after discounts and caps, rounded half up to an integer of minor units, as before.
  2. A percent line's base is that total, shared out over the energy, time, idle and flat components in proportion to their exact amounts. Components the line excludes are left out. compound adds the earlier lines' amounts.
  3. A per_kwh line is its rate times the kWh delivered. A session with less than 1 Wh delivers none.
  4. Each line is rounded half up to an integer of minor units once.

With tax_exclusive, net_minor is the tariff's total. Each line is computed on it, and total_minor is net_minor plus tax_minor.

With tax_inclusive, the tariff's total is what the driver pays. Ivora solves the net before tax exactly and computes each line on it. net_minor is then total_minor minus the rounded lines, so the parts always add up to the price shown. When an inclusive price is smaller than its per_kwh tax, the lines are capped at the price.

Example: a CAD tariff at 0.42 per kWh, at an Alberta location (GST 5 %, tax_exclusive). For 6.941 kWh, 6.941 × 42 = 291.522 rounds to 292, and GST 5 % of 292 = 14.6 rounds to 15. The driver pays 307 cents.

The shown price, the quote and the bill agree, tax included. session_limit.amount_minor converts to energy at the per-kWh price with tax (rate_minor on the limit shows it). max_session_cost_minor caps the price before tax.

Where tax appears

WhereWhat
Quotes and simulationsSend location_id on POST .../tariffs/{tariff_id}/quote or .../tariffs/simulate: tax and a total_minor with tax
Billstax (the frozen configuration, with registration numbers) on every bill at a taxed location; usage.estimated_minor and total_minor include tax; cost_breakdown.tax itemises each line with net_minor, tax_minor and total_minor
Charging sessionsThe bill, as above. Settlement reports are in the bill's total with tax
Webhooksbill.finalized and the other bill payloads carry the same fields (additive)
Running costThe charger shows the cost with tax; OCPP 1.6 kWhPrice and the final cost text show the per-kWh price with tax
OCPI TariffsA tariff whose connectors are all at locations with the same lines publishes their combined percentage per component as vat. With tax_inclusive the price is the price before that tax, as OCPI prices exclude VAT. Without location tax, the core tariff's taxRate is published as before
OCPI CDRsA bill-priced CDR's excl_vat is the bill's net_minor and incl_vat is what the driver paid

per_kwh lines are not a percentage, so an OCPI Tariff cannot express them. They are included in a CDR's incl_vat. A tariff used at locations whose taxes differ publishes no vat; its CDRs still carry incl_vat.

A bill freezes the tax of its station's location when it is created. A later change, or deleting the location, never changes an open or final bill. A bill without tax has no tax field. Its cost_breakdown has no tax.

Presets

GET /v1/tax-presets (public) lists editable starting points:

  • Canada's provinces and territories. Canada has no EV-specific charging tax: GST or HST, plus PST, QST or RST where a province has one.
  • The US states with a per-kWh EV charging excise: Iowa, Kentucky and Oklahoma. US sales tax depends on the state, county and city, so it has no preset; add its lines yourself where it applies to charging.

Apply one with {"preset": "CA-AB", "confirm_preset": true}. confirm_preset says that you checked the preset applies to this location. Without it the request returns 422 tax_preset_unconfirmed; an unknown ID returns 422 tax_preset_unknown. The configuration records the preset. Edit it afterwards with lines, for example to add your registration numbers.

PresetLines (tax_exclusive)
CA-AB Alberta, CA-NT, CA-NU, CA-YTGST 5 %
CA-BC British ColumbiaGST 5 % (British Columbia exempts electricity from PST)
CA-MB ManitobaGST 5 %, RST 7 %
CA-SK SaskatchewanGST 5 %, PST 6 %
CA-QC QuebecGST 5 %, QST 9.975 % (not compounding)
CA-ON OntarioHST 13 %
CA-NS Nova ScotiaHST 14 %
CA-NB, CA-NL, CA-PEHST 15 %
US-IA IowaElectric fuel excise, 2.6 cents per kWh
US-KY KentuckyEV charging excise, 3 cents per kWh
US-OK OklahomaEV charging excise, 3 cents per kWh

Each preset carries as_of, the date Ivora last reviewed its rates, and a note.

Not covered

  • Automatic tax determination by address (such as Stripe Tax). Ivora applies the lines you configure only.
  • Ivora's own usage fee invoices. They are not affected by location tax.