What Is OCPP? The Open Charge Point Protocol Explained

OCPP is how a charging station talks to its back-end. What it is, the messages it carries, how a session flows, and how 1.6, 2.0.1 and 2.1 differ.

OCPP, the Open Charge Point Protocol, is the language EV charging stations use to talk to the back-end systems that operate them. If you have ever wondered how a charger knows whether your card is allowed to charge, how the operator knows a session started, or how new pricing reaches a charger overnight, the answer is OCPP.

It is one of the most important standards in EV charging and one of the least understood outside the small group of people who work on it. This article is a thorough introduction.

Why OCPP exists

In the early 2010s, every EV charging station was a tiny island. The company that built the hardware usually operated the back-end system too. If you bought a charger from Brand A, it talked to Brand A’s cloud, and only Brand A’s cloud. Mixing chargers from different brands in one network was technically possible but operationally painful. You ran two parallel back-ends and reconciled the data by hand.

Operators (CPOs, or Charge Point Operators) hated this. They wanted to choose the best hardware for each location and run all of it through one operations platform. Hardware vendors hated it too, because being locked into their own back-end capped their addressable market.

In 2009 the ELaadNL foundation in the Netherlands led a coalition of utilities, manufacturers, and operators to define a vendor-neutral protocol. OCPP 1.2 came out in 2010 and OCPP 1.5 followed. OCPP 1.6 arrived in 2015 and is old enough that any CSMS you build still has to speak it, because the hardware already in the ground was commissioned against it. OCPP 2.0 came in 2018 and was quickly superseded by 2.0.1 with important corrections. The Open Charge Alliance published OCPP 2.1 in January 2025.

The protocol is published and maintained by the Open Charge Alliance (OCA), a non-profit industry consortium with members across the EV charging value chain.

The two sides of an OCPP connection

OCPP runs between a charge point (also called a charging station, EVSE, or charger) and a CSMS (Charging Station Management System, also called a back-end, back-office, or central system).

  • The charge point is the physical hardware that delivers electricity to the vehicle. It has firmware, a WebSocket client, one or more connectors, sometimes a payment terminal, sometimes an RFID reader.
  • The CSMS is the cloud system that monitors the charger, authorizes sessions, configures pricing and behaviour, collects metering data, and serves as the integration point to higher-layer systems such as OCPI roaming, billing, and the customer app.

The CSMS is operated by the CPO. One CSMS manages anywhere from a handful to hundreds of thousands of charge points.

flowchart LR
    V[Vehicle] -->|ISO 15118<br/>or IEC 61851| CP[Charge point]
    CP <-->|OCPP<br/>WebSocket| CSMS[CSMS<br/>cloud backend]
    CSMS <-->|OCPI| RP[Roaming partners<br/>eMSPs, hubs]
    CSMS --> BD[Billing, app,<br/>ops dashboards]
    style CP fill:#dbeafe,stroke:#2563eb
    style CSMS fill:#dcfce7,stroke:#16a34a

OCPP is the middle link. Vehicle-to-charger is ISO 15118 or simpler signalling. Operator-to-operator is OCPI. OCPP is operator-to-its-own-hardware.

What OCPP actually does

The protocol has a long list of message types, but they cluster into a few job families.

Session lifecycle.

  • Authorize a user’s identifier: RFID card, app token, or ISO 15118 contract.
  • Start a transaction in 1.6, or send a TransactionEvent in 2.0.1.
  • Send periodic meter readings during the session.
  • Stop the transaction and report the total energy delivered.

Operational status.

  • Heartbeat: the charger pings the CSMS regularly to confirm it is alive.
  • StatusNotification: the charger reports state changes (Available, Preparing, Charging, Faulted) for each connector.
  • BootNotification: identification when the charger comes online.

Configuration and control.

  • ChangeConfiguration and SetVariables: the CSMS pushes new settings to the charger.
  • TriggerMessage (coming soon): the CSMS asks the charger to send something specific.
  • Reset: the CSMS reboots the charger.
  • RemoteStartTransaction and RequestStartTransaction: the CSMS initiates a session remotely, which is what happens when a user starts from the app.

Firmware and diagnostics.

Smart charging.

  • SetChargingProfile: define when and how much power the charger can deliver.
  • ClearChargingProfile and GetCompositeSchedule: manage and inspect those profiles.

Reservation.

OCPP 2.0.1 and later add a richer security stack with signed messages, certificate-based mutual auth, and key rotation. They also add a device model for representing the charger’s internal structure of controllers, EVSEs, connectors, and sensors, plus explicit support for ISO 15118 Plug & Charge.

How the conversation actually flows

A typical session, simplified:

  1. Charge point boots. It opens a WebSocket connection to the CSMS URL it has configured, then sends BootNotification with its identity and capabilities.
  2. CSMS responds with Accepted, plus the heartbeat interval and the registration status.
  3. Charge point starts heartbeating. Every five minutes, or whatever interval the CSMS returned, it sends Heartbeat and gets back the current server time, which it uses for clock sync.
  4. A user plugs in a vehicle and presents an RFID card. The charge point sends Authorize with the card’s ID.
  5. CSMS checks the identifier. Is this card on our local whitelist? If not, query the eMSP via OCPI. Respond with Accepted or Invalid.
  6. If accepted, the charge point sends StartTransaction in 1.6 or TransactionEvent (Started) in 2.0.1. This carries the start meter reading and the connector ID.
  7. Charging proceeds. The charge point periodically sends MeterValues, or TransactionEvent (Updated) in 2.0.1, with current power, energy, and other sampled metrics.
  8. The vehicle reaches its target state of charge, or the user unplugs. The charge point sends StopTransaction in 1.6 or TransactionEvent (Ended) in 2.0.1 with the final meter reading.
  9. CSMS processes the completed transaction. It bills the user, generates a CDR for roaming partners via OCPI, and updates dashboards.
  10. Throughout, StatusNotification messages keep the CSMS aware of connector state: Available, Preparing, Charging, Finishing, Available.

Each of these messages has a request and a response, correlated by a unique message ID. The full message flow walkthrough takes the same session frame by frame, and you can replay it yourself in the interactive OCPP simulator without any hardware.

The transport: WebSocket and JSON

OCPP 1.5 used SOAP over HTTP. That was a mess: verbose, hard to debug, polling-based, and awkward for chargers sitting behind NAT or a firewall.

OCPP 1.6 switched to WebSocket, with a fallback SOAP option that essentially nobody uses. The charger opens a persistent WebSocket connection to the CSMS and keeps it open. Both sides can send messages whenever they want, and messages are JSON.

A typical OCPP message on the wire:

[2,"abc123","BootNotification",{"chargePointVendor":"ExampleCo","chargePointModel":"X1"}]

The format is:

  • 2 is the message type: 2 = Call (request), 3 = CallResult (response), 4 = CallError.
  • "abc123" is the unique message ID used for correlation.
  • "BootNotification" is the action name.
  • {...} is the payload.

The response would be:

[3,"abc123",{"currentTime":"2026-06-26T08:00:00Z","interval":300,"status":"Accepted"}]

Once you are past the array-format weirdness it is a simple, debuggable protocol. You can open the network tab in Chrome DevTools on a CSMS dashboard and watch the messages flow in real time. There is a library of ready-to-use OCPP-J examples if you want to copy real frames rather than write them from scratch.

The version differences in one paragraph each

OCPP 1.6 is the workhorse. JSON over WebSocket, roughly 30 message types. It works. It lacks a security model, since the security extensions arrived as a separate add-on in 2018. Its transaction lifecycle is confusing, split across StartTransaction, StopTransaction, and MeterValues, and the data model is essentially free-form. This is the version most of the installed base was commissioned against, which is why it refuses to go away.

OCPP 2.0.1 is the modernization. Restructured transactions, with a single TransactionEvent message replacing StartTransaction and StopTransaction. It introduced the device model for a richer charger representation, native security with mutual TLS and signed messages, better support for multiple connectors per EVSE, cleaner smart-charging primitives, and explicit ISO 15118 Plug & Charge integration. Around 40 message types, but better organized.

OCPP 2.1 is the iteration, published by the Open Charge Alliance in January 2025. It is a smaller delta than 1.6 to 2.0.1 was, and it is backward compatible with 2.0.1. It brings bidirectional power flow for V2G, DER coordination, battery-swap support, ad hoc payment options, and improved certificate management for Plug & Charge.

The full version comparison works through what each release changes and which one to specify for a new deployment.

OCPP vs OCPI vs ISO 15118: which protocol does what

These three get confused constantly, usually because they all appear in the same architecture diagram. Each covers a different link in the chain, and none of them overlaps:

ProtocolRuns betweenAnswers
ISO 15118Vehicle and charge pointWho is this car, and how much power should flow?
OCPPCharge point and CSMSWhat is my hardware doing, and what should it do next?
OCPICPO and eMSPCan this roaming customer charge here, and who bills them?

A useful test: if the question involves a cable, it is ISO 15118. If it involves a piece of hardware reporting to its owner, it is OCPP. If it involves two companies settling up, it is OCPI. The side-by-side comparison goes deeper on where the boundaries actually sit.

Where OCPP doesn’t reach

A few clarifications about what OCPP is not responsible for.

OCPP doesn’t decide whether to authorize a user. It carries the authorization request, but the CSMS makes the decision, sometimes after asking an eMSP via OCPI.

OCPP doesn’t define the actual electricity delivery. That happens between the charger’s internal control and the vehicle, over lower-level signalling: IEC 61851 PWM, or ISO 15118 for the richer cases.

OCPP doesn’t handle payment processing. It can carry the meter values that feed billing, but payment APIs sit outside OCPP entirely.

OCPP doesn’t define the charger’s user interface. Whether the charger has an LCD, a buzzer, a contactless reader, or a screen showing tariffs is up to the OEM.

OCPP doesn’t do roaming. When a customer of eMSP A charges at a CPO B station, OCPP knows nothing about eMSP A. The CSMS handles that relationship over OCPI, and the charger only ever sees its CSMS.

Why OCPP matters for the industry

OCPP is what made vendor-neutral charging infrastructure possible. Without it, every brand would be a silo, and the shape of the industry would be different in three specific ways:

  • Independent CPOs could not exist as a category. Operating chargers you did not manufacture requires a protocol the manufacturer does not control.
  • The CSMS market could not exist either. A platform that works across hardware brands is only buildable because the interface to the hardware is standardized and public.
  • Roaming would have no foundation. OCPI assumes the CPO already has structured, real-time data about its own chargers. OCPP is what produces that data.

If OCPP did not exist, EV charging would look more like the early cellular industry, where every carrier had its own handsets. Instead it looks more like the modern internet, where any device that speaks the standards can talk to any service that speaks them.

What to learn next

If you are new to OCPP, the natural next reads are:

If you are choosing a CSMS, you want one that speaks the OCPP version you will standardize on, most likely 2.0.1, with a credible upgrade path to 2.1. If you are choosing chargers, look for firmware that supports both 1.6 and 2.0.1 so you keep your options open.

OCPP is one of those technologies that is invisible when it works. Every session you have ever started with an app or an RFID card was brokered by a handful of JSON arrays travelling over a WebSocket, and the protocol’s boringness is precisely the point. The interesting engineering in charging happens above and below OCPP. That it stays out of the way is why the industry could scale at all.

OCPP quick check

Q1. OCPP runs between which two entities?
Q2. Which transport does OCPP 1.6 and later use?
Q3. Which message does a charge point send first when it boots up?

Frequently asked questions

Is OCPP the same as OCPI?

No. OCPP runs between a charging station and its operator backend (CSMS). OCPI runs between operators, connecting a CPO and an eMSP for roaming. The two protocols solve different problems and work together.

Which OCPP version should I use?

For new deployments in 2026, OCPP 2.0.1 is the safe default. OCPP 2.1 is the latest release and adds bidirectional power flow, but hardware support for it is early. OCPP 1.6 is what most of the existing installed base speaks, so your backend still has to handle it even if you do not specify it for new hardware.

Is OCPP free to use?

Yes. OCPP is published openly by the Open Charge Alliance (OCA). You do not pay royalties to use it. OCA membership is paid and gives you a voice in the protocol evolution and access to certification, but you can implement OCPP without joining.

Does OCPP work over the cellular network?

Yes. OCPP runs over the internet (TCP/IP) and production charge points commonly connect via cellular, ethernet, or wifi. The transport is WebSockets in 1.6 and later, which works over any reliable IP network.

Can a charging station support multiple OCPP versions?

Firmware that speaks both 1.6 and 2.0.1 is common, usually with a configuration toggle. The CPO chooses which version to enable per charger based on what their backend supports. Check the vendor datasheet for the specific model rather than assuming.

Found this useful? Share it.