What OCPP is for
A charge point is a piece of roadside hardware with a contactor, a meter, a card reader and a cellular modem. On its own it can do almost nothing useful: it does not know who is allowed to charge, what electricity costs, or where to send the meter readings.
OCPP connects it to a CSMS — a Charging Station Management System, the operator's platform. Over that link the charger asks permission, reports state, streams meter data, and accepts commands. Every business function of a charging network is built on those four things.
It is maintained by the Open Charge Alliance and is the reason a charging operator can buy hardware from several vendors and run it all from one platform.
Transport and framing
OCPP-J runs over a persistent WebSocket, initiated by the charge point. The charger dials out, which matters because roadside hardware is almost never publicly addressable.
GET /ocpp/CP014 HTTP/1.1
Host: csms.example.com
Upgrade: websocket
Sec-WebSocket-Protocol: ocpp1.6The subprotocol header is how version selection happens — ocpp1.6 or ocpp2.0.1. A CSMS supporting both picks per connection.
Message framing
Every message is a JSON array with a type identifier first:
| Type | Name | Shape |
|---|---|---|
2 | CALL | [2, "uniqueId", "Action", {payload}] |
3 | CALLRESULT | [3, "uniqueId", {payload}] |
4 | CALLERROR | [4, "uniqueId", "ErrorCode", "description", {details}] |
The uniqueId correlates a result to its call. Because the socket is bidirectional, both sides initiate calls — the charger sends Heartbeat and StatusNotification upward, while the CSMS sends RemoteStartTransaction and Reset downward. A CSMS is a server that is also a client.
The message map
Each of these has a full guide.
Lifecycle and connection
| Message | Direction | Purpose |
|---|---|---|
| BootNotification | CP → CSMS | Registration on connect; sets the heartbeat interval |
| Heartbeat | CP → CSMS | Liveness and clock synchronisation |
| StatusNotification | CP → CSMS | Connector state and fault codes |
Transactions
| Message | Direction | Purpose |
|---|---|---|
| Authorize | CP → CSMS | May this credential charge? |
| StartTransaction | CP → CSMS | Opens a session; CSMS assigns the transaction ID |
| MeterValues | CP → CSMS | Energy, power, voltage, state of charge |
| StopTransaction | CP → CSMS | Final meter reading and stop reason |
| TransactionEvent | CP → CSMS | 2.0.1 only — replaces the three above |
Remote control and operations
| Message | Direction | Purpose |
|---|---|---|
| RemoteStartTransaction | CSMS → CP | Start a charge from the cloud |
| RemoteStopTransaction | CSMS → CP | Stop a charge from the cloud |
| SetChargingProfile | CSMS → CP | Power and current limits |
| Get/ChangeConfiguration | CSMS → CP | Read and write charger settings |
| UpdateFirmware | CSMS → CP | Firmware rollout and diagnostics |
| Reset / ChangeAvailability | CSMS → CP | Restart, or take out of service |
A complete session
How the messages fit together for one driver, one charge:
Charge point CSMS
│ │
├── WebSocket connect (ocpp1.6) ────────►│
├── BootNotification ───────────────────►│
│◄── Accepted, interval: 900 ────────────┤
├── StatusNotification: Available ──────►│
│ │
│ ── driver plugs in and taps card ── │
├── StatusNotification: Preparing ──────►│
├── Authorize { idTag } ────────────────►│
│◄── idTagInfo: Accepted ────────────────┤
├── StartTransaction ───────────────────►│
│◄── transactionId: 770142 ──────────────┤
├── StatusNotification: Charging ───────►│
│ │
├── MeterValues (every 60s) ────────────►│
├── Heartbeat (every 900s) ─────────────►│
│ │
│ ── driver unplugs ── │
├── StopTransaction { meterStop } ──────►│
├── StatusNotification: Finishing ──────►│
├── StatusNotification: Available ──────►│Energy billed is meterStop - meterStart. Everything else in a charging business — roaming settlement, driver invoices, partner disputes — reconciles back to that subtraction.
1.6J versus 2.0.1
| 1.6J | 2.0.1 | |
|---|---|---|
| Released | 2015 | 2020 |
| Deployment | The overwhelming majority of installed hardware | Growing, mostly newer DC hardware |
| Transactions | Start / Stop / MeterValues | One TransactionEvent |
| Configuration | Flat string key-value | Structured components and typed variables |
| Transaction ID | Integer | String |
| Security | Added later by whitepaper | Three security profiles in the core spec |
| Device model | Implicit | Explicit component/variable inventory |
Security
OCPP 1.6 shipped without a security model; it was added afterwards as a separate whitepaper, which means security posture on 1.6 fleets varies enormously. 2.0.1 defines three profiles in the core specification:
| Profile | Transport | Authentication |
|---|---|---|
| 1 | Unsecured HTTP | HTTP Basic |
| 2 | TLS | HTTP Basic |
| 3 | TLS | Client certificates, mutual TLS |
Profile 1 should not exist on a public network — it puts credentials and meter data in clear text over cellular. Profile 3 is the target for new deployments, though it brings certificate lifecycle management into scope, which is a real operational burden on hardware that may be in the field for a decade.
Practical baseline regardless of version: TLS on every connection, per-charger credentials rather than a shared secret, and configuration auditing so a charger cannot be silently repointed at another CSMS.
Where OCPP sits in the stack
Beckn ── open discovery and booking, any buyer app to any provider
│
OCPI ── bilateral roaming, eMSP ↔ CPO
│
OCPP ── operator to its own hardware
│
Charge pointA single driver action can traverse all three. A driver taps “start” in an app found through Beckn; the booking becomes an OCPI START_SESSION to the CPO; the CPO issues RemoteStartTransaction to the charger. Three protocols, three company boundaries, one tap.
| OCPP | OCPI | |
|---|---|---|
| Between | Charger and its own operator | Two companies |
| Transport | Persistent WebSocket | HTTPS request/response |
| Crosses a company boundary | No | Yes |
| Owned by | Open Charge Alliance | EVRoaming Foundation |
The financial join between the layers is the one to get right: the OCPP StopTransaction is the ground truth an OCPI CDR must reconcile against. If those two disagree, the CDR is wrong and you cannot defend the invoice.
An implementation roadmap
| Phase | Build | You can now |
|---|---|---|
| 1 | WebSocket + framing + BootNotification + Heartbeat | Keep chargers connected and know they are alive |
| 2 | StatusNotification | Publish accurate availability |
| 3 | Authorize + Start / Stop | Run and bill real charging sessions |
| 4 | MeterValues | Live progress and granular billing |
| 5 | Remote start / stop | App-driven charging and OCPI roaming |
| 6 | Configuration + firmware + reset | Operate a fleet rather than a demo |
| 7 | Smart charging | Load management and grid participation |
Phases 1 to 4 are a working charging network. Phase 6 is what separates an operator from a prototype — without configuration management and firmware control, a fleet becomes unmaintainable at a few hundred units.
Production lessons
- Design for offline first. Chargers on cellular links lose connectivity constantly. Queued transactions arriving hours late are normal operation, not an error path.
- Trust message timestamps over receipt time for anything financial.
- Make ingestion idempotent. Chargers resend when unsure, and duplicates must never become duplicate charges.
- Reconcile CDRs against StopTransaction continuously. The mismatch rate is the number an audit asks for.
- Serve a synchronised clock in Heartbeat. Every downstream timestamp inherits it.
- Normalise 1.6J and 2.0.1 at the edge. Two billing paths is a permanent tax.
- Certify each charger model. Vendor conformance varies far more than the spec implies; what works on one model is not evidence about another.
- Never publish stale availability. A charger you have not heard from is
UNKNOWN, not available.
Official reference
The normative sources are the OCPP 1.6 and OCPP 2.0.1 specifications published by the Open Charge Alliance, along with the OCPP 1.6 Security Whitepaper. This guide and the linked message pages are written against them, with the operational detail that only appears once hardware from several vendors is running in the field.
Frequently asked questions
The Open Charge Point Protocol, the standard by which a charge point communicates with the operator's management system (CSMS). It carries authorisation requests, status and fault reporting, meter data and remote commands, and it is what lets an operator run hardware from multiple vendors on one platform.
OCPP runs between a charger and its own operator over a persistent WebSocket. OCPI runs between two companies over HTTPS — typically a CPO and an eMSP exchanging locations, tokens, sessions and CDRs. OCPP never crosses a company boundary; OCPI exists to cross one.
In practice you support both. 1.6J is the overwhelming majority of installed hardware and generally cannot be upgraded, since the device model differs too fundamentally. Any CSMS running a real fleet speaks both side by side and normalises them into one internal model.
The charger continues operating under its configured offline authorisation policy, generates temporary local transaction IDs, and queues messages for replay. Platforms must therefore expect transactions arriving hours late, out of order and sometimes duplicated.
Profile 1 is unsecured HTTP with basic authentication, profile 2 is TLS with basic authentication, and profile 3 is TLS with client certificates and mutual authentication. Profile 1 should not be used on a public network, and profile 3 is the target for new deployments.
By subtracting meterStart on StartTransaction from meterStop on StopTransaction. Both are cumulative register readings in watt-hours, and that subtraction is what every roaming settlement and driver invoice ultimately reconciles against.