Skip to main content

Structure of a resolved price

Every resolved price follows the same three-level shape:

Price type

The top-level key describes what the price is based on:

Day

Within a price type, prices are organized by day of week (MONDAYSUNDAY). If the resolved schedule is identical across all seven days, it is represented once under ALL — this is a size optimization, not a different kind of tariff or a “default” price. Some tariffs may still list seven identical per-day entries instead of collapsing to ALL; consumer logic should handle both shapes. All calendar values — day of week, time_from, time_to — are expressed in the station’s local timezone, not the customer’s and not UTC, and should be rendered as-is without conversion.

Price slots

Each day contains one or more price slots, applicable over a time_fromtime_to window (or the whole day, if unset):

Resolving a price during a session

Locating the correct price slots (by day and time-of-day) determines which price applies. A second, independent dimension determines which tier within it applies once a session is underway:
  • Calendar time — determines the active price slot (day, time_from/time_to).
  • Session-relative time — determines the active tier within that price slot, via from_minute/to_minute (duration) or from_kwh/to_kwh (energy), measured from the start of that session.
These two dimensions are independent: a session restriction is never a calendar boundary, and a calendar boundary is never reset by session state. Either bound in a tier may be null, meaning “no upper limit” — never “zero” or “not set.” A restriction can in principle require both duration and energy bounds simultaneously, though this is uncommon in practice. Energy and time-based prices are applied differently once a session starts: the applicable energy price is resolved once, at the start of charging, and used for the entire session; time-based pricing instead follows the calendar schedule as it unfolds, so a session spanning a slot-price boundary is billed against each slot in turn. This distinction exists because not all partners reliably send the session updates needed for continuously re-evaluated energy pricing. Cost calculation is always performed against net_prices (unrounded, VAT-excluded), not user_facing_prices (rounded for display, typically to 2 decimals). A cost computed manually from user_facing_prices may differ slightly from the actual calculated cost due to this rounding — user_facing_prices should be treated as what to display, not what to calculate from.

Points requiring care

A single applicable price is the intersection of three independent dimensions — price type, calendar time, and session-relative state — and all three must be resolved together; applying a duration or energy tier as if it were a calendar boundary produces a plausible but incorrect price. Other points worth noting:
  • A constant calendar schedule can still combine with a highly tiered session structure — a resolved price is not guaranteed to be a flat value.
  • net_prices and user_facing_prices differ in both tax treatment and unit (time-based prices are per-hour in net_prices, per-minute in user_facing_prices), not only in VAT. Example: 6 euro/hour excl. VAT -> 0.12 euro/min incl. VAT (20%)
  • to_minute: null / to_kwh: null means unbounded; treating null as falsy can incorrectly drop the final tariff tier, where null typically indicates an unlimited upper bound. This can result in the most expensive tier of the tariff being omitted.
Recommended resolution order: price type → day (or ALL) → time-of-day price slot, in station-local time → session restriction tier (duration and/or energy) for the session in question.

Examples

Full example: constant schedule, tiered by session duration

A station that charges:
resolves to a constant calendar schedule (ALL) whose price slot holds the session tiers:

Duration tier scoped to a specific day and time window

“€0.45/min (after 60 min, 06:00–17:00)”