TL;DR: OCPP 2.0.1 is not a cosmetic update to 1.6. It redesigns the device model into a Station/EVSE/Connector hierarchy with typed variables, replaces StartTransaction and StopTransaction with a single TransactionEvent stream, and adds richer smart charging, ISO 15118 Plug & Charge, V2G hooks, and defined security profiles. Assume mixed 1.6/2.0.1 fleets for years, and evaluate vendors on coexistence and migration safety rather than a protocol checkbox.
Why OCPP 2.0.1 is a bigger jump than you think
OCPP 2.0.1 is not an incremental patch on 1.6. The device model was fundamentally redesigned, the message format changed, and several core concepts were renamed or restructured. Treating it as a point release is the most common way migrations go sideways.
Whenever we sit in on a first 2.0.1 integration, the same pattern shows up: a team copies its 1.6 message handlers, swaps a few field names, and assumes the rest will follow. It doesn't. The boot payload, the transaction lifecycle, and the configuration model all behave differently, so the early hours get spent rediscovering changes that were never optional. The protocol kept the OCPP-J transport, but reworked almost everything carried inside it. The sections below walk through what changed and where rollout planning has to adapt.
What this changes in rollout planning
The practical impact is not "more features." OCPP 2.0.1 changes how rollout teams should evaluate chargers, backend abstractions, and coexistence strategy. The decisions that used to be afterthoughts in 1.6, capability discovery, transaction modeling, and config governance, move to the front of the plan.
- Mixed fleets become a long-term operating model rather than a temporary migration phase.
- Capability discovery matters more because charger features are described with more precision but also more vendor variance.
- Transaction handling needs retesting because
TransactionEventreplaces older assumptions around start/stop flows. - Configuration governance gets harder because a richer model creates more opportunities for drift between charger, backend, and field expectations.
If a vendor says it "supports OCPP 2.0.1," the useful follow-up is not a protocol checkbox. It is whether your operations team can roll out, monitor, and troubleshoot a mixed 1.6/2.0.1 fleet without building a parallel exception process.
The OCPP 2.0.1 device model
The biggest structural change is the device model. OCPP 1.6 described a charger as a flat list of connectors, while the OCPP 2.0.1 specification introduces a three-layer hierarchy plus a typed variable system that lets the backend read and configure the station with far more precision.
The hierarchy looks like this:
- Charging Station — the physical unit that boots and reports firmware
- EVSE (Electric Vehicle Supply Equipment) — an independently controllable outlet group
- Connector — the physical plug (CCS, CHAdeMO, Type 2)
This matters because modern chargers often pack multiple EVSEs, each exposing several connector types, and operators need to address availability, faults, and setpoints at the EVSE level rather than guessing from a flat connector list. On top of the hierarchy, 2.0.1 replaces the old free-form key/value configuration with a structured component-and-variable model: each variable carries a type, mutability, and characteristics. The upside is precise control. The cost is that two chargers can model the same physical feature with slightly different components, so a backend that assumes uniform naming will mishandle some hardware. In practice, the device model is where most of the normalization work lives.
How the message format changed in OCPP 2.0.1
The OCPP-J transport envelope stayed the same, but the payload schema changed almost everywhere. Messages now nest structured objects like chargingStation, carry explicit reason codes, and align field names with the new device model. A 1.6 BootNotification and a 2.0.1 one are not interchangeable, even though they share a verb.
In 1.6, a BootNotification looks like:
[2, "19223201", "BootNotification", {
"chargePointModel": "Optimus",
"chargePointVendor": "VendorX"
}]In 2.0.1:
[2, "19223201", "BootNotification", {
"reason": "PowerUp",
"chargingStation": {
"model": "Optimus",
"vendorName": "VendorX",
"firmwareVersion": "1.0.0",
"modem": { "iccid": "...", "imsi": "..." }
}
}]The envelope is the same (OCPP-J array), but the payload schema is different almost everywhere. The transaction layer is the change most likely to break a naive port: 1.6's separate StartTransaction and StopTransaction calls are replaced by a single TransactionEvent message with eventType values of Started, Updated, and Ended. State that used to be implied by which message arrived now lives inside one event stream, so meter values, trigger reasons, and stop causes all flow through the same handler.
Here is how the two protocols line up on the parts that most affect a backend:
| Area | OCPP 1.6 | OCPP 2.0.1 |
|---|---|---|
| Topology | Flat connector list | Station, EVSE, Connector hierarchy |
| Configuration | Free-form key/value | Typed component and variable model |
| Transactions | StartTransaction / StopTransaction | Single TransactionEvent stream |
| Boot payload | Flat fields | Nested chargingStation object with reason |
| Smart charging | Basic, partial | Profiles plus ISO 15118 and V2G hooks |
| Security | Optional, loosely specified | Defined profiles for TLS and certificates |
What smart charging features does OCPP 2.0.1 add?
Smart charging is where 2.0.1 closes the most painful gaps in 1.6. The protocol adds richer charging profiles, ISO 15118 Plug & Charge, vehicle-to-grid signaling, and a path for tariff information, which together let the backend shape load and authentication instead of only switching sessions on and off.
The additions worth planning around:
- ISO 15118 Plug & Charge — automatic, certificate-based authentication without RFID, negotiated between vehicle and EVSE
- V2G hooks — capability signaling for bidirectional energy flow back to the grid
- Richer charging profiles — more expressive setpoint and limit scheduling than 1.6 allowed
- Dynamic pricing signals — a path for the CPMS to push tariff information toward the session
For fleet operators and utilities, these are not nice-to-haves. Take V2G as the clearest example. Bidirectional capability lets a parked fleet discharge during peak pricing or grid-stress windows and recharge when energy is cheap, so the same connected vehicles become a dispatchable resource. The protocol does not pay anyone on its own. It provides the signaling that lets a CPMS and an aggregator coordinate that discharge against a tariff or demand-response program, which is the mechanism that turns idle dwell time into avoided demand charges or program revenue. Without the signaling in the protocol layer, that coordination has to be bolted on per vendor, which is exactly the kind of exception work that erodes the economics. The same holds for dynamic pricing: the value only appears when the charger can actually act on a tariff the backend sends.
How do you migrate from OCPP 1.6 to 2.0.1?
Migration is less about flipping a version flag and more about remapping your data model and handlers, then proving coexistence. Plan for 1.6 and 2.0.1 to run side by side for years, because field hardware turns over slowly. The sequence below is the one that tends to surface problems early rather than at commissioning.
If you're migrating from 1.6 to 2.0.1:
- Audit your connector model — map your physical hardware to the EVSE hierarchy
- Update your message handlers —
BootNotification,StatusNotification,TransactionEventall changed - Test with a broker — don't connect directly to production until you've validated against a 2.0.1-compliant intermediary
- Plan for 1.6 coexistence — most field hardware will stay on 1.6 for years
EV Cloud handles the 1.6 ↔ 2.0.1 translation automatically, so your CPMS can be 2.0.1-native even when your chargers are on older firmware.
What proof should you require before accepting a "2.0.1-ready" claim?
A vendor checkbox is not proof. Before a charger or backend is approved for rollout, ask for evidence against a bounded test plan that exercises the parts of 2.0.1 most likely to behave inconsistently across hardware. The five checks below cover the failure modes we see surface after commissioning.
- Boot and inventory accuracy: confirm the charger exposes the expected station, EVSE, and connector structure.
- Transaction consistency: validate start, update, suspend, resume, and stop events under unstable network conditions.
- Smart charging behavior: prove setpoints are enforced, rejected cleanly, or downgraded predictably rather than silently ignored.
- Configuration lifecycle: test reading, updating, and auditing key variables without manual site intervention.
- Fallback and coexistence: run the same operational workflow across both 1.6 and 2.0.1 chargers and compare what breaks.
Teams that skip these checks usually discover protocol gaps only after commissioning, when the cost of rollback is much higher.
How should 2.0.1 readiness shape a vendor shortlist?
Score migration safety, not protocol support. A vendor can claim 2.0.1 and still leave you to absorb coexistence, rollout sequencing, and charger-specific exceptions in the field, which is where the real cost sits. The useful test is whether one operational workflow runs cleanly across both 1.6 and 2.0.1 hardware.
Use the OCPP platform buyer guide and the best OCPP platforms for CPOs to score shortlists more rigorously. If migration is already in scope, continue with the legacy CSMS migration plan for CPOs.
Learn more about OCPP in our ultimate guide to OCPP.


