API versions and changelog
The Ivora API keeps the path major /v1. Within it, the contract is versioned
by date (YYYY-MM-DD). The current version is 2026-10-15; 2026-10-14
remains supported.
Policy
- Additive by default. New routes, new optional request fields, new response fields, new event types and new error codes ship without a new version. Write clients that ignore fields and event types they do not know.
- Breaking changes are rare. Removing or renaming a field, changing its type or meaning, or changing a route's behaviour needs Ivora's sign-off and ships only as a new dated version. Your keys keep their pinned version until you move them.
- Six months' notice. A deprecated field, route or version is announced here at least six months before its sunset date.
- At most two supported versions at any time: the latest and the one before it.
Headers
| Header | Direction | Meaning |
|---|---|---|
Ivora-Version | Response | The version applied to this request. Every response carries it |
Ivora-Version | Request, optional | A version to apply, such as 2026-10-15. A version not listed below answers 400 invalid_api_version with details.supported_versions. Without it, your API key's pinned version applies |
Deprecation | Response | Only on a deprecated route or a route with a deprecated field: when the deprecation was announced (RFC 9745, @<unix seconds>) |
Sunset | Response | With Deprecation: the date after which the route or field may be removed (RFC 8594) |
Link | Response | With Deprecation: this changelog, rel="deprecation" |
Webhook deliveries also carry Ivora-Version: the version the endpoint is
pinned to.
Pinning
Every API key and webhook endpoint stores the version it is pinned to, shown
as api_version in GET /v1/api-keys, the key creation response and webhook
endpoint reads. A new key or endpoint is pinned to the latest version. Keys and
endpoints created before versioning are pinned to 2026-10-14.
Diagram source
flowchart LR
Request[Request] --> Header{Ivora-Version sent?}
Header -->|No| Pin[Key's pinned version]
Header -->|Supported version| Applied[That version]
Header -->|Anything else| Refused[400 invalid_api_version]
Pin --> Response[Response with Ivora-Version]
Applied --> ResponseVersions
| Version | Status | Sunset |
|---|---|---|
| 2026-10-15 | Current | None scheduled |
| 2026-10-14 | Supported | None scheduled |
2026-10-15
Tariff price blocks (tariffs guide).
- Changed in this version: tariff responses (
GET,POST,PATCHandDELETEon/v1/tenants/{tenant_id}/tariffs) carryelements(OCPI 2.2.1 price blocks),tariff_alt_text,rulesandtime_zone. A simple tariff shows its oneENERGYelement. - For every version (additive):
- Tariffs carry
is_complexandpricing_summary. A 2026-10-14 client sees a complex tariff as its baserate_minor_per_kwhplus these two fields. - Tariff creation and edits accept
elements,tariff_alt_text,rulesandtime_zone. Withelements,rate_minor_per_kwhis optional. - New routes:
POST /v1/tenants/{tenant_id}/tariffs/{tariff_id}/quoteandPOST /v1/tenants/{tenant_id}/tariffs/simulate. - Bills accept
pricing_groupandmerchant_validation. Bills on complex tariffs havebilling_version: "elements-v1". Final bills carrycost_breakdown. Thebill.finalizedevent carries the final bill, so it gainscost_breakdownand can carrybilling_version: "elements-v1". - Group discounts and merchant validations compound: the merchant validation applies to the amount left after the group discount, then the session cost cap applies.
- Bills on complex tariffs charge
TIMEover the transaction's charging time andPARKING_TIMEover its idle time, as the charger reports them (charging and idle time); with too little data the whole transaction is charging time. Final bills on complex tariffs carrycost_breakdown.activity. Power and kWh restrictions use the session's averages over its charging time. A transaction with no start time cannot be priced by a time-dependent tariff. - New error codes:
422 tariff_invalid,409 tariff_complexand409 transaction_start_unknown.
- Tariffs carry
- Unchanged: simple tariffs read, write and bill exactly as in 2026-10-14.
OCPI partners receive complex tariffs' elements and
tariff_alt_text, never billing rules.
New API keys and webhook endpoints are pinned to 2026-10-15. Existing ones keep
2026-10-14 until you move them; send Ivora-Version: 2026-10-15 to try the new
shape first.
Deprecations
Deprecated fields and routes are listed here with their announcement and
sunset dates, and their responses carry the Deprecation headers.
| What | Announced | Sunset | Replacement |
|---|---|---|---|
allow_protected on configuration changes (ignored) | 2026-10-17 | — | stations:admin |
Changelog
Unreleased additions (2026-10-14 contract)
Additive; no new version.
stations:admin: a new elevated scope for protected configuration keys and for pushing a password to a connected charger (PUT .../credentials).stations:writestill sets the password of an offline or new station (applied = stored); on a connected station it now answers403 stations_admin_requiredand sends nothing. Team owners and admins and Ivora platform administrators hold it; API keys only when created with it. Connection keys (WebSocketURL,OCPPID,SecurityProfile, the OCPP 2.x network variables) also needconfirm_connection_change: true. Password changes are limited to 5 per station per hour (429 credentials_rate_limited). New eventsstation.credentials_changedandstation.configuration_changed.Idle time on bills: bills on complex tariffs now tell charging from idle time (OCPP 2.0.1
chargingState; OCPP 1.6 connector status and meter power).TIMEis charged over charging time only andPARKING_TIMEover idle time after charging, on final bills, live estimates and running-cost displays. Idle shorter than 2 minutes is charging time; time before the first charging (at least 2 minutes of it, else the firstCharging(status orchargingState) or metered draw of any length) is waiting, charged as neither. A session that draws less than 1 Wh is all waiting (reasonno_energy) and bills no time and no energy (the metered kWh is kept; simple per-kWh tariffs are unchanged). Final bills carrycost_breakdown.activitywith the method, the seconds of each and the intervals. Generated tariff descriptions now read "per hour while charging" forTIMEand "idle fee after charging" forPARKING_TIME. OCPI CDRs carrytotal_parking_time, and sessions and CDRs with idle time have one charging period per interval. Simple tariffs and existing final bills are unchanged.Per-project charger URLs (preproduction only, not available in production; on for every project by default, Ivora staff may turn a project's off; in preproduction the project URL is the address chargers connect to):
POST /v1/tenants/{tenant_id}/stationsacceptscharger_idinstead ofname, unique within the project; stations carrycharger_id,usernameandconnection_base_url;?charger_id=filters the station list;PATCHacceptscharger_id; projects carrycharger_urlsandconnection_base_url. Error codeproject_urls_disabled. Station names are now limited to 36 characters, the charging core's own limit (longer ones could never be stored), and names starting withp<digits>-are reserved for these stations. Staff routesGET|PUT /v1/admin/tenants/{tenant_id}/charger-urlsread the effective state (source:defaultoroverride) and set an override.Enterprise invoicing: Ivora can switch a team to
billing_mode: "enterprise". Its monthly usage-fee invoice is then sent with net terms (due_date,collection_method: "send_invoice") and paid by ACH debit, bank transfer or, if allowed, card; Canadian teams pay by bank transfer, pre-authorized debit in US dollars, or card. Every amount stays in US dollars.GET /v1/teams/{team_id}/billinggainsbilling_mode,invoice_terms,bank_accountandbank_transfer. A project's billing profile gainsbilling_mode,bank_accountandinvoice_termswithout the billing contacts, legal name or PO number, and nobank_transfer. Invoices gaincollection_method,due_date,overdue,days_overdue,payment_processing,minimum_topup_minorandpo_number. The usage estimate gainsbilling_mode,minimum_commitment_minorandminimum_topup_minor. Staff settings gainbank_country(usorca);currencystaysusd. New statuses:enterpriseandsuspended. New error code:402 billing_suspended. New routes:POST /v1/teams/{team_id}/billing/bank-account/setup|syncandDELETE /v1/teams/{team_id}/billing/bank-account, plus the staff routePATCH /v1/admin/billing-teams/{team_id}/invoicing. Self-serve billing is unchanged.Team billing:
GET /v1/teams/{team_id}/billingreads the team's billing account (status, card, grace, discount, and each project's rate andcurrent_month),GET /v1/teams/{team_id}/billing/invoicesandGET /v1/teams/{team_id}/billing/usageits invoices and this month's estimate across every project, andPOST /v1/teams/{team_id}/billing/payment-method/setup|syncandDELETE /v1/teams/{team_id}/billing/payment-methodmanage its card. Signed-in owners, admins and billing members only; API keys are refused. Admins now hold thebilling:manageteam permission (they already managed the card through any project'sbilling:write).Project keys, operations and projects: API keys with project scopes belong to the project, not their creator, and are managed by the team's owners, admins and developers at
GET|POST /v1/tenants/{tenant_id}/api-keysandDELETE /v1/tenants/{tenant_id}/api-keys/{key_id}.POST /v1/api-keyswith project scopes now makes such a key, so operators and viewers no longer make project keys, and a key mixing project and workspace scopes is refused (422).GET /v1/api-keyslists your workspace keys and the project keys you made, withowner.GET /v1/tenants/{tenant_id}/operationslists the project's operations by every actor, andGET .../operations/{operation_id}reads another actor's operation within your read scopes. New scopewebhooks:readlists webhook endpoints and deliveries (webhooks:writeincludes it; viewers and operators hold it).POST /v1/teams/{team_id}/projects,GET|PATCH /v1/tenants/{tenant_id}create, read and rename projects. Error codeproject_limit.Teams:
GET /v1/me/teams,GET /v1/me/invites,POST /v1/me/invites/{invite_id}/accept|decline,GET /v1/teams/{team_id}/members,PATCH|DELETE /v1/teams/{team_id}/members/{user_id}andGET|POST|DELETE /v1/teams/{team_id}/invites[/{invite_id}]. Signed-in tenant access now comes from team roles; existing grants are imported unchanged in effect. Error codeslast_owner,already_member,invite_pending,invite_closedandinvite_expired. The billing role holds no project scope: it reads only.../billing-profile,/invoicesand/usageand manages the team's card.
2026-10-14
The first dated version. It is the /v1 contract as it was on 2026-10-14,
with no behaviour change for existing callers.
- Responses carry
Ivora-Version. Requests may send it; an unsupported value answers400 invalid_api_version. - API keys and webhook endpoints show their pinned
api_version. - The OpenAPI document's
info.versionis the latest version date.