Simulate a tariff draft against a session
post/v1/tenants/{tenant_id}/tariffs/simulate
Requires an API key
Stateless: validates a tariff definition exactly as tariff creation does (422 tariff_invalid with every problem in details.errors) and prices the session with the billing function, without storing anything. Use it to build and check a tariff before creating it.
Path parameters
- tenant_idintegerRequired
Request body
- tariffTariffDefinitionInputRequiredA tariff to simulate without storing it.
Child attributes
- currencystringRequiredPattern
^[A-Z]{3}$ - elementsarray of TariffElementRequiredOCPI 2.2.1 TariffElements, the native tariff format. For each moment of a session the first element that prices a dimension and whose restrictions all hold applies. Overlapping time windows must nest (narrower first) and an element may not hide a later one.
Child attributes
- price_componentsarray of PriceComponentRequired
Child attributes
- typeenumRequiredENERGY: price per kWh. TIME: price per hour while charging. PARKING_TIME: price per hour idle (connected, not charging). FLAT: a fee per session (per reservation in a reservation element). Bills tell charging from idle time from the charger's reports and charge TIME and PARKING_TIME accordingly; when a session has too little data, all of it is charging time.One of
ENERGY,TIME,PARKING_TIME,FLAT - pricenumberRequiredMajor units excluding tax, at most 4 decimal places (OCPI): 0.35 is $0.35 per kWh.Minimum 0 · Maximum 10000
- step_sizeintegerOCPI step size: ENERGY in Wh, TIME and PARKING_TIME in seconds; the dimension's total rounds up to a multiple of the last billed element's step. 1 bills the metered quantity exactly. Ignored for FLAT.Default
1· Minimum 1 · Maximum 86400
- restrictionsobject | nullOCPI 2.2.1 TariffRestrictions, evaluated in the tariff's local time. All given restrictions must hold. min values are inclusive, max values and end times/dates exclusive; an end_time before its start_time wraps midnight.
Child attributes
- start_timestring | nullLocal time of day (HH:MM) from which the element applies.Pattern
^([01][0-9]|2[0-3]):[0-5][0-9]$ - end_timestring | nullLocal time of day (HH:MM) until which the element applies (exclusive).Pattern
^([01][0-9]|2[0-3]):[0-5][0-9]$ - start_datestring | nullLocal date (YYYY-MM-DD) from which the element applies.Pattern
^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$ - end_datestring | nullLocal date (YYYY-MM-DD) until which the element applies (exclusive).Pattern
^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$ - min_kwhnumber | nullEnergy already charged in the session, kWh (inclusive).Minimum 0 · Maximum 100000
- max_kwhnumber | nullEnergy already charged in the session, kWh (exclusive).Minimum 0 · Maximum 100000
- min_currentnumber | nullCharging current, A (inclusive). An element restricting current never applies when the current is unknown.Minimum 0 · Maximum 10000
- max_currentnumber | nullCharging current, A (exclusive).Minimum 0 · Maximum 10000
- min_powernumber | nullCharging power, kW (inclusive). Unknown power matches no power-restricted element.Minimum 0 · Maximum 10000
- max_powernumber | nullCharging power, kW (exclusive).Minimum 0 · Maximum 10000
- min_durationinteger | nullSession duration so far, seconds (inclusive).Minimum 0 · Maximum 604800
- max_durationinteger | nullSession duration so far, seconds (exclusive).Minimum 0 · Maximum 604800
- day_of_weekarray of enum | nullLocal days on which the element applies.
- reservationenum | nullPrices a reservation (TIME: reserved time, FLAT: reservation fee) instead of charging; RESERVATION_EXPIRES only when the reservation expires unused.One of
RESERVATION,RESERVATION_EXPIRES
- tariff_alt_textarray of AltText | nullDriver-facing descriptions (OCPI tariff_alt_text), at most one per language. Omit to have Ivora generate an English one from the elements; a tariff too complex to describe in 512 characters is refused unless you supply it.
Child attributes
- languagestringRequiredISO 639-1 language code.Pattern
^[a-z]{2}$ - textstringRequiredDriver-facing description of the tariff.1–512 characters
- rulesobject | nullIvora billing rules applied after the elements, in this order, and never published over OCPI: partners see the elements and tariff_alt_text only.
Child attributes
- group_discountsarray of GroupDiscountMember/RFID group discounts: the largest matching one applies; they never stack.
Child attributes
- idstringRequiredYour name for this discount; shown on quote and bill adjustments.Pattern
^[A-Za-z0-9][A-Za-z0-9_.:-]{0,63}$ - groupsarray of stringMember or RFID groups (the session's group) the discount applies to.
- id_tokensarray of stringRFID or app tokens (the session's id_token) the discount applies to.
- percent_offintegerRequiredMinimum 1 · Maximum 100
- merchant_validationobject | nullA discount when the session carries a merchant validation code.
Child attributes
- percent_offinteger | nullMinimum 1 · Maximum 100
- amount_off_minorinteger | nullInteger minor units off, never below 0.Minimum 1 · Maximum 10000000
- codesarray of stringAccepted validation codes; empty accepts any code the session carries.
- max_session_cost_minorinteger | nullCap on a session's total, integer minor units.Minimum 1 · Maximum 100000000
- prepaid_limitbooleanReport, on quotes for sessions with prepaid_balance_minor, how much the balance covers and whether the session reaches it. It never changes the total; your application stops or tops up.Default
false
- time_zonestring | nullIANA time zone of the restrictions' local times. Omit to use the station location's time zone when billing (UTC without one).Up to 64 characters
- sessionSessionProfileRequiredA charging session to price. Energy is cumulative kWh: energy_kwh spreads evenly over duration_minutes, or energy_curve gives it at points (linear between them).
Child attributes
- start_atstringRequiredWhen charging starts, ISO 8601 with an offset.
- time_zonestring | nullIANA time zone for the tariff's local-time restrictions. Default: the tariff's time_zone, else start_at's offset.Up to 64 characters
- duration_minutesnumberCharging time in minutes (TIME is billed on it).Default
0· Minimum 0 · Maximum 10080 - energy_kwhnumber | nullTotal energy, kWh. Omit when energy_curve is given.Minimum 0 · Maximum 100000
- energy_curvearray of CurvePoint | nullCumulative kWh at minutes into charging, ascending.
Child attributes
- minutenumberRequiredMinutes after charging started.Minimum 0 · Maximum 10080
- kwhnumberRequiredCumulative energy charged by then, kWh.Minimum 0 · Maximum 100000
- idle_minutesnumberMinutes connected after charging ends (PARKING_TIME is billed on it).Default
0· Minimum 0 · Maximum 10080 - power_kwnumber | nullConstant charging power for power restrictions, kW. Default: the energy curve's slope.Minimum 0 · Maximum 10000
- current_anumber | nullCharging current for current restrictions, A. Unknown matches no current-restricted element.Minimum 0 · Maximum 10000
- reservation_minutesnumberMinutes reserved before charging starts (reservation elements price them).Default
0· Minimum 0 · Maximum 1440 - reservation_expiredbooleanThe reservation expired unused: no charging; RESERVATION_EXPIRES elements apply.Default
false - groupstring | nullMember or RFID group, for group discounts.Up to 128 characters
- id_tokenstring | nullRFID or app token, for group discounts that list tokens. Not stored.Up to 64 characters
- merchant_validationstring | nullA merchant validation code, for the merchant validation rule.Pattern
^[A-Za-z0-9][A-Za-z0-9_.:-]{0,63}$ - prepaid_balance_minorinteger | nullA prepaid balance, for the prepaid_limit report.Minimum 0 · Maximum 100000000
Returns · 200
- tariff_idinteger | nullThe stored tariff quoted; null for a simulation.
- currencystringRequired
- pricing_versionenumRequiredenergy-v1: a simple tariff (kWh × rate, unchanged); elements-v1: elements and rules.One of
energy-v1,elements-v1 - linesarray of QuoteLineRequired
Child attributes
- typeenumRequiredOne of
ENERGY,TIME,PARKING_TIME,FLAT - elementintegerRequiredIndex of the element that priced this line.
- reservationbooleanRequiredThe line prices a reservation.
- quantitystringRequiredDecimal quantity in unit (rounded to 6 places for display).
- unitenumRequiredOne of
kWh,h,session - price_minorstringRequiredMinor units per unit (decimal string).
- exact_minorstringRequiredUnrounded amount, minor units (decimal string, 6 places).
- amount_minorintegerRequiredAmount rounded half up to integer minor units, for display. total_minor rounds the exact sum once, so line amounts may differ from it by rounding.
- subtotal_minorintegerRequiredThe elements' exact sum rounded half up, before rules.
- exact_subtotal_minorstringRequired
- adjustmentsarray of QuoteAdjustmentRequired
Child attributes
- kindenumRequiredOne of
group_discount,merchant_validation,max_session_cost - rulestringRequiredThe group discount id, the validation code, or max_session_cost_minor.
- exact_minorstringRequired
- amount_minorintegerRequiredNegative: a reduction.
- total_minorintegerRequiredInteger minor units: the exact subtotal after rules, rounded half up once. Bills finalize with this same calculation.
- prepaidobject | nullRequired
Child attributes
- balance_minorintegerRequired
- covered_minorintegerRequired
- shortfall_minorintegerRequired
- limit_reachedbooleanRequiredThe session's total reaches the balance: stop or top up.
- tariff_alt_textarray of AltTextThe tariff's driver-facing descriptions, for receipts.
Child attributes
- languagestringRequiredISO 639-1 language code.Pattern
^[a-z]{2}$ - textstringRequiredDriver-facing description of the tariff.1–512 characters
- activityobject | nullBills on complex tariffs only: the charging and idle time the bill was priced over. Null on quotes, simulations and simple tariffs (which price kWh only).
Child attributes
- methodenumRequiredocpp201_charging_state: the charger's OCPP 2.x chargingState. ocpp16_status: OCPP 1.6 connector statuses (Charging; SuspendedEV, SuspendedEVSE and Finishing are idle). ocpp16_status_and_power: those statuses, plus idle wherever the meter shows almost no power for a while. meter_power: the meter alone. none: not enough data; the whole transaction is charging time, as before idle detection (unless it drew less than 1 Wh: see reason no_energy).One of
ocpp201_charging_state,ocpp16_status,ocpp16_status_and_power,meter_power,none - detectedbooleanRequiredFalse: method none, and reason says why. A session with less than 1 Wh is all waiting (reason no_energy), and detected is true then, also with method none.
- reasonstring | nullWhy nothing was detected (for example no_state_or_meter_data); no_energy: a session with less than 1 Wh is all waiting, billing neither TIME nor PARKING_TIME nor energy; else null.
- charging_secondsintegerRequired
- idle_secondsintegerRequired
- waiting_secondsintegerPlugged in before the first charging: neither TIME nor PARKING_TIME.Default
0 - intervalsarray of ActivityIntervalRequiredThe transaction from start to end, oldest first.
Child attributes
- startstringRequiredUTC, ISO 8601.
- endstringRequiredUTC, ISO 8601.
- stateenumRequiredwaiting: plugged in before the first charging, priced as neither TIME nor PARKING_TIME.One of
charging,idle,waiting
POST /v1/tenants/{tenant_id}/tariffs/simulate
curl --fail-with-body -X POST "https://api.ivoracharge.com/v1/tenants/1042/tariffs/simulate" \
-H "Authorization: Bearer $IVORA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tariff": {
"currency": "usd",
"elements": [
{
"price_components": [
{
"type": null,
"price": null
}
]
}
]
},
"session": {
"start_at": "2026-10-15T17:30:00-07:00"
}
}'Response · 200
{
"tariff_id": 42,
"currency": "usd",
"pricing_version": "energy-v1",
"lines": [
{
"type": "ENERGY",
"element": 1,
"reservation": false,
"quantity": "string",
"unit": "kWh",
"price_minor": "string",
"exact_minor": "string",
"amount_minor": 1250
}
],
"subtotal_minor": 1250,
"exact_subtotal_minor": "string",
"adjustments": [
{
"kind": "group_discount",
"rule": "string",
"exact_minor": "string",
"amount_minor": 1250
}
],
"total_minor": 1250,
"prepaid": {
"balance_minor": 1250,
"covered_minor": 1250,
"shortfall_minor": 1250,
"limit_reached": false
},
"tariff_alt_text": [
{
"language": "string",
"text": "string"
}
],
"activity": {
"method": "ocpp201_charging_state",
"detected": false,
"reason": "string",
"charging_seconds": 1,
"idle_seconds": 1,
"waiting_seconds": 0,
"intervals": [
{
"start": "string",
"end": "string",
"state": "charging"
}
]
}
}Try it is not available here yetRequests from this page are off until the production API at
https://api.ivoracharge.com is public. Use the code samples from your application server; Ivora grants production access. Keys are created in Developer tools.