# OCPPLab — Full Content > Full-text corpus of OCPPLab marketing guides. OCPPLab is a browser-based OCPP and OCPI simulator for testing EV chargers, CPMS integrations, and roaming flows. Supports OCPP 1.6, OCPP 2.0.1, OCPI 2.1.1, and OCPI 2.2.1. Operator and protocol documentation is served by the docs app — ingest https://ocpplab.com/docs/llms-full.txt. See /llms.txt for the link-only index of marketing pages. # Documentation Operator guides and OCPP/OCPI protocol references live in the docs app at https://ocpplab.com/docs. Ingest the full docs corpus from https://ocpplab.com/docs/llms-full.txt. --- # Reference Guides ## What Is OCPP? Open Charge Point Protocol Explained Source: https://ocpplab.com/blog/what-is-ocpp What OCPP is, how the Open Charge Point Protocol works, and what EV charging teams must know about OCPP 1.6, 2.0.1, message flows, security, and testing. **Quick answer:** OCPP (Open Charge Point Protocol) is an open WebSocket-based protocol from the [Open Charge Alliance](https://www.openchargealliance.org/) that lets EV chargers communicate with a backend platform (a CPMS). It standardizes how a charger registers, authorizes users, runs transactions, reports meter values, and applies smart charging — across vendors. The two production versions are **OCPP 1.6** (the most widely deployed) and **OCPP 2.0.1** (the modern standard with mandatory security profiles, a device model, and ISO 15118 support). OCPP (Open Charge Point Protocol) is the standard that lets EV chargers communicate with a backend platform such as a [CPMS (Charging Station Management System)](/blog/what-is-CPMS). Maintained by the Open Charge Alliance (OCA), OCPP allows chargers from different manufacturers to connect to compatible software without proprietary lock-in, which is why it underpins most modern EV charging networks. As of 2024, the [Open Charge Alliance](https://openchargealliance.org/) counts more than 400 member organizations worldwide, and every major charger manufacturer --- ABB, Schneider Electric, EVBox, Wallbox, Alfen, Tritium, Kempower, and Autel --- ships hardware with OCPP support built in. The specifications themselves run to several hundred pages: per the [OCPP specification published by the OCA](https://openchargealliance.org/protocols/open-charge-point-protocol/), **OCPP 1.6 Edition 2** defines **28 unique core actions** (10 charger-initiated, 19 CPMS-initiated counting `DataTransfer` once) plus **11 more in the Security Whitepaper edition 2**, while **OCPP 2.0.1** reorganizes and substantially expands the message set across **16 functional blocks** (labelled A through P), covering many more messages than 1.6. If you are evaluating implementation or QA work right now, go straight to [OCPP 1.6 testing](/protocols/ocpp-1-6), [OCPP 2.0.1 testing](/protocols/ocpp-2-0-1), or [platform features](/features). ## Why Does OCPP Exist? Before OCPP, every EV charger manufacturer built proprietary communication protocols. A ChargePoint station could only talk to ChargePoint's backend. An ABB charger required ABB's software. This created four systemic problems: - **Vendor lock-in**: Operators were permanently tied to a single manufacturer's ecosystem for both hardware and software. - **No interoperability**: Running a mixed-brand charging network was either impossible or required expensive custom integrations for each charger model. - **High integration costs**: Every new charger model demanded months of bespoke protocol development, driving up costs for CPMS vendors. - **Slow innovation**: Closed systems meant features developed by one vendor stayed siloed, and the industry moved slowly as a result. The [Open Charge Alliance (OCA)](https://www.openchargealliance.org/), founded in 2014 in the Netherlands, created OCPP to solve these problems with a single, open, royalty-free standard. The specifications are freely available from the OCA at [openchargealliance.org/protocols/open-charge-point-protocol](https://openchargealliance.org/protocols/open-charge-point-protocol/). Today, OCPP is mandated or strongly encouraged by public funding programs across the EU, UK, and parts of the United States (notably California's NEVI program), making it the de facto global standard for EV charger communication. ## How Does OCPP Work? OCPP operates on a client-server architecture where the charge point (the physical charger) acts as the client and the CPMS acts as the server. Communication flows over persistent WebSocket connections, enabling real-time bidirectional messaging between charger and backend. ### Connection Lifecycle The WebSocket connection lifecycle follows a predictable pattern: 1. **DNS resolution and TCP handshake**: The charger resolves the CPMS hostname and establishes a TCP connection to the configured endpoint (typically `wss://CPMS.example.com/ocpp/`). 2. **TLS negotiation** (if using `wss://`): The charger and server negotiate a secure TLS session. OCPP 2.0.1 defines three specific security profiles governing this step. 3. **WebSocket upgrade**: The charger sends an HTTP Upgrade request with `Sec-WebSocket-Protocol: ocpp1.6` or `ocpp2.0.1`. The server validates the charger's identity (often from the URL path, e.g., `/ocpp/CP001`) and accepts or rejects the upgrade. 4. **BootNotification**: Immediately after the WebSocket is established, the charger sends a `BootNotification` message containing its vendor, model, serial number, and firmware version. The CPMS responds with `Accepted`, `Pending`, or `Rejected` along with a heartbeat interval. 5. **Steady-state communication**: Both sides exchange messages over the persistent connection. The charger sends periodic `Heartbeat` messages to confirm connectivity. Either side can initiate requests at any time. 6. **Reconnection**: If the connection drops, the charger automatically reconnects using configurable retry logic with exponential backoff. For a deep dive into WebSocket connection management, error handling, and reconnection strategies, see our [OCPP WebSocket guide](/blog/ocpp-websocket-guide). ### Request-Response Pattern Every OCPP interaction follows a strict request-response pattern using JSON-RPC-style framing over WebSocket. Messages are JSON arrays with a specific structure: **Call (Request)**: ```json [2, "unique-message-id", "BootNotification", {"chargePointVendor": "OCPPLab", "chargePointModel": "Emulator"}] ``` - `2` = Message type (Call) - `"unique-message-id"` = Unique identifier for correlation - `"BootNotification"` = Action name - `{...}` = Payload **CallResult (Successful Response)**: ```json [3, "unique-message-id", {"status": "Accepted", "currentTime": "2025-02-20T10:00:00Z", "interval": 300}] ``` - `3` = Message type (CallResult) - Same message ID as the originating Call - `{...}` = Response payload **CallError (Error Response)**: ```json [4, "unique-message-id", "FormationViolation", "Invalid payload", {}] ``` - `4` = Message type (CallError) - Standard error codes like `NotImplemented`, `NotSupported`, `InternalError`, `ProtocolError`, `SecurityError`, and `FormationViolation` Each side can only have one outstanding request at a time per the specification (though some implementations relax this). A request must receive a response within a configurable timeout, typically 30 seconds. ## OCPP Versions: A Complete History The protocol has evolved through several versions, each addressing limitations of its predecessor: | Version | Year | Transport | Status | |---------|------|-----------|--------| | OCPP 1.2 | 2010 | SOAP/XML | Legacy, rarely seen | | OCPP 1.5 | 2012 | SOAP/XML | Legacy, still in some older deployments | | OCPP 1.6 | 2015 | SOAP or WebSocket/JSON | Most widely deployed version globally | | OCPP 2.0 | 2018 | WebSocket/JSON | Superseded by 2.0.1, never widely adopted | | OCPP 2.0.1 | 2020 | WebSocket/JSON | Latest stable version, growing adoption | For a detailed feature-by-feature comparison, see our dedicated [OCPP 1.6 vs 2.0.1 comparison](/blog/ocpp-1-6-vs-2-0-1). If you are evaluating tooling rather than protocol features, see [best OCPP emulators compared](/blog/best-ocpp-emulators-compared). ### OCPP 1.6 Released in 2015, OCPP 1.6 remains the most widely deployed version in the field by a wide margin. It introduced JSON over WebSocket as a transport option alongside the original SOAP/XML format, which dramatically simplified implementations. Key capabilities of OCPP 1.6: - **Smart Charging**: Basic charging profile management with `SetChargingProfile` and `ClearChargingProfile` - **Remote Operations**: Start and stop transactions remotely, reset chargers, unlock connectors - **Authorization**: Local authorization list management and remote ID tag validation - **Firmware Management**: Remote firmware updates and diagnostics file uploads - **Meter Values**: Periodic and transaction-based energy measurement reporting - **Reservation**: Reserve a connector for a specific ID tag OCPP 1.6 core defines 28 unique actions split between charger-initiated and CPMS-initiated operations (with `DataTransfer` going in both directions). The optional Security Whitepaper edition 2 extension adds 11 more — signed firmware, certificate management, log upload, and `SecurityEventNotification` — for a total of about 39 when both are implemented. ### OCPP 2.0.1 OCPP 2.0.1 represents a ground-up rearchitecture of the protocol. Released in 2020, it addresses the most significant gaps in 1.6 while adding support for modern EV charging requirements like [Plug & Charge (ISO 15118)](/blog/iso-15118-plug-and-charge) and vehicle-to-grid (V2G). Key improvements over 1.6: - **Device Model**: A comprehensive, standardized data model for charger configuration --- replacing the ad-hoc key-value approach in 1.6 with a structured component/variable hierarchy - **ISO 15118 Support**: Native support for certificate-based vehicle authentication, enabling true Plug & Charge without RFID cards - **Security Profiles**: Three defined security levels with mandatory TLS, signed firmware updates, and secure boot chains - **Transaction Handling**: Redesigned transaction event model that eliminates the "hanging transaction" problem in 1.6 where a `StopTransaction` message lost in transit could leave a transaction open indefinitely - **Display Messages**: Remote control of charger screen content for pricing information, instructions, or advertisements - **Cost and Tariff**: Real-time cost updates sent to the charger during a transaction - **Improved Smart Charging**: Composite charging schedules, external power limits, and better integration with energy management systems OCPP 2.0.1 defines many more messages than 1.6, organized into 16 functional blocks spanning provisioning, security, transactions, smart charging, and ISO 15118. ## OCPP 1.6 vs 2.0.1: What's the Difference? | Feature | OCPP 1.6 | OCPP 2.0.1 | |---------|----------|------------| | **Transport** | WebSocket/JSON or SOAP/XML | WebSocket/JSON only | | **Security** | Optional TLS in core; Profiles 0–3 via Security Whitepaper edition 2 (opt-in) | Mandatory security profiles (1/2/3) | | **ISO 15118** | No native support (hacky `DataTransfer` workarounds) | Full native support for Plug & Charge | | **Smart Charging** | Single `ChargingProfile` stack per connector | Composite schedules, EVSE-level and station-level profiles | | **Device Management** | `GetConfiguration`/`ChangeConfiguration` with flat key-value pairs | Structured Device Model with Components and Variables | | **Transaction Model** | `StartTransaction` + `StopTransaction` (paired messages) | `TransactionEvent` (single message type with Started/Updated/Ended) | | **Message Format** | JSON arrays `[2, id, action, payload]` | Same JSON array format, backward-compatible framing | | **Message Count** | 28 core actions (39 with Security Whitepaper edition 2) | Many more, across 16 functional blocks | | **Firmware Update** | Basic via `UpdateFirmware`; `SignedUpdateFirmware` available via Security Whitepaper edition 2 | Signed firmware with certificate validation | | **Display Messages** | Not supported | `SetDisplayMessage`, `GetDisplayMessages`, `ClearDisplayMessage` | | **Cost Information** | Not supported | Running cost and final cost sent to charger | | **Reservation** | Reserve single connector | Reserve EVSE with connector type preference | | **Connector Model** | Flat: ChargePoint has Connectors | Hierarchical: Station > EVSE > Connector | | **Logging** | `GetDiagnostics` in core; `GetLog` / `LogStatusNotification` via Security Whitepaper edition 2 | `GetLog` with structured log types (diagnostics, security) | | **Certificate Management** | Not in core; full cert lifecycle (`InstallCertificate`, `SignCertificate`, `CertificateSigned`, `DeleteCertificate`, `GetInstalledCertificateIds`) available via Security Whitepaper edition 2 | Full certificate lifecycle management | | **Local Auth List** | Basic ID tag list | Extended with ID token types and grouping | | **Error Handling** | Limited; lost `StopTransaction` causes orphan transactions | Sequence numbers and event-based model prevent data loss | ## OCPP Message Types: Complete Reference ### OCPP 1.6 Messages **Charger-initiated (Charge Point to CPMS):** | Message | Purpose | |---------|---------| | `Authorize` | Validate an RFID tag or other credential before allowing charging | | `BootNotification` | Register with the CPMS on startup, report vendor/model/firmware | | `DataTransfer` | Vendor-specific data exchange (escape hatch for custom features) | | `DiagnosticsStatusNotification` | Report status of a diagnostics upload | | `FirmwareStatusNotification` | Report status of a firmware update | | `Heartbeat` | Periodic keep-alive; CPMS responds with current time for clock sync | | `MeterValues` | Report energy consumption, power, voltage, current, temperature, SoC | | `StartTransaction` | Notify CPMS that a charging session has started | | `StatusNotification` | Report connector status changes (Available, Charging, Faulted, etc.) | | `StopTransaction` | Notify CPMS that a charging session has ended, include final meter value | **CPMS-initiated (CPMS to Charge Point):** | Message | Purpose | |---------|---------| | `CancelReservation` | Cancel a previously made reservation | | `ChangeAvailability` | Set a connector to operative or inoperative | | `ChangeConfiguration` | Modify a configuration key on the charger | | `ClearCache` | Clear the charger's local authorization cache | | `ClearChargingProfile` | Remove one or more charging profiles | | `DataTransfer` | Vendor-specific data exchange | | `GetCompositeSchedule` | Retrieve the combined effective charging schedule | | `GetConfiguration` | Read configuration key values from the charger | | `GetDiagnostics` | Request the charger to upload diagnostics logs | | `GetLocalListVersion` | Check version number of the local authorization list | | `RemoteStartTransaction` | Remotely start a charging session | | `RemoteStopTransaction` | Remotely stop a charging session | | `ReserveNow` | Reserve a connector for a specific ID tag | | `Reset` | Soft or hard reset the charger | | `SendLocalList` | Update or replace the local authorization list | | `SetChargingProfile` | Install a charging profile for load management | | `TriggerMessage` | Request the charger to send a specific message (e.g., StatusNotification) | | `UnlockConnector` | Remotely unlock the charging cable connector | | `UpdateFirmware` | Instruct the charger to download and install new firmware | ### OCPP 2.0.1 Messages (Selected Key Additions) OCPP 2.0.1 retains the concepts from 1.6 but reorganizes and extends them significantly. Notable new or redesigned messages include: | Message | Purpose | |---------|---------| | `TransactionEvent` | Replaces `StartTransaction`/`StopTransaction` with a unified event model | | `SetVariables` / `GetVariables` | Replace `ChangeConfiguration`/`GetConfiguration` with structured device model access | | `GetBaseReport` | Request a full dump of the charger's device model | | `NotifyReport` | Charger sends device model data in response to `GetBaseReport` | | `RequestStartTransaction` / `RequestStopTransaction` | Renamed remote start/stop with enhanced parameters | | `SetDisplayMessage` | Display custom messages on the charger screen | | `CostUpdated` | Send running cost information during a transaction | | `SetChargingProfile` | Enhanced with composite schedule support and EVSE-level targeting | | `GetCompositeSchedule` | Returns the effective composite from all stacked profiles | | `SetNetworkProfile` | Configure charger network settings remotely | | `InstallCertificate` / `DeleteCertificate` / `GetInstalledCertificateIds` | Full certificate lifecycle management | | `SignCertificate` | Charger requests a new certificate from the CPMS | | `Get15118EVCertificate` | ISO 15118 certificate provisioning for Plug & Charge | | `NotifyEVChargingNeeds` | Vehicle communicates its charging requirements via ISO 15118 | | `ClearedChargingLimit` | External charging limit has been removed | | `NotifyChargingLimit` | Report external limits imposed by energy management | | `ReportChargingProfiles` | Charger reports all installed charging profiles | | `CustomerInformation` | Retrieve or clear customer-related data stored on the charger | | `LogStatusNotification` | Report status of a log upload operation | | `SecurityEventNotification` | Report security-related events (tamper detection, auth failures) | ## What Are the OCPP Security Profiles? OCPP 2.0.1 defines three security profiles that provide escalating levels of protection. Security was one of the weakest areas in OCPP 1.6, where TLS was optional and most deployments ran unencrypted WebSocket connections. ### Security Profile 1: Basic Authentication Security Profile 1 uses unsecured transport (ws://) with HTTP Basic Authentication. The charger sends a username (typically the charge point identity) and password in the WebSocket handshake headers. - **Transport**: Unencrypted WebSocket (`ws://`) - **Authentication**: HTTP Basic Auth (password in Authorization header) - **Use case**: Lab environments, isolated private networks - **Risk**: Credentials and all OCPP messages travel in plaintext; vulnerable to interception This profile exists primarily for backward compatibility and testing. It should never be used in production deployments over public networks. ### Security Profile 2: TLS with Basic Authentication Security Profile 2 adds TLS encryption while retaining password-based authentication. The charger validates the CPMS server certificate against a trusted root, ensuring it connects to the legitimate backend. - **Transport**: Encrypted WebSocket (`wss://`) with server-side TLS - **Authentication**: HTTP Basic Auth over TLS - **Certificate**: Charger validates CPMS server certificate - **Use case**: Production deployments where client certificate management is not feasible - **Advantage**: All traffic is encrypted; CPMS identity is verified ### Security Profile 3: TLS with Client-Side Certificates Security Profile 3 provides mutual TLS (mTLS) authentication. Both the charger and the CPMS present and validate X.509 certificates, providing the strongest available authentication. - **Transport**: Encrypted WebSocket (`wss://`) with mutual TLS - **Authentication**: Client certificate (charger) + server certificate (CPMS) - **Certificate management**: Requires PKI infrastructure for provisioning, rotating, and revoking charger certificates - **Use case**: High-security deployments, public charging infrastructure, compliance-driven environments - **Advantage**: Eliminates password-based vulnerabilities; cryptographic identity verification for both endpoints Additionally, OCPP 2.0.1 mandates signed firmware updates. The charger validates the cryptographic signature of firmware binaries before installation, preventing malicious firmware injection --- a critical concern for internet-connected devices on public infrastructure. ## How Does Smart Charging Work with OCPP? [Smart charging](/blog/smart-charging-explained) is one of OCPP's most important features. It enables dynamic power management across a charging site, balancing grid constraints, energy costs, renewable availability, and vehicle needs. ### How SetChargingProfile Works A charging profile defines a power or current limit over time. The CPMS sends a `SetChargingProfile` message to the charger containing: - **Stack level**: Priority of this profile (higher levels override lower ones) - **Charging profile purpose**: `ChargePointMaxProfile` (site-level limit), `TxDefaultProfile` (default for new transactions), or `TxProfile` (specific to an active transaction) - **Charging schedule**: A time-based series of power or current limits Example: A site with 150 kW of available grid capacity and 4 DC fast chargers can use `ChargePointMaxProfile` to distribute power dynamically. When one charger is idle, the others can draw more. When all four are active, each gets 37.5 kW. When grid load peaks, the CPMS can reduce the site limit to 100 kW, and the charger recalculates the composite schedule. In OCPP 1.6, charging profiles operate at the connector level with a simple stack. In OCPP 2.0.1, the system is significantly more capable: - **EVSE-level and station-level profiles**: Apply limits at different points in the hierarchy - **Composite schedule calculation**: The charger computes the effective limit from all active profiles, and the CPMS can query this composite via `GetCompositeSchedule` - **External limits**: The charger can report constraints from an external energy management system via `NotifyChargingLimit` - **Absolute and relative schedules**: Profiles can be tied to absolute timestamps or relative to transaction start Smart charging is essential for fleet depot charging, workplace charging, and residential multi-unit installations where grid capacity is shared. ## Who Uses OCPP? OCPP adoption spans the entire EV charging value chain. ### Charge Point Operators (CPOs) CPOs deploy and manage physical charging infrastructure. Major CPOs running OCPP-connected networks include: - **ChargePoint** (North America, Europe) --- operates one of the largest OCPP-connected networks globally - **Fastned** (Europe) --- high-power fast charging along highways - **EVgo** (United States) --- one of the largest public fast-charging networks in the U.S. - **Allego** (Europe) --- pan-European charging network - **Shell Recharge / Ubitricity** (Global) --- leveraging OCPP to unify charger management across acquired brands - **bp pulse** (Europe, North America) --- rapidly expanding OCPP-connected infrastructure ### CPMS Vendors Software companies building charging station management systems that communicate with chargers via OCPP: - **Driivz** (acquired by Vontier) - **EVConnect** - **AMPECO** - **Current** - **EV.energy** - **Open Charge Point (open-source)** ### Charger Manufacturers Hardware manufacturers shipping OCPP-compliant chargers: - **ABB E-mobility** --- DC fast chargers (Terra series) - **Schneider Electric** --- AC and DC chargers for commercial deployments - **EVBox** --- residential and commercial AC chargers - **Wallbox** --- residential and small commercial chargers - **Alfen** --- smart AC chargers popular in the Netherlands - **Tritium** --- high-power DC fast chargers - **Kempower** --- modular DC fast charging systems - **Autel Energy** --- AC and DC chargers for North American market - **BTC Power** --- DC fast chargers for fleet and public deployments ### Energy Companies and Utilities Utilities integrating EV charging into grid management strategies use OCPP's smart charging capabilities to implement demand response, time-of-use optimization, and vehicle-to-grid (V2G) programs. Companies like Enel X, E.ON, and Engie are active participants in the OCPP ecosystem. ## OCPP vs OCPI vs OICP: How Do They Compare? OCPP is one of several open protocols in the EV charging ecosystem. Each serves a different purpose. | Protocol | Full Name | Purpose | Communication Path | |----------|-----------|---------|-------------------| | **OCPP** | Open Charge Point Protocol | Charger-to-backend communication | Charge Point <-> CPMS | | **OCPI** | Open Charge Point Interface | Roaming and interoperability between networks | CPMS <-> CPMS (or CPMS <-> eMSP) | | **OICP** | Open InterCharge Protocol | Roaming (primarily Hubject ecosystem) | CPMS <-> Hubject Hub <-> CPMS | | **ISO 15118** | Vehicle-to-grid communication | Vehicle-to-charger communication | EV <-> Charge Point | | **OpenADR** | Open Automated Demand Response | Grid demand response signals | Utility <-> Energy Management System | **OCPP** operates between the charger and the backend. It handles "make the charger do things" --- start charging, report meter values, update firmware. **[OCPI](/blog/what-is-ocpi)** operates between charging networks. It handles "let an eMSP customer use a CPO's charger" --- roaming, real-time location data, tariff information, and CDR (Charge Detail Record) exchange. If OCPP is the protocol inside a network, OCPI is the protocol between networks. **OICP** serves a similar roaming purpose to OCPI but uses a centralized hub model (Hubject) rather than peer-to-peer connections. It is dominant in Germany and parts of Central Europe. **ISO 15118** operates between the vehicle and the charger (below OCPP in the stack). It enables Plug & Charge authentication and communicates the vehicle's charging requirements. OCPP 2.0.1 has specific messages to relay ISO 15118 data between the charger and CPMS. ## How Do You Test OCPP Implementations? Testing OCPP is inherently complex. The specification defines hundreds of message flows, error scenarios, and state transitions that must work correctly across different network conditions. For a comprehensive testing approach, see our [OCPP testing guide](/blog/ocpp-testing-guide) and [EV charger testing guide](/blog/ev-charger-testing-guide). ### Challenges of Physical Testing Testing with real hardware is slow and expensive: - A single networked DC fast charger is a major capital purchase, and grid upgrades, trenching, and permitting push the installed cost far higher - Testing requires physical EV connectors, power supplies, and often actual vehicles - Reproducing edge cases (network drops mid-transaction, firmware corruption, concurrent sessions) is difficult with physical equipment - Test cycles with hardware typically take weeks to months ### Simulation-Based Testing **OCPPLab** provides cloud-based OCPP simulation that eliminates these constraints: - **Scale**: Deploy 1,000+ virtual charge points in minutes, simulating an entire charging network - **Protocol coverage**: Test both OCPP 1.6 and 2.0.1 with full message type support - **Realistic behavior**: Simulate real charger behaviors from 100+ device models, including vendor-specific quirks and timing characteristics - **Edge case testing**: Simulate network failures, malformed messages, slow responses, concurrent operations, and protocol error conditions that are nearly impossible to reproduce with hardware - **CI/CD integration**: Automate regression testing as part of your development pipeline - **Smart charging validation**: Test complex charging profile scenarios, composite schedule calculations, and load management algorithms Teams using OCPPLab typically compress OCPP QA cycles from months to weeks and sharply reduce testing infrastructure costs. ## OCPP Certification and Compliance The Open Charge Alliance operates an OCPP certification program that validates conformance to the specification. Certification involves: 1. **Self-testing**: Vendors run the OCA's test tool against their implementation 2. **Conformance testing**: An accredited test lab executes the official test suite 3. **Interoperability testing**: The implementation is tested against other certified products Certified products are listed in the OCA's product directory. While certification is not legally required in most jurisdictions, many RFPs and government funding programs require or strongly prefer OCA-certified products. The EU's Alternative Fuels Infrastructure Regulation (AFIR) references OCPP as the communication standard for publicly accessible charging points. ## Frequently Asked Questions ### Is OCPP free to use? Yes. OCPP is an open protocol published by the Open Charge Alliance under royalty-free terms. Anyone can download the specification and implement it without licensing fees. The specification documents are freely available on the OCA website. Certification is optional and involves a fee, but implementing the protocol itself costs nothing. ### What is the difference between OCPP and OCPI? OCPP handles communication between a charger and its management backend (CPMS) --- operations like starting charging sessions, reporting energy usage, and updating firmware. OCPI handles communication between different charging networks for roaming, allowing an EV driver subscribed to one network to use chargers on another. OCPP operates inside a network; OCPI operates between networks. ### Do all EV chargers support OCPP? Most commercial EV chargers sold today support OCPP 1.6 at minimum. Tesla Superchargers historically used a proprietary protocol, but Tesla has begun adopting OCPP for its chargers that serve non-Tesla vehicles as part of NEVI-funded deployments. Some low-cost residential chargers may lack OCPP support since they are designed for standalone operation without backend management. ### What is a CPMS? A CPMS (Charging Station Management System) is the backend software platform that manages a network of EV chargers via OCPP. It handles user authorization, session management, billing, energy monitoring, remote operations, firmware updates, and analytics. Also referred to as CPMS (Charge Point Management System) or simply "the backend." The term CPMS is used in OCPP 2.0.1, while OCPP 1.6 uses "Central System." ### Which OCPP version should I implement? If you are starting a new implementation in 2025, support both OCPP 1.6 and 2.0.1. Most chargers in the field still run 1.6, so your CPMS needs 1.6 support for backward compatibility. However, new charger models increasingly ship with 2.0.1 support, and features like ISO 15118 Plug & Charge, advanced security profiles, and the structured device model require 2.0.1. The two versions differ substantially in security, device modeling, and transaction handling. ### How does OCPP handle offline charging? OCPP supports offline operation through the Local Authorization List. The CPMS pushes a list of authorized ID tags to the charger via `SendLocalList`. When the charger loses its WebSocket connection, it can still authorize users against this local list and start charging sessions. Transaction data (meter values, start/stop events) is queued locally and transmitted to the CPMS when connectivity is restored. OCPP 2.0.1 improves this with its event-based transaction model, which handles message loss more gracefully than 1.6's paired start/stop messages. ### Is OCPP secure? Core OCPP 1.6 has minimal built-in security --- TLS is optional, and many deployments run unencrypted. The optional **OCPP 1.6 Security Whitepaper edition 2** retroactively adds security profiles (0/1/2/3), certificate management, signed firmware updates, and `SecurityEventNotification` to 1.6, but it is opt-in per deployment, so a large portion of the installed base still runs without it. OCPP 2.0.1 makes the same profile model mandatory (renumbered Profile 1/2/3) and bakes signed firmware and security event logging into the core spec. For production deployments, Security Profile 2 (TLS with basic auth) is the practical minimum, and Security Profile 3 (mutual TLS) is recommended for public infrastructure. ### What is the OCPP heartbeat? The `Heartbeat` message is a lightweight keep-alive sent by the charger to the CPMS at a regular interval (configured in the `BootNotification` response, typically 30--300 seconds). It serves two purposes: confirming that the charger is online and connected, and synchronizing the charger's internal clock with the CPMS server time (the `Heartbeat` response includes the current UTC timestamp). If the CPMS stops receiving heartbeats, it marks the charger as offline. ### Can OCPP support vehicle-to-grid (V2G)? OCPP 2.0.1 includes foundational support for V2G through its ISO 15118 integration. The `NotifyEVChargingNeeds` message can communicate bidirectional power flow requirements, and charging profiles can specify negative power values for energy export back to the grid. Full V2G orchestration typically requires additional protocols (like OpenADR for demand response signals), but OCPP 2.0.1 provides the charger-to-backend communication layer needed to participate in V2G programs. ### What happens when OCPP messages fail? When a message fails (timeout, network error, or `CallError` response), the behavior depends on the message type. Critical messages like `StartTransaction` and `StopTransaction` in OCPP 1.6 are queued and retried until delivered. In OCPP 2.0.1, the `TransactionEvent` message carries a per-transaction `seqNo` and the Charging Station replays queued offline events in order on reconnect, so the CPMS can detect gaps and reconstruct the full transaction without losing data. (OCPP 2.0.1 does not define an explicit retransmission request — gap recovery relies on the Charging Station's offline message queue.) For a complete guide to error handling, see our [OCPP error codes reference](/blog/ocpp-error-codes-reference). --- ## What Is OCPI? EV Charging Roaming Protocol Explained Source: https://ocpplab.com/blog/what-is-ocpi What OCPI is, how EV charging roaming works, and what CPOs and eMSPs must know about OCPI 2.1.1 vs 2.2.1, all 8 modules, hubs, and how to implement it. **Quick answer:** OCPI (Open Charge Point Interface) is an open REST/HTTPS protocol from the [EVRoaming Foundation](https://evroaming.org/) used between EV charging back-office systems — typically a CPO (Charge Point Operator) and an eMSP (e-Mobility Service Provider) — to enable roaming. The two production versions are **OCPI 2.1.1** (the broad interoperability baseline, alpha-3 country codes, no Hub role) and **OCPI 2.2.1** (adds Hub/NSP/NAP/SCSP roles, ChargingProfiles and HubClientInfo modules, alpha-2 country codes + party_id). OCPI (Open Charge Point Interface) is the protocol that enables EV charging roaming between backend systems such as CPO and eMSP platforms. Developed and maintained by the [EVRoaming Foundation](https://evroaming.org/), OCPI standardizes how networks exchange locations, sessions, tariffs, tokens, and billing records so drivers can charge outside their home network. The current specifications and reference implementations are hosted on [GitHub at ocpi/ocpi](https://github.com/ocpi/ocpi). If you are implementing or validating a roaming stack, continue with [OCPI 2.1.1 testing](/protocols/ocpi-2-1-1) and [OCPI 2.2.1 testing](/protocols/ocpi-2-2-1) for version-specific coverage. If you are deciding which version to implement, read the full [OCPI 2.1.1 vs 2.2.1 comparison](/blog/ocpi-2-1-1-vs-2-2-1). If you are preparing for partner onboarding or hub validation, see [OCPI roaming testing](/use-cases/ocpi-roaming-testing) or [book an OCPI demo](/contact). ## Why Does OCPI Exist? The EV Charging Roaming Problem Without a roaming protocol, every EV charging network operates as a walled garden. A driver subscribed to Network A cannot use Network B's chargers without creating a separate account, downloading another app, and managing another payment method. This fragmentation is the single largest friction point for EV adoption today. OCPI solves this by standardizing how charging networks exchange data. The result is an experience similar to mobile phone roaming: one subscription, universal access. Here is what OCPI enables in practice: - **Driver convenience**: A single app or RFID card works across all participating networks, eliminating the need for dozens of accounts - **Network growth**: [CPOs](/blog/cpo-vs-emsp-explained) gain access to a larger customer base without incremental marketing spend - **Automated settlement**: Billing, invoicing, and revenue sharing between networks happen programmatically through standardized Charge Detail Records - **Market expansion**: [eMSPs](/blog/cpo-vs-emsp-explained) can offer nationwide or continent-wide coverage without owning or operating a single charger - **Regulatory compliance**: The EU Alternative Fuels Infrastructure Regulation (AFIR) requires ad-hoc access to all public chargers, which in practice demands roaming capability As of February 2026, [GIREVE's monthly *Roaming in Europe* barometer](https://www.gireve.com/roaming-in-europe-february-2026/) reported roughly **695,000 charge points** connected to its OCPI-mediated platform across dozens of European countries, making it the largest roaming hub on the continent. [Hubject's intercharge network](https://www.hubject.com/) — which carries both OCPI and OICP traffic — reports connecting **over 1,000,000 charge points across 70+ countries on four continents**. These figures reflect the protocol's central role in EV roaming today. The OCPI 2.2.1 specification itself defines **8 modules** (Locations, Sessions, CDRs, Tariffs, Tokens, Commands, ChargingProfiles, HubClientInfo) on top of Credentials + Versions — published openly by the [EVRoaming Foundation](https://evroaming.org/). ## How Does OCPI Work? Architecture and Technical Design OCPI is a REST API protocol built on standard HTTP. Two parties -- typically a [CPO (Charge Point Operator) and an eMSP (e-Mobility Service Provider)](/blog/cpo-vs-emsp-explained) -- establish a peer-to-peer connection and exchange structured JSON data over HTTPS. Unlike [OCPP](/blog/what-is-ocpp), which uses persistent WebSocket connections between chargers and backends, OCPI uses stateless HTTP requests between backend systems. ### The OCPI Credential Handshake Before any data exchange occurs, both parties must complete a credential handshake. This is a mutual authentication process: 1. **Registration**: Party A sends a `POST /credentials` request to Party B, including its `TOKEN_A` (a pre-shared token exchanged out-of-band) and a list of supported OCPI versions 2. **Version negotiation**: Both parties agree on the highest mutually supported OCPI version 3. **Endpoint discovery**: Each party retrieves the other's module endpoints via `GET /versions/{version_number}` 4. **Token exchange**: Party B responds with `TOKEN_B`. From this point, Party A uses `TOKEN_B` to authenticate requests to Party B, and vice versa 5. **Connection active**: Both parties can now exchange data through the agreed-upon module endpoints This handshake ensures that credentials are never static. Either party can re-register at any time to rotate tokens, which is a significant security advantage over protocols that rely on fixed API keys. ### Push and Pull Communication Modes OCPI supports two data synchronization modes, and most production deployments use both: **Pull mode** (Client-Owned): The receiving party periodically requests data from the sender using standard `GET` requests with pagination. For example, an eMSP pulls location data from a CPO by calling `GET /locations?date_from=2025-01-01T00:00:00Z&offset=0&limit=50`. This is simple to implement but introduces latency between updates. **Push mode** (Server-Owned): The sending party proactively pushes updates to the receiver using `PUT`, `PATCH`, or `DELETE` requests. When a CPO updates a charger's status, it immediately sends a `PATCH /locations/{location_id}/{evse_id}` to the eMSP. This provides near-real-time data but requires the receiver to expose endpoints that accept incoming requests. In practice, most implementations use pull mode for initial data synchronization (fetching the full dataset) and push mode for incremental updates (real-time status changes, new sessions, etc.). ### OCPI Versioning and Endpoint Discovery Every OCPI implementation exposes a versions endpoint that lists all supported protocol versions: ``` GET /ocpi/versions ``` This returns a list of version objects, each containing a version number and URL. The connecting party then queries the specific version URL to discover available module endpoints. This design means a single OCPI server can support multiple protocol versions simultaneously, enabling gradual migration without breaking existing connections. ## All OCPI Modules Explained OCPI is organized into modules, each handling a specific domain of the roaming workflow. A party does not need to implement every module -- only those relevant to its role and business needs. ### Locations Module The Locations module is the foundation of OCPI. It describes where chargers are, what capabilities they have, and whether they are currently available. A Location object contains one or more EVSEs (Electric Vehicle Supply Equipment), each with one or more Connectors. **Data hierarchy**: Location > EVSE > Connector **Key fields**: address, coordinates, operator info, opening hours, EVSE status (`AVAILABLE`, `BLOCKED`, `CHARGING`, `INOPERATIVE`, `OUTOFORDER`, `PLANNED`, `REMOVED`, `RESERVED`, `UNKNOWN`), connector type (Type 2, CCS2, CHAdeMO), power output, and pricing. **Example use case**: An eMSP pulls all locations from a CPO to populate its driver-facing app with a map of available chargers. When an EVSE status changes from AVAILABLE to CHARGING, the CPO pushes the update so the app reflects real-time availability. ### Sessions Module The Sessions module provides real-time data about active charging sessions. While a session is in progress, both parties can track energy delivered, current power, cost accrued, and session state. **Key fields**: session ID, start timestamp, kWh delivered, [CDR](/blog/what-is-CPMS) token (identifying the driver), status (ACTIVE, COMPLETED, INVALID, PENDING), and total cost. **Example use case**: An eMSP displays a live charging dashboard in its app showing the driver how much energy has been delivered, current charging speed, and estimated cost so far. ### CDRs Module (Charge Detail Records) CDRs are the billing backbone of OCPI. A CDR is generated after a session completes and contains all information needed for invoicing and settlement between the CPO and eMSP. **Key fields**: start/stop timestamps, total energy (kWh), total time, total parking time, total cost, tariff applied, charging periods (time-based breakdown of the session), and the authorization token used. **Example use case**: After a driver finishes charging, the CPO generates a CDR and pushes it to the eMSP. The eMSP uses this CDR to invoice the driver and reconcile payments with the CPO at the end of the billing cycle. ### Tariffs Module The Tariffs module defines pricing structures that CPOs apply to their charge points. OCPI tariffs support complex pricing models including time-of-use rates, energy-based pricing, flat fees, parking fees, and combinations thereof. **Key fields**: tariff ID, currency, tariff elements (each containing price components and restrictions like time-of-day, min/max kWh, day of week), and tariff type (`AD_HOC_PAYMENT`, `PROFILE_CHEAP`, `PROFILE_FAST`, `PROFILE_GREEN`, `REGULAR` — added in 2.2.1; not present in 2.1.1). **Example use case**: A CPO publishes a tariff that charges 0.35 EUR/kWh during peak hours (08:00-20:00) and 0.25 EUR/kWh during off-peak hours, plus a 0.05 EUR/min idle fee after the session completes. The eMSP displays this pricing to the driver before they start charging. ### Tokens Module The Tokens module handles driver authorization. An eMSP pushes its driver tokens (RFID UIDs, app-based virtual tokens, or vehicle-based tokens) to the CPO so the CPO can authorize charging sessions locally without a real-time callback. **Key fields**: token UID, token type (`RFID`, `OTHER` in 2.1.1; `RFID`, `APP_USER`, `AD_HOC_USER`, `OTHER` in 2.2.1), contract ID, issuer, valid flag, and whitelist type (`ALWAYS`, `ALLOWED`, `ALLOWED_OFFLINE`, `NEVER`). **Example use case**: An eMSP pushes all its active driver tokens to a CPO. When a driver taps their RFID card at the CPO's charger, the CPO can authorize the session instantly by checking its local token cache, even if the network connection to the eMSP is temporarily unavailable. ### Commands Module The Commands module enables remote control of charging sessions. An eMSP can send commands to a CPO to start or stop a session, reserve a charger, or unlock a connector on behalf of a driver. **Supported commands**: - `START_SESSION`: Remotely start a charging session at a specific EVSE - `STOP_SESSION`: Remotely stop an active session - `RESERVE_NOW`: Reserve an EVSE for a specific driver for a limited time - `UNLOCK_CONNECTOR`: Remotely unlock a connector (useful if the cable is stuck) **Example use case**: A driver opens their eMSP app, selects a charger on the map, and taps "Start Charging." The eMSP sends a `START_SESSION` command to the CPO via OCPI, and the CPO relays it to the charger via [OCPP](/blog/what-is-ocpp). ### ChargingProfiles Module Added in OCPI 2.2, the ChargingProfiles module allows an eMSP to set power limits or charging schedules on behalf of the driver. This is essential for smart charging and demand response scenarios. **Key fields**: charging profile (containing schedule periods with power limits), response URL (for async result notification). **Example use case**: A driver tells their eMSP app they need 80% charge by 7 AM and want the cheapest rate. The eMSP calculates an optimal charging schedule and sends a ChargingProfile to the CPO, which applies it to the charger via [OCPP charging profiles](/blog/ocpp-1-6-vs-2-0-1). The charger modulates power delivery according to the schedule. ### HubClientInfo Module The HubClientInfo module is specific to hub-based deployments. It allows a roaming hub (like [GIREVE](/blog/gireve-hub-integration)) to inform connected parties about all other parties connected to the hub, including their roles and connection status. **Key fields**: party ID, country code, role (CPO, eMSP, HUB), status (CONNECTED, OFFLINE, PLANNED, SUSPENDED). **Example use case**: An eMSP connected to GIREVE receives HubClientInfo updates listing all CPOs currently connected to the hub. The eMSP uses this to know which CPO networks are available for its drivers and can display coverage accordingly. ## OCPI 2.1.1 vs 2.2.1: What Changed? OCPI has gone through several iterations. The two versions you will encounter in production today are 2.1.1 and 2.2.1. Understanding the differences is critical for implementation planning. ### OCPI 2.1.1 Released in 2019, OCPI 2.1.1 is the most widely deployed version. It covers all core roaming functionality and remains the baseline requirement for most roaming hub connections. If you are building your first OCPI integration, you will almost certainly start here. ### OCPI 2.2.1 Released in 2021, OCPI 2.2.1 is a significant upgrade that adds hub support, smart charging, and improved tariff handling. Adoption is growing rapidly as roaming hubs and larger operators migrate. ### Detailed Version Comparison | Feature | OCPI 2.1.1 | OCPI 2.2.1 | |---------|-----------|-----------| | **Core modules** (Locations, Sessions, CDRs, Tariffs, Tokens, Commands) | Yes | Yes | | **Hub role support** | No -- peer-to-peer only | Yes -- native hub/platform role | | **HubClientInfo module** | Not available | Full support | | **ChargingProfiles module** | Not available | Full support for smart charging | | **Tariff types** | Basic tariff model (no `type` field) | Extended with `tariff_type` enum (`AD_HOC_PAYMENT`, `PROFILE_CHEAP`, `PROFILE_FAST`, `PROFILE_GREEN`, `REGULAR`) | | **Tariff alt_text / alt_url** | Not available | Human-readable tariff descriptions and external links | | **Token types** | RFID, OTHER | RFID, APP_USER, AD_HOC_USER, OTHER | | **Authorization reference** | Basic | Enhanced with authorization_reference for linking tokens to sessions | | **Async commands** | Async via `response_url` callback (same pattern as 2.2.1) | Async via `response_url` callback | | **Connector-level pricing** | Limited | Full connector-level tariff assignment | | **Energy mix info** | Basic | Detailed energy source breakdown per location | | **Calibration law support** | `signed_data` field on CDR for signed metering | `signed_data` field on CDR; richer signed-data context fields added | | **Error handling** | Standardized OCPI status codes (1xxx success, 2xxx client, 3xxx server) | Same plus 4xxx Hub error class | | **Pagination** | Supported | Enhanced with X-Total-Count and X-Limit headers | **Recommendation**: Implement OCPI 2.2.1 if you are connecting through a roaming hub, need smart charging capabilities, or operate in Germany (Eichrecht compliance). Start with 2.1.1 if you need the fastest path to production for basic roaming. ## OCPI vs OCPP: What Is the Difference? This is the most common question in EV charging protocol discussions. The short answer: [OCPP (Open Charge Point Protocol)](/blog/what-is-ocpp) manages communication between a charger and its [backend system (CPMS)](/blog/what-is-CPMS). OCPI manages communication between backend systems of different charging networks. They operate at different layers of the stack and are complementary, not competing. | Dimension | OCPP | OCPI | |-----------|------|------| | **Full name** | Open Charge Point Protocol | Open Charge Point Interface | | **Purpose** | Charger-to-backend communication | Backend-to-backend roaming | | **Parties involved** | Charge Point and [CPMS](/blog/what-is-CPMS) | CPO backend and eMSP backend | | **Transport protocol** | WebSocket (persistent connection) | REST API over HTTPS (stateless) | | **Data format** | JSON (OCPP 1.6) or SOAP (OCPP 1.6S) | JSON | | **Connection type** | Persistent, bidirectional | Request/response, stateless | | **Scope** | Single-network charger management | Cross-network interoperability | | **Maintained by** | Open Charge Alliance (OCA) | EVRoaming Foundation | | **Current versions** | [1.6, 2.0.1](/blog/ocpp-1-6-vs-2-0-1) | 2.1.1, 2.2.1 | | **Typical data exchanged** | Boot notifications, heartbeats, meter values, firmware updates | Locations, sessions, CDRs, tariffs, tokens | | **Example message** | "Start transaction on connector 1" | "Driver X from eMSP Y is authorized to charge on your network" | | **Security** | TLS + basic auth or certificate-based | TLS + TOKEN-based authentication via credential handshake | **How they work together**: When a roaming driver starts a session, the eMSP sends an OCPI command to the CPO's backend. The CPO's backend then sends an OCPP RemoteStartTransaction message to the physical charger. Session data flows back up through OCPP (MeterValues, StopTransaction) and is then shared with the eMSP via OCPI (Sessions, CDRs). ## OCPI vs OICP vs OCHP: EV Charging Roaming Protocols Compared OCPI is not the only roaming protocol in the EV charging industry. Two other protocols serve similar purposes: OICP (Open InterCharge Protocol) and OCHP (Open Clearing House Protocol). Understanding the differences helps when choosing which ecosystem to join. | Dimension | OCPI | OICP | OCHP | |-----------|------|------|------| | **Maintained by** | EVRoaming Foundation | Hubject | e-clearing.net (Smartlab) | | **Governance** | Open community | Proprietary (single vendor) | Open community | | **License** | Creative Commons | Proprietary | Creative Commons | | **Primary hub** | GIREVE, multiple hubs | Hubject (intercharge) | e-clearing.net | | **Geographic focus** | Europe-wide, expanding globally | Europe, strong in DACH region | Central Europe | | **Transport** | REST API (JSON) | REST API (JSON) | SOAP/XML (legacy) and REST | | **Peer-to-peer support** | Yes -- native | Limited -- hub-centric | Limited -- hub-centric | | **Smart charging** | Yes (2.2.1) | Yes | Limited | | **Plug&Charge (ISO 15118)** | Partial support | Full support via Hubject PKI | Not supported | | **Adoption** | Broad, multi-vendor | Large Hubject-centric base | Niche, Central Europe | | **Open specification** | Freely available on GitHub | Available under NDA | Freely available | **OCPI** has the broadest adoption and the most open governance model. It is the default choice for most new implementations. **OICP** is tightly coupled with Hubject and offers mature Plug&Charge support through Hubject's PKI infrastructure, making it strong in the German-speaking market. **OCHP** is the oldest of the three and is most common among e-clearing.net members, but has seen less adoption growth in recent years. Many large operators implement multiple protocols. A CPO connected to both GIREVE (via OCPI) and Hubject (via OICP) maximizes its roaming reach. ## Roaming Hubs: GIREVE, Hubject, and e-clearing Rather than establishing direct OCPI connections with every partner (which does not scale), most CPOs and eMSPs connect through a roaming hub. A single hub connection gives access to all other parties connected to that hub. ### GIREVE [GIREVE](/blog/gireve-hub-integration) is the largest OCPI-based roaming hub in Europe. Founded in France in 2013, it has grown into the dominant roaming platform on the continent. - **Coverage**: As of February 2026, roughly 695,000 charge points across dozens of European countries ([GIREVE *Roaming in Europe* barometer](https://www.gireve.com/roaming-in-europe-february-2026/)) - **Partners**: Several hundred connected CPOs and eMSPs - **Protocol support**: OCPI 2.1.1 and 2.2.1 (primary), plus eMIP (GIREVE's legacy protocol) - **Key features**: Quality scoring of charge points, B2B marketplace for roaming agreements, data analytics - **Certification**: GIREVE runs a certification process for new OCPI connections, including test scenarios that validate your implementation ### Hubject Hubject operates the intercharge network, the largest global roaming platform by geographic reach. - **Coverage**: As of 2026, over 1,000,000 charge points across 70+ countries on four continents ([Hubject](https://www.hubject.com/)) - **Protocol support**: OICP (primary), OCPI 2.2.1 (growing) - **Key features**: Plug&Charge PKI infrastructure (ISO 15118), eRoaming marketplace, global interoperability - **Market position**: Strongest in Germany, Austria, and Switzerland; expanding aggressively in North America and Asia-Pacific ### e-clearing.net e-clearing.net is a pan-European clearing house originally developed by Smartlab (now part of the Recharge group). - **Coverage**: Primarily Central Europe (Germany, Netherlands, Belgium, Austria) - **Protocol support**: OCHP (primary), OCPI (supported) - **Key features**: Clearing and settlement services, contract management, direct roaming facilitation - **Market position**: Smaller than GIREVE and Hubject but well-established among Central European utilities ## How Do CPOs Use OCPI? A [Charge Point Operator (CPO)](/blog/cpo-vs-emsp-explained) uses OCPI to expose its charging infrastructure to external networks. Here is what a CPO typically implements: **Data provider role** (CPO pushes data to eMSPs): - **Locations**: Publish all charge point locations, EVSE statuses, connector types, and real-time availability - **Sessions**: Share active session data so eMSPs can display live charging information to their drivers - **CDRs**: Generate and push Charge Detail Records after each roaming session for billing and settlement - **Tariffs**: Publish pricing structures so eMSPs can display accurate costs to drivers before they start charging **Data receiver role** (CPO receives data from eMSPs): - **Tokens**: Receive and cache driver authorization tokens for local, offline-capable authorization - **Commands**: Accept remote start/stop, reservation, and unlock commands from eMSP apps **Business impact**: A mid-sized CPO that connects to GIREVE via OCPI can immediately access hundreds of thousands of eMSP subscribers without any direct sales or marketing effort. For public charging operators, roaming sessions can account for a meaningful and growing share of total revenue. ## How Do eMSPs Use OCPI? An [eMSP (e-Mobility Service Provider)](/blog/cpo-vs-emsp-explained) uses OCPI to aggregate charging infrastructure from multiple CPOs and present it to its subscribers. Here is what an eMSP typically implements: **Data receiver role** (eMSP pulls/receives data from CPOs): - **Locations**: Aggregate charge point data from all connected CPOs to build a comprehensive charging map - **Sessions**: Receive real-time session updates to display in the driver app - **CDRs**: Receive billing records to invoice drivers and reconcile with CPOs - **Tariffs**: Receive pricing data to display accurate cost estimates **Data provider role** (eMSP pushes data to CPOs): - **Tokens**: Push driver authorization tokens to all connected CPOs for local authorization - **Commands**: Send remote start/stop and reservation commands on behalf of drivers - **ChargingProfiles**: Send smart charging schedules (OCPI 2.2.1) based on driver preferences **Business impact**: An eMSP connected to one roaming hub can offer its drivers access to hundreds of thousands of charge points across multiple countries without deploying any hardware. The entire value proposition -- "charge anywhere with one app" -- depends on OCPI working reliably. ## How Do You Implement OCPI? A Step-by-Step Guide Implementing OCPI requires building a REST API server and client that conforms to the OCPI specification. Here is a high-level roadmap: ### Step 1: Define Your Role and Scope Determine whether you are implementing as a CPO, eMSP, or both. This determines which modules you need and whether you are primarily a data sender or receiver. ### Step 2: Choose Your OCPI Version For most new implementations, start with OCPI 2.2.1. If your target roaming hub only requires 2.1.1, start there. Support both versions if possible -- OCPI's version discovery mechanism makes this straightforward. ### Step 3: Implement Core Endpoints Build the required endpoints in order of dependency: 1. **Versions and Credentials**: These are mandatory. Without them, no connection can be established. 2. **Locations** (if CPO): This is the most data-intensive module and typically requires the most development effort. 3. **Tokens** (if eMSP): Push your driver tokens to enable authorization. 4. **Sessions and CDRs**: These handle the billing workflow and are required for any commercial roaming. 5. **Tariffs**: Needed for price transparency. 6. **Commands**: Needed for remote start/stop from eMSP apps. ### Step 4: Implement Push and Pull Synchronization Build both pull endpoints (for initial sync and periodic reconciliation) and push endpoints (for real-time updates). Implement proper pagination handling with `offset`, `limit`, and `date_from` parameters. ### Step 5: Connect to a Roaming Hub Contact your target hub ([GIREVE](/blog/gireve-hub-integration), Hubject, or e-clearing) and begin their onboarding process. Each hub has a staging environment for testing. ### Step 6: Test End-to-End Validate the full workflow: credential handshake, location sync, token exchange, remote start, session tracking, CDR generation, and settlement. This is where most implementations encounter issues with edge cases -- malformed data, timeout handling, concurrent updates, and tariff calculation discrepancies. ## How Do You Test OCPI Implementations? Testing OCPI is challenging because it requires simulating both sides of the protocol. You need to act as both a CPO and an eMSP, generate realistic data, and validate complex interactions across multiple modules. Common testing challenges include: - Simulating the credential handshake and token rotation - Generating realistic location data with proper EVSE/Connector hierarchies - Testing push and pull synchronization, including conflict resolution - Validating CDR calculations against published tariffs - Simulating hub-based routing (for OCPI 2.2.1) - Testing error handling and edge cases (network timeouts, invalid tokens, concurrent session updates) **OCPPLab** provides OCPI testing tools alongside its [OCPP emulator](/blog/what-is-ocpp), letting you validate both protocols in a single environment. You can simulate CPO and eMSP endpoints, generate realistic sessions and CDRs, test tariff calculations, validate [GIREVE-compatible](/blog/gireve-hub-integration) hub integration, and run full end-to-end roaming scenarios without needing a live roaming partner. ## Frequently Asked Questions About OCPI ### What does OCPI stand for? OCPI stands for Open Charge Point Interface. It is an open protocol maintained by the EVRoaming Foundation that standardizes data exchange between EV charging networks to enable roaming. The name is often confused with [OCPP (Open Charge Point Protocol)](/blog/what-is-ocpp), but they serve different purposes: OCPI handles network-to-network roaming, while OCPP handles charger-to-backend communication. ### Is OCPI mandatory in Europe? OCPI is not legally mandated by any European regulation. However, the EU Alternative Fuels Infrastructure Regulation (AFIR), which took effect in April 2024, requires that all public charging stations offer ad-hoc (contract-free) access and interoperable payment. While AFIR does not specify a protocol, meeting its interoperability requirements in practice requires roaming capability, and OCPI is the dominant protocol for achieving this. ### Can I use OCPP without OCPI? Yes. [OCPP](/blog/what-is-ocpp) manages communication between your chargers and your [CPMS (Charging Station Management System)](/blog/what-is-CPMS). You only need OCPI if you want to enable roaming -- allowing drivers from other networks to use your chargers, or allowing your drivers to use chargers on other networks. Many small CPOs operate OCPP-managed networks for years before adding OCPI when they are ready to join a roaming ecosystem. ### What is the difference between OCPI and OICP? OCPI is an open community protocol governed by the EVRoaming Foundation, with its specification freely available on GitHub. OICP (Open InterCharge Protocol) is developed and controlled by Hubject, with its specification available under NDA. Both protocols enable roaming between charging networks. OCPI has broader industry adoption and supports peer-to-peer connections, while OICP is tightly integrated with Hubject's intercharge network and offers more mature Plug&Charge (ISO 15118) support. ### How long does it take to implement OCPI? Implementation timelines vary significantly based on scope and team experience. A minimum viable OCPI implementation (Credentials, Locations, Tokens, and CDRs) typically takes 2-4 months for a development team new to the protocol. Adding all modules, comprehensive error handling, and hub certification extends this to 4-8 months. The credential handshake and CDR reconciliation logic tend to be the most time-consuming aspects. ### What programming languages can I use for OCPI? OCPI is a REST API specification, so it can be implemented in any language that supports HTTP servers and clients. Common choices in the industry include Python, Java, Go, C#, and Node.js. There are several open-source OCPI libraries on GitHub, though most production implementations are custom-built to handle the specific business logic of tariff calculation, CDR validation, and hub integration. ### Does OCPI support Plug&Charge? OCPI 2.2.1 includes partial support for Plug&Charge through the Tokens module (using the AD_HOC_USER token type and authorization_reference field). However, the full Plug&Charge workflow (ISO 15118 certificate management, contract certificate provisioning) is not part of the OCPI specification. Hubject's OICP protocol currently offers more complete Plug&Charge support through its integrated PKI infrastructure. The EVRoaming Foundation is actively working on enhanced Plug&Charge support for future OCPI versions. ### How does OCPI handle pricing and billing? OCPI handles pricing through two modules: Tariffs (published pricing structures) and CDRs (actual billing records). A CPO publishes its tariffs via the Tariffs module, which the eMSP uses to display estimated costs to drivers. After a session completes, the CPO generates a CDR containing the actual cost calculated against the applicable tariff. The eMSP then invoices the driver based on the CDR. Settlement between CPO and eMSP typically happens monthly through the roaming hub or via direct bilateral agreements. ### Is OCPI used outside of Europe? OCPI adoption originated in Europe but is expanding globally. GIREVE has partners in North Africa, the Middle East, and parts of Asia. Hubject (which supports both OICP and OCPI) reports operating across 70+ countries on four continents. In North America, OCPI adoption is growing as operators seek interoperability, though the market has historically relied more on proprietary integrations. Australia, South Korea, and India are emerging OCPI markets as their public charging networks mature. ### What is the latest version of OCPI? As of 2025, the latest stable version is OCPI 2.2.1, released in 2021. OCPI 3.0 is under development by the EVRoaming Foundation, with expected improvements including better support for Plug&Charge, enhanced smart charging profiles, improved hub functionality, and alignment with ISO 15118-20. Most production deployments today run either 2.1.1 or 2.2.1, with an increasing share migrating to 2.2.1. --- ## OCPP 1.6 vs 2.0.1: Differences, Features & Migration Guide Source: https://ocpplab.com/blog/ocpp-1-6-vs-2-0-1 Compare OCPP 1.6 and 2.0.1 across security, smart charging, the device model, transactions, and ISO 15118 — plus a 5-step migration guide for CPMS teams. **Quick answer:** OCPP 2.0.1 is a major redesign of OCPP 1.6, not a backwards-compatible upgrade. The biggest differences: 2.0.1 has **mandatory security profiles** (1.6 makes them optional via the Security Whitepaper edition 2), a structured **device model** instead of flat config keys, a unified **`TransactionEvent`** instead of separate `StartTransaction`/`StopTransaction`, native **ISO 15118 Plug & Charge** support, and **renamed remote commands** (`RequestStartTransaction` instead of `RemoteStartTransaction`). OCPP 1.6 is still the most widely deployed version; OCPP 2.0.1 is the standard for new high-security and smart-charging deployments. **OCPP 1.6 and OCPP 2.0.1** are the two active versions of the Open Charge Point Protocol, both published by the [Open Charge Alliance (OCA)](https://openchargealliance.org/protocols/open-charge-point-protocol/). OCPP 1.6 is deployed on the vast majority of charge points worldwide (estimated 80%+ of installed base as of 2025), while OCPP 2.0.1 is the standard for new deployments requiring advanced security, [ISO 15118](https://www.iso.org/standard/55366.html) Plug & Charge, and grid-integrated smart charging. Most production [CPMS platforms](/blog/what-is-CPMS) need to support both versions simultaneously, since operators typically manage mixed fleets of legacy and modern charge points. If you need version-specific validation guidance, start with [OCPP 1.6 testing](/protocols/ocpp-1-6) and [OCPP 2.0.1 testing](/protocols/ocpp-2-0-1). By the numbers — per the [Open Charge Alliance](https://www.openchargealliance.org/) and the official compliance test packs: - **OCPP 1.6 core defines 28 unique actions** across 10 charger-initiated + 19 CPMS-initiated messages (with `DataTransfer` going in both directions). The **OCPP 1.6 Security Whitepaper edition 2** extension adds 11 more, bringing the total to ~39. - **OCPP 1.6 ships with 178 official OCTT (compliance) test cases** (102 Charge Point, 76 Central System). - **OCPP 2.0.1 Edition 2 defines 64 operations** across **16 functional blocks** (A–P), of which 12 blocks (A, B, C, E, F, G, J, K, L, M, N, P) have **365 official Part 6 test cases** (230 Charging Station + 135 CPMS). - OCPP 1.6 schemas are **JSON Schema draft-04**; OCPP 2.0.1 schemas are **JSON Schema draft-06**. ## Quick Comparison: OCPP 1.6 vs 2.0.1 | Feature | OCPP 1.6 | OCPP 2.0.1 | |---------|-----------|------------| | **Release Year** | 2015 | 2020 | | **Transport** | WebSocket + SOAP | WebSocket only | | **Message Format** | JSON or SOAP/XML | JSON only | | **Security** | Optional TLS in core; Profiles 0–3 via Security Whitepaper edition 2 (opt-in extension) | Mandatory security profiles (1, 2, 3) | | **ISO 15118** | Not natively supported | Full Plug & Charge support | | **Smart Charging** | Basic charge profiles | Composite schedules with priorities | | **Device Model** | Limited configuration keys (~50) | Comprehensive variable system (500+) | | **Firmware Updates** | Basic via `UpdateFirmware`; `SignedUpdateFirmware` available via Security Whitepaper edition 2 | Signed firmware, secure boot | | **Transaction Handling** | Start/Stop based | Event-driven with automatic recovery | | **Display Messages** | Not available | Remote display control | | **Cost Information** | Not available | Real-time pricing updates | | **Reservations** | Basic connector reservation | EVSE-based reservations | | **Certificate Management** | Not in core; `InstallCertificate`, `SignCertificate`, `CertificateSigned`, `DeleteCertificate`, `GetInstalledCertificateIds` available via Security Whitepaper edition 2 | Full PKI certificate lifecycle | | **Message Count** | ~30 message types | ~50+ message types | | **Adoption** | Dominant on the installed base | Standard for new high-security deployments | ## Why Is Security the Biggest Difference? Security is the single most significant improvement in OCPP 2.0.1. In OCPP 1.6, TLS encryption is optional — many production deployments run unencrypted [WebSocket connections](/blog/ocpp-websocket-guide), relying solely on network-level security. ### OCPP 1.6 Security In core OCPP 1.6: - TLS is optional and often not implemented - No standardized authentication mechanism - No certificate management - No signed firmware updates - Vulnerable to man-in-the-middle attacks on unencrypted connections The **OCPP 1.6 Security Whitepaper edition 2** is an optional extension that retroactively adds the same security model later made mandatory in OCPP 2.0.1: four security profiles (0/1/2/3, with different numbering than 2.0.1), certificate management messages (`InstallCertificate`, `SignCertificate`, `CertificateSigned`, `DeleteCertificate`, `GetInstalledCertificateIds`), signed firmware updates (`SignedUpdateFirmware`, `SignedFirmwareStatusNotification`), and security event reporting (`SecurityEventNotification`). The catch is that whitepaper support is opt-in per deployment, so much of the installed 1.6 base still runs without it. ### OCPP 2.0.1 Security Profiles OCPP 2.0.1 defines three mandatory security profiles (numbered differently from the 1.6 Security Whitepaper edition 2 — 2.0.1 starts at Profile 1, while 1.6 starts at Profile 0): | Profile | Authentication | Encryption | Use Case | |---------|---------------|------------|----------| | **Profile 1** | HTTP Basic Auth | None (ws://) | Trusted private networks only | | **Profile 2** | HTTP Basic Auth | TLS with server certificate (wss://) | Standard production deployments | | **Profile 3** | Mutual TLS (client + server certificates) | Full mTLS (wss://) | High-security enterprise deployments | Profile 3 provides the strongest security: the charger and CPMS authenticate each other with X.509 certificates, preventing unauthorized devices from connecting. OCPP 2.0.1 also adds: - **Signed firmware updates**: Cryptographic verification prevents malicious firmware - **Secure boot**: Ensures only authorized firmware runs on the charge point - **Certificate lifecycle management**: Install, update, and revoke certificates remotely ## How Does Smart Charging Compare? [Smart charging](/blog/smart-charging-explained) capabilities differ substantially between versions. ### OCPP 1.6 Smart Charging OCPP 1.6 supports `SetChargingProfile` with basic schedule periods. Each profile contains a stack level and a sequence of time-based power limits. **Limitations:** - Profiles apply per connector only - No station-wide power distribution - No external constraint handling (grid operator limits) - No composite schedule calculation on the charger - Basic priority system (stack levels 0-99) ### OCPP 2.0.1 Smart Charging OCPP 2.0.1 introduces composite schedules and a hierarchical profile system: - **Charging Station profiles**: Apply power limits to the entire station - **EVSE profiles**: Apply limits per EVSE (charging point) - **Transaction profiles**: Apply limits per active session - **External constraints**: Grid operator limits override local profiles - **Composite schedules**: Charger calculates the effective schedule from all active profiles - **Cost-based optimization**: Charge when electricity is cheapest | Capability | OCPP 1.6 | OCPP 2.0.1 | |-----------|----------|------------| | Per-connector limits | Yes | Yes | | Per-station limits | No | Yes | | Grid operator constraints | No | Yes | | Composite schedule calculation | No (CPMS-side only) | Yes (charger-side) | | Cost-based charging | No | Yes | | Discharge (V2G) | No | Yes (with ISO 15118) | ## How Do the Versions Handle ISO 15118 and Plug & Charge? [ISO 15118](/blog/iso-15118-plug-and-charge) is the standard for high-level communication between EVs and chargers, enabling Plug & Charge — where the vehicle authenticates automatically when plugged in, with no RFID card or app needed. **OCPP 1.6** has no native ISO 15118 support. Some implementations use the `DataTransfer` message as a workaround, but this is non-standard and inconsistent across vendors. **OCPP 2.0.1** provides full ISO 15118 integration: - Certificate-based vehicle authentication - Contract certificate installation and updates - Signed metering data for billing accuracy - Vehicle-to-Grid (V2G) communication support If your roadmap includes Plug & Charge, OCPP 2.0.1 is required. ## How Does Transaction Handling Differ? ### OCPP 1.6 Transactions follow a simple Start/Stop model: 1. `StartTransaction.req` → CPMS assigns a transaction ID 2. `MeterValues` sent periodically during charging 3. `StopTransaction.req` → Transaction ends **Problem**: If the charger loses connectivity between Start and Stop, the transaction can become orphaned. Recovery requires manual intervention or custom workarounds. ### OCPP 2.0.1 Transactions use an event-driven model: 1. `TransactionEvent(Started)` → New transaction 2. `TransactionEvent(Updated)` → Meter values, status changes 3. `TransactionEvent(Ended)` → Transaction complete **Key improvement**: Each event is independently transmitted and can be queued offline. When connectivity is restored, events are sent in order. The CPMS can reconstruct the complete transaction from the event stream, eliminating orphaned transactions. | Aspect | OCPP 1.6 | OCPP 2.0.1 | |--------|----------|------------| | Model | Start/Stop | Event-driven | | Offline handling | Transaction may be lost | Events queued and replayed | | Meter values | Separate MeterValues message | Embedded in TransactionEvent | | ID assignment | CPMS assigns ID (integer) | Charging Station assigns ID (string, 1–36 chars; UUID is common but not required) | ## How Does Device Management Differ? ### OCPP 1.6 Device configuration uses key-value pairs via `GetConfiguration` and `ChangeConfiguration`. There are approximately 50 standardized configuration keys, with vendors often adding proprietary extensions. ### OCPP 2.0.1 The comprehensive **Device Model** replaces configuration keys with a structured variable system: - **Components**: Logical parts of the charger (Connector, EVSE, Controller) - **Variables**: Attributes of each component (CurrentLimit, Temperature, FirmwareVersion) - **Characteristics**: Metadata about each variable (read-only, writable, data type, unit) This provides 500+ standardized variables covering every aspect of charger configuration, monitoring, and diagnostics. The device model makes it possible to manage any charger without vendor-specific documentation. ## Message Types Comparison ### Messages Only in OCPP 2.0.1 | Message | Purpose | |---------|---------| | `SetDisplayMessage` | Control charger screen content | | `CostUpdated` | Real-time pricing display | | `Get15118EVCertificate` | ISO 15118 certificate management | | `GetInstalledCertificateIds` | PKI certificate inventory | | `InstallCertificate` | Install new certificates | | `DeleteCertificate` | Remove certificates | | `NotifyReport` | Comprehensive device status reporting | | `SetVariables` / `GetVariables` | Device model management | | `SetNetworkProfile` | Network configuration | | `PublishFirmwareStatusNotification` | Firmware distribution status | | `ReportChargingProfiles` | Smart charging profile reporting | | `ClearedChargingLimit` | External constraint acknowledgment | ### Messages in Both Versions (with improvements in 2.0.1) | Message | 1.6 Behavior | 2.0.1 Improvement | |---------|-------------|-------------------| | `BootNotification` | Basic charger registration | Includes reason (PowerUp, Watchdog, etc.) | | `StatusNotification` | Per-connector status | Per-EVSE + per-connector status | | `FirmwareUpdate` | HTTP download | Signed firmware with integrity check | | `RemoteStartTransaction` | Start by ID tag | Start with charging profile + EVSE selection | ## When Should You Use Which Version? ### Choose OCPP 1.6 if: - You need maximum compatibility with existing chargers - Your network consists primarily of AC Level 2 chargers - ISO 15118 Plug & Charge is not on your roadmap - You need to ship a working product quickly on a budget ### Choose OCPP 2.0.1 if: - Security is a top priority (regulatory or enterprise requirements) - You need ISO 15118 Plug & Charge support - You're building a new platform from scratch - You need advanced smart charging for grid integration - You're deploying DC fast chargers with complex billing - You want future-proof architecture ### Best Practice: Support Both Most modern CPMS platforms support OCPP 1.6 and 2.0.1 simultaneously. A typical production network has: - Legacy AC chargers on OCPP 1.6 - New DC fast chargers on OCPP 2.0.1 - The CPMS handles protocol translation internally ## Migration Guide: OCPP 1.6 to 2.0.1 ### Step 1: Assess Your Current Implementation Audit your OCPP 1.6 message handlers. Map each handler to its 2.0.1 equivalent: - `StartTransaction` / `StopTransaction` → `TransactionEvent` - `GetConfiguration` / `ChangeConfiguration` → `GetVariables` / `SetVariables` - `MeterValues` → Embedded in `TransactionEvent(Updated)` ### Step 2: Implement the Device Model The device model is the biggest architectural change. You'll need: - A database schema for Components, Variables, and their Characteristics - Handlers for `GetBaseReport`, `NotifyReport`, `GetVariables`, `SetVariables` - A mapping layer from your existing configuration to the device model ### Step 3: Migrate Transaction Handling Replace Start/Stop transaction logic with the event-driven model: - Handle `TransactionEvent` with Started, Updated, and Ended types - Implement event sequencing and offline event replay - Update your billing system to work with event streams ### Step 4: Add Security Profiles Implement at least Security Profile 2 (TLS with server certificate): - Configure your WebSocket server for TLS - Implement HTTP Basic Auth over TLS - Set up certificate management for Profile 3 ### Step 5: Test Thoroughly Testing the migration is critical. You need to validate: - Both protocol versions running simultaneously - Backward compatibility with existing 1.6 chargers - All new 2.0.1 message flows - Security profile negotiation - Smart charging composite schedules [OCPPLab](/blog/ocpp-testing-guide) lets you run OCPP 1.6 and 2.0.1 virtual chargers side by side, test migration scenarios, and validate all [error handling paths](/blog/ocpp-error-codes-reference) without physical hardware. ## How Do You Test Both OCPP Versions? Validating an OCPP implementation across both versions requires hundreds of test cases covering message flows, error scenarios, edge cases, and version-specific features. Physical charger testing is impractical at this scale. **OCPPLab** provides: - Side-by-side OCPP 1.6 and 2.0.1 virtual chargers - 100+ pre-built device model profiles from real charger vendors - Automated test suites covering all message types in both versions - Security profile testing (Profile 1, 2, and 3) - Smart charging composite schedule validation - Load testing with 10,000+ concurrent connections across both versions [Start your free simulation](/dashboard) and test both OCPP versions in minutes. ## Frequently Asked Questions ### Can a CPMS support both OCPP 1.6 and 2.0.1 simultaneously? Yes, and most production CPMS platforms do. The CPMS detects the protocol version during the WebSocket handshake (via the `Sec-WebSocket-Protocol` header) and routes messages to the appropriate handler. This is essential since real-world networks have mixed fleets. ### Is OCPP 2.0.1 backward compatible with 1.6? No. OCPP 2.0.1 is a major protocol revision with different message structures, a new device model, and event-driven transactions. A charger running 1.6 cannot communicate with a CPMS that only supports 2.0.1, and vice versa. The CPMS must implement both versions independently. ### Which OCPP version do new chargers support? Many new commercial chargers support both OCPP 1.6 and 2.0.1. They commonly ship with 1.6 as the default and offer 2.0.1 via firmware update. DC fast charger manufacturers (ABB, Tritium, Kempower) generally have stronger 2.0.1 support than AC charger manufacturers. ### When will OCPP 1.6 be deprecated? The Open Charge Alliance has not announced a deprecation date for OCPP 1.6. Given the massive installed base, 1.6 will remain relevant for many years. However, new deployments are increasingly moving to 2.0.1, and OCA's focus is on the 2.x line. ### What is OCPP 2.1? OCPP 2.1 is the next minor version after 2.0.1, adding features for ISO 15118-20 (bidirectional charging / V2G), improved smart charging, and better tariff handling. It maintains backward compatibility with 2.0.1 chargers for core functionality. ### How many message types does each version have? OCPP 1.6 defines approximately 30 message types. OCPP 2.0.1 defines over 50 message types, with the additions primarily covering the device model, certificate management, ISO 15118, and display messages. ### Is OCPP 2.0.1 harder to implement than 1.6? Yes. OCPP 2.0.1 has a larger specification, more message types, mandatory security requirements, and the complex device model. A typical 2.0.1 implementation takes considerably longer than 1.6. However, the result is significantly more robust and future-proof. ### What is the difference between OCPP and OCPI? [OCPP](/blog/what-is-ocpp) manages communication between a charger and its management system (CPMS). [OCPI](/blog/what-is-ocpi) manages roaming between different charging networks, allowing drivers to use any network with a single account. They serve different purposes and are typically both needed in a production charging network. --- ## OCPI 2.1.1 vs 2.2.1: Differences, Features & Upgrade Guide Source: https://ocpplab.com/blog/ocpi-2-1-1-vs-2-2-1 Compare OCPI 2.1.1 and OCPI 2.2.1 across roaming modules, hub support, ChargingProfiles, HubClientInfo, tariffs, and upgrade decisions for EV charging teams. **Quick answer:** OCPI 2.2.1 is a superset of OCPI 2.1.1 with three structural changes that matter most. **(1) Roles:** 2.2.1 adds Hub, NSP, NAP, and SCSP on top of 2.1.1's CPO/EMSP/OTHER. **(2) Modules:** 2.2.1 adds **ChargingProfiles** (smart charging through the roaming chain) and **HubClientInfo** (hub-aware participant discovery). **(3) Identifiers:** 2.1.1 uses ISO 3166-1 alpha-3 country codes (`FRA`, `NLD`); 2.2.1 switches to alpha-2 (`FR`, `NL`) plus a separate `party_id`. OCPI 2.2.1 also adds a `4xxx` Hub-error status-code class and a third credentials token (Token C) for hub-mediated routing. **OCPI 2.1.1 and OCPI 2.2.1** are the two versions most EV charging teams evaluate when they build roaming integrations, both published by the [EVRoaming Foundation](https://evroaming.org/). The specifications and reference schemas are hosted on [GitHub at ocpi/ocpi](https://github.com/ocpi/ocpi). OCPI 2.1.1 remains a common baseline for partner interoperability, while OCPI 2.2.1 expands the protocol for hubs, smarter tariff handling, and charging-profile workflows. If you need version-specific validation, start with [OCPI 2.1.1 testing](/protocols/ocpi-2-1-1) and [OCPI 2.2.1 testing](/protocols/ocpi-2-2-1). If you are preparing for roaming rollout or partner onboarding, continue with [OCPI roaming testing](/use-cases/ocpi-roaming-testing) or [book an OCPI demo](/contact). ## What Are the Key Differences Between OCPI 2.1.1 and 2.2.1? | Feature | OCPI 2.1.1 | OCPI 2.2.1 | |---|---|---| | **Core roaming modules** | Yes | Yes | | **Credentials + version discovery** | Yes | Yes | | **Locations, Sessions, CDRs, Tariffs, Tokens, Commands** | Yes | Yes | | **Roles** | CPO, EMSP, OTHER (no Hub role) | CPO, EMSP, HUB, NSP, NAP, SCSP, OTHER | | **Country codes** | ISO 3166-1 alpha-3 (e.g. `FRA`, `NLD`, `DEU`) | ISO 3166-1 alpha-2 (e.g. `FR`, `NL`, `DE`) plus separate `party_id` | | **Hub support** | No native Hub role; hubs operate as CPO/eMSP peers | Native HUB role with hub-aware routing headers (`OCPI-from-*` / `OCPI-to-*`) | | **HubClientInfo module** | No | Yes | | **ChargingProfiles module** | No | Yes | | **Credentials handshake** | Token A → Token B | Token A → Token B → Token C (hub-aware) | | **Status codes** | 1xxx success, 2xxx client, 3xxx server | Same plus 4xxx Hub errors | | **Tariff model** | Core pricing model | Richer tariff metadata and structure | | **Migration difficulty** | Lower implementation surface | Larger implementation surface | | **Best fit** | Direct roaming partners and baseline interoperability | Hubs, smart charging, and broader future-ready roaming | ## The Short Answer Choose **OCPI 2.1.1** when you need the fastest path to stable roaming interoperability with the core modules: credentials, locations, sessions, CDRs, tariffs, tokens, and commands. Choose **OCPI 2.2.1** when you need hub-oriented behavior, smarter charging workflows, or a broader protocol surface for future roaming requirements. In practice, many teams still need to **support both**: 2.1.1 for existing partner compatibility and 2.2.1 for newer integrations. By the numbers — as of 2025, per the [EVRoaming Foundation](https://evroaming.org/) and the published [OCPI specifications](https://github.com/ocpi/ocpi): - **OCPI 2.1.1 defines 6 modules** (Locations, Sessions, CDRs, Tariffs, Tokens, Commands) plus Credentials and Versions. Roles: CPO, EMSP, OTHER. - **OCPI 2.2.1 defines 8 modules** — the same 6 plus **ChargingProfiles** and **HubClientInfo**. Roles add **Hub, NSP, NAP, SCSP**. - **Country codes**: 2.1.1 uses [ISO 3166-1](https://www.iso.org/iso-3166-country-codes.html) **alpha-3** (`FRA`, `NLD`, `DEU`); 2.2.1 switches to **alpha-2 + a separate `party_id`**. - **Status codes**: 2.1.1 uses ranges 1xxx / 2xxx / 3xxx; 2.2.1 adds a **4xxx Hub-error class** (15 codes). - **Credentials handshake**: 2.1.1 uses **Token A → Token B** (2 tokens); 2.2.1 uses **Token A → Token B → Token C** (3 tokens) for hub-aware routing. ## What Stays the Same Between the Two Versions? The good news is that the two versions share the same core model: - REST APIs over HTTPS - credentials handshake and token exchange - version discovery through `/versions` - core roaming entities such as locations, EVSEs, sessions, CDRs, tariffs, and tokens - CPO and eMSP role separation That means an upgrade from 2.1.1 to 2.2.1 is usually not a full rewrite. It is more often an expansion of your existing roaming implementation. ## Where Does OCPI 2.2.1 Add Real Value? ### 1. Hub-Centric Integrations OCPI 2.2.1 is a better fit for hub-connected ecosystems because it adds structures that are more practical for multi-party roaming environments. The most visible example is `HubClientInfo`, which helps systems exchange participant information in hub-based topologies. If your roadmap includes hub onboarding, version 2.2.1 is usually the safer long-term choice. ### 2. ChargingProfiles OCPI 2.2.1 introduces `ChargingProfiles`, which matters when smart charging needs to pass through the roaming chain instead of staying entirely inside the local CPO backend. This becomes relevant when: - an eMSP wants to influence charging behavior - a roaming workflow needs schedule-aware energy management - the backend stack must coordinate with [OCPP 2.0.1 smart charging flows](/protocols/ocpp-2-0-1), the charger-side protocol maintained by the [Open Charge Alliance](https://openchargealliance.org/protocols/open-charge-point-protocol/) ### 3. Richer Tariff and Field Coverage OCPI 2.2.1 gives teams more expressive tariff and metadata structures. That matters when pricing presentation, settlement clarity, or country-specific compliance expectations become stricter. ## How Do the Modules Compare? ### Credentials and Version Discovery No major conceptual change here. Both versions rely on the same practical sequence: 1. `GET /versions` 2. `GET /versions/{version}` 3. `POST /credentials` 4. token exchange and endpoint discovery This is why many teams can run both versions side by side without changing the whole architecture. ### Locations, Sessions, and CDRs Both versions support the core data flows roaming teams need every day: - publish charger locations and EVSE data - exchange live or near-real-time session updates - submit CDRs for settlement and invoicing For many operators, this is enough to ship a production roaming connection on 2.1.1. ### Tokens and Commands Again, both versions cover the main operational paths: - driver token synchronization - remote start and stop behavior - reservation and unlock style command flows If your product only needs baseline roaming enablement, 2.1.1 can remain perfectly serviceable. ### ChargingProfiles This is one of the clearest reasons to move to 2.2.1. When your roaming program needs charging control beyond static authorization and billing, 2.2.1 gives you the protocol surface to model it. ### HubClientInfo This is the other major differentiator. Hub-oriented roaming is easier to reason about in 2.2.1 because the protocol acknowledges those integration patterns more explicitly. ## When Should You Choose OCPI 2.1.1? Choose **OCPI 2.1.1** if: - you need fast partner onboarding with the core roaming modules - your partners already standardize on 2.1.1 - you do not need ChargingProfiles right now - your current architecture is direct CPO-to-eMSP interoperability rather than hub-heavy orchestration - you want a narrower implementation scope for the first production release For many teams, 2.1.1 is the right operational baseline and remains worth supporting for years. ## When Should You Choose OCPI 2.2.1? Choose **OCPI 2.2.1** if: - you need hub integration workflows - you need `HubClientInfo` - you need `ChargingProfiles` - your tariff and metadata requirements are growing - you want to reduce the risk of building against an older functional baseline while your product roadmap expands If you are building a newer roaming platform from scratch, 2.2.1 is often the better strategic default. ## Should You Support Both OCPI Versions? The safest commercial approach is often: - **support OCPI 2.1.1 for baseline compatibility** - **support OCPI 2.2.1 for advanced and future-facing integrations** This mirrors what many backend teams already do on the charger side with [OCPP 1.6 testing](/protocols/ocpp-1-6) and [OCPP 2.0.1 testing](/protocols/ocpp-2-0-1). ## How Do You Migrate from OCPI 2.1.1 to 2.2.1? ### Step 1: Keep Your Core Modules Stable Before adding 2.2.1-only features, make sure your 2.1.1 baseline is fully reliable: - credentials lifecycle - locations synchronization - sessions and CDR exchange - token authorization - command callbacks and error handling ### Step 2: Add Version-Aware Routing Make sure your implementation can distinguish version-specific endpoints and payload handling cleanly. This reduces regression risk and lets you run 2.1.1 and 2.2.1 side by side. ### Step 3: Add 2.2.1-Only Modules Deliberately Treat `ChargingProfiles` and `HubClientInfo` as explicit additions, not incidental changes. They usually need: - new payload validation - new persistence models - new async workflow handling - new interoperability tests ### Step 4: Test with Simulated Counterparties Do not wait for a live roaming partner or hub to discover payload mismatches. Simulate the opposite party and test the full flow before launch with [OCPI roaming testing](/use-cases/ocpi-roaming-testing). ### Step 5: Validate Mixed-Version Behavior If your platform will support both versions, test: - 2.1.1-only partner flows - 2.2.1-only partner flows - shared core modules across both versions - error handling when payload expectations diverge ## Example Decision Framework | Situation | Recommended Version | |---|---| | Launching a simple direct roaming integration | OCPI 2.1.1 | | Connecting to hub-oriented ecosystems | OCPI 2.2.1 | | Need smart charging over roaming | OCPI 2.2.1 | | Need maximum compatibility with existing partners | OCPI 2.1.1 plus 2.2.1 roadmap | | Building a future-facing roaming platform | Support both, prioritize 2.2.1 depth | ## Frequently Asked Questions ### Is OCPI 2.2.1 backward compatible with 2.1.1? Not automatically in the sense of using identical endpoints and payload expectations everywhere. The versions are closely related, but your implementation still needs explicit version-aware handling. ### Should I skip OCPI 2.1.1 and only implement 2.2.1? Only if you are certain your target partners and hubs do not require 2.1.1. Many teams still need 2.1.1 for practical interoperability. ### Is ChargingProfiles the main reason to adopt 2.2.1? It is one of the strongest reasons, especially for smart charging and advanced roaming workflows. Hub support is the other big reason. ### What is the safest production strategy? Support the 2.1.1 baseline cleanly, then expand to 2.2.1 where partner demand or product scope requires it. ## Further Reading - [OCPI 2.1.1 testing](/protocols/ocpi-2-1-1) - [OCPI 2.2.1 testing](/protocols/ocpi-2-2-1) - [What is OCPI?](/blog/what-is-ocpi) - [OCPI endpoints complete reference](/blog/ocpi-endpoints-complete-reference) - [How to implement OCPI roaming](/blog/how-to-implement-ocpi-roaming) - [OCPI roaming testing](/use-cases/ocpi-roaming-testing) --- ## OCPP Message Types Reference: 1.6 and 2.0.1 Explained Source: https://ocpplab.com/blog/ocpp-message-types-complete-reference Reference guide to all OCPP 1.6 and 2.0.1 message types, including the 28 core 1.6 actions, TransactionEvent, directions, payloads, and worked examples. **Quick answer:** OCPP message types are the named actions a charge point and CPMS exchange over WebSocket in a strict request-response pattern. Every request is a `CALL`; responses are a `CALLRESULT` or `CALLERROR`. OCPP 1.6 defines about 28 core actions, while OCPP 2.0.1 roughly doubles them and unifies transactions under `TransactionEvent`. **OCPP message types** define every interaction between a charge point and a Charging Station Management System (CPMS). Each message type corresponds to a specific operation: authorizing a user, starting a transaction, reporting meter data, updating firmware, or configuring smart charging profiles. The [Open Charge Point Protocol](https://openchargealliance.org/protocols/open-charge-point-protocol/), maintained by the Open Charge Alliance, specifies exactly which party initiates each message, what fields are required, and what response is expected. OCPP communication follows a strict request-response pattern over [WebSocket](/blog/ocpp-websocket-guide). Every request is a `CALL` message containing an action name and payload. The receiver responds with either a `CALLRESULT` (success) or a `CALLERROR` (failure). There are no unsolicited responses, no partial acknowledgments, and no message queuing within the protocol itself. Understanding the full catalog of message types is the foundation for building any OCPP-compliant system. This reference covers every message type in OCPP 1.6 and 2.0.1, organized by direction and protocol version. If you want version-specific execution guidance beyond the message catalog, see [OCPP 1.6 testing](/protocols/ocpp-1-6) and [OCPP 2.0.1 testing](/protocols/ocpp-2-0-1). ## How Is an OCPP Message Formatted? All OCPP messages are JSON arrays transmitted over WebSocket. There are three message types, each identified by a `MessageTypeId` integer. ### CALL (Request) — MessageTypeId 2 ```json [2, "uniqueId-123", "BootNotification", { "chargePointVendor": "OCPPLab", "chargePointModel": "Emulator-v1" }] ``` | Position | Field | Type | Description | |----------|-------|------|-------------| | 0 | `MessageTypeId` | Integer | Always `2` for CALL | | 1 | `UniqueId` | String | Unique identifier for this request (max 36 chars) | | 2 | `Action` | String | The message type name (e.g., `BootNotification`) | | 3 | `Payload` | Object | JSON object containing the message fields | ### CALLRESULT (Success Response) — MessageTypeId 3 ```json [3, "uniqueId-123", { "currentTime": "2025-03-20T10:00:00.000Z", "interval": 300, "status": "Accepted" }] ``` | Position | Field | Type | Description | |----------|-------|------|-------------| | 0 | `MessageTypeId` | Integer | Always `3` for CALLRESULT | | 1 | `UniqueId` | String | Must match the `UniqueId` of the original CALL | | 2 | `Payload` | Object | Response data specific to the action | ### CALLERROR (Error Response) — MessageTypeId 4 ```json [4, "uniqueId-123", "InternalError", "Database connection timeout", {"retryAfter": 30}] ``` | Position | Field | Type | Description | |----------|-------|------|-------------| | 0 | `MessageTypeId` | Integer | Always `4` for CALLERROR | | 1 | `UniqueId` | String | Must match the `UniqueId` of the original CALL | | 2 | `ErrorCode` | String | Standardized [OCPP error code](/blog/ocpp-error-codes-reference) | | 3 | `ErrorDescription` | String | Human-readable explanation (max 255 chars) | | 4 | `ErrorDetails` | Object | Optional additional context | The `UniqueId` ties every response to its request. A charge point or CPMS must never send a CALLRESULT or CALLERROR without a matching pending CALL. If a response is not received within the configured timeout, the sender should treat the request as failed. ## Which OCPP 1.6 Messages Are Charger-Initiated? These messages are sent **from the charge point to the CPMS**. The charge point creates the CALL; the CPMS responds with CALLRESULT or CALLERROR. | Message Name | Purpose | Key Fields | When Sent | |---|---|---|---| | **Authorize** | Validate an ID tag before or during charging | `idTag` | User presents RFID card or app credential | | **BootNotification** | Register the charger and receive configuration | `chargePointVendor`, `chargePointModel`, `chargePointSerialNumber` | On startup, after reset, or after reconnection | | **DataTransfer** | Send vendor-specific data outside the standard spec | `vendorId`, `messageId`, `data` | Anytime — used for custom extensions | | **DiagnosticsStatusNotification** | Report diagnostic upload progress | `status` (Idle, Uploaded, UploadFailed, Uploading) | After CPMS requests diagnostics via GetDiagnostics | | **FirmwareStatusNotification** | Report firmware update progress | `status` (Downloaded, DownloadFailed, Downloading, Idle, InstallationFailed, Installing, Installed) | During firmware update lifecycle | | **Heartbeat** | Confirm the charger is still connected | *(empty payload)* | At the interval specified in BootNotification response | | **MeterValues** | Report energy measurements and power readings | `connectorId`, `meterValue[]` (timestamp, sampledValue[]) | Periodically during charging, or clock-aligned | | **StartTransaction** | Notify CPMS that a charging session has begun | `connectorId`, `idTag`, `meterStart`, `timestamp` | When energy transfer starts | | **StatusNotification** | Report the current status of a connector | `connectorId`, `errorCode`, `status` | On status change (Available, Charging, Faulted, etc.) | | **StopTransaction** | Notify CPMS that a charging session has ended | `transactionId`, `meterStop`, `timestamp`, `reason` | When energy transfer stops | Every charger-initiated message expects a `.conf` response from the CPMS. For example, `BootNotification` expects a `BootNotification.conf` containing `status`, `currentTime`, and `interval`. If the CPMS responds with `status: Rejected`, the charger must retry at the interval specified and must not accept charging sessions until accepted. ## Which OCPP 1.6 Messages Are CPMS-Initiated? These messages are sent **from the CPMS to the charge point**. The CPMS creates the CALL; the charge point responds. | Message Name | Purpose | Key Fields | When Sent | |---|---|---|---| | **CancelReservation** | Cancel a previously made reservation | `reservationId` | When a user cancels or reservation policy requires it | | **ChangeAvailability** | Set a connector or charger to operative/inoperative | `connectorId`, `type` (Operative, Inoperative) | For maintenance, scheduling, or load management | | **ChangeConfiguration** | Update a configuration key on the charger | `key`, `value` | To adjust settings like heartbeat interval or meter sampling | | **ClearCache** | Clear the charger's local authorization cache | *(empty payload)* | When authorization data has changed centrally | | **ClearChargingProfile** | Remove one or more charging profiles | `id`, `connectorId`, `chargingProfilePurpose`, `stackLevel` | When smart charging profiles need to be cleared | | **DataTransfer** | Send vendor-specific data to the charger | `vendorId`, `messageId`, `data` | For custom vendor extensions | | **GetCompositeSchedule** | Retrieve the effective composite charging schedule from all active profiles | `connectorId`, `duration`, `chargingRateUnit` | For verifying the actual schedule a connector will follow | | **GetConfiguration** | Retrieve current configuration values | `key[]` (optional — omit to get all) | For diagnostics or auditing charger settings | | **GetDiagnostics** | Request the charger to upload diagnostic logs | `location` (URI), `startTime`, `stopTime`, `retries` | When debugging charger issues remotely | | **GetLocalListVersion** | Check the version of the local authorization list | *(empty payload)* | Before sending an updated local list | | **RemoteStartTransaction** | Remotely start a charging session | `idTag`, `connectorId` (optional), `chargingProfile` (optional) | When user starts charging via mobile app or CPMS portal | | **RemoteStopTransaction** | Remotely stop a charging session | `transactionId` | When user or operator stops charging remotely | | **ReserveNow** | Reserve a connector for a specific user | `connectorId`, `expiryDate`, `idTag`, `reservationId` | When a user reserves a charger in advance | | **Reset** | Reboot the charger | `type` (Hard, Soft) | For recovery, updates, or maintenance | | **SendLocalList** | Send or update the local authorization list | `listVersion`, `localAuthorizationList[]`, `updateType` | To enable offline authorization | | **SetChargingProfile** | Install a charging profile for smart charging | `connectorId`, `csChargingProfiles` | For load balancing, demand response, or scheduled charging | | **TriggerMessage** | Request the charger to send a specific message immediately | `requestedMessage` (e.g., BootNotification, MeterValues) | When CPMS needs a status update on demand | | **UnlockConnector** | Remotely unlock a connector | `connectorId` | When a cable is stuck or user requests remote unlock | | **UpdateFirmware** | Instruct charger to download and install new firmware | `location` (URI), `retrieveDate`, `retries`, `retryInterval` | For firmware rollouts | All 19 CPMS-initiated messages follow the same CALL/CALLRESULT pattern. The charge point must implement handlers for every message it claims to support in its feature profile. ## What Messages Are New in OCPP 2.0.1? [OCPP 2.0.1](/blog/ocpp-1-6-vs-2-0-1) introduces a significantly expanded message set organized into functional blocks, as documented in the [OCPP 2.0.1 specification](https://openchargealliance.org/protocols/open-charge-point-protocol/) from the Open Charge Alliance. Many OCPP 1.6 messages were renamed, split, or consolidated. The following table lists messages that are **new in 2.0.1** or substantially changed from 1.6. ### New Charger-Initiated Messages (2.0.1) | Message Name | Purpose | Functional Block | |---|---|---| | **Authorize** | Extended with certificate-based auth, ISO 15118 support | Authorization | | **ClearedChargingLimit** | Notify CPMS that an external charging limit was cleared | SmartCharging | | **FirmwareStatusNotification** | Extended with `requestId` for tracking | FirmwareManagement | | **Get15118EVCertificate** | Request an ISO 15118 certificate for the EV | ISO15118CertificateManagement | | **LogStatusNotification** | Report log upload status (replaces DiagnosticsStatusNotification) | Diagnostics | | **MeterValues** | Restructured with `evse` instead of `connectorId` | MeterValues | | **NotifyChargingLimit** | Report external charging limits (e.g., from grid operator) | SmartCharging | | **NotifyCustomerInformation** | Return customer information requested by CPMS | CustomerInformation | | **NotifyDisplayMessages** | Return display messages currently stored | DisplayMessage | | **NotifyEVChargingNeeds** | Report the EV's charging requirements (ISO 15118) | SmartCharging | | **NotifyEVChargingSchedule** | Report the current EV charging schedule | SmartCharging | | **NotifyEvent** | Report events and monitoring results | DeviceModel | | **NotifyMonitoringReport** | Return monitoring configuration data | DeviceModel | | **NotifyReport** | Return device model report data | DeviceModel | | **PublishFirmwareStatusNotification** | Report publish firmware status for local controller | FirmwareManagement | | **ReportChargingProfiles** | Return installed charging profiles | SmartCharging | | **ReservationStatusUpdate** | Report reservation status changes | Reservation | | **SecurityEventNotification** | Report security-related events | Security | | **SignCertificate** | Request CPMS to sign a certificate | Security | | **TransactionEvent** | Unified transaction lifecycle reporting (replaces StartTransaction, StopTransaction, MeterValues during transaction) | Transactions | ### New CPMS-Initiated Messages (2.0.1) | Message Name | Purpose | Functional Block | |---|---|---| | **CertificateSigned** | Send a signed certificate to the charger | Security | | **ClearDisplayMessage** | Remove a message from the charger display | DisplayMessage | | **ClearVariableMonitoring** | Remove monitoring settings | DeviceModel | | **CostUpdated** | Update the running cost of a transaction | TariffAndCost | | **CustomerInformation** | Request customer data stored on charger | CustomerInformation | | **DeleteCertificate** | Remove an installed certificate | Security | | **GetBaseReport** | Request a full device model report | DeviceModel | | **GetChargingProfiles** | Request installed charging profiles | SmartCharging | | **GetDisplayMessages** | Request current display messages | DisplayMessage | | **GetInstalledCertificateIds** | List installed certificates | Security | | **GetLog** | Request log upload (replaces GetDiagnostics) | Diagnostics | | **GetMonitoringReport** | Request monitoring configuration | DeviceModel | | **GetReport** | Request specific device model variables | DeviceModel | | **GetTransactionStatus** | Check if a transaction is still ongoing | Transactions | | **GetVariables** | Read device model variables | DeviceModel | | **InstallCertificate** | Install a certificate on the charger | Security | | **PublishFirmware** | Instruct local controller to publish firmware | FirmwareManagement | | **RequestStartTransaction** | Start a transaction (replaces RemoteStartTransaction) | Transactions | | **RequestStopTransaction** | Stop a transaction (replaces RemoteStopTransaction) | Transactions | | **SetDisplayMessage** | Configure a message on the charger display | DisplayMessage | | **SetMonitoringBase** | Configure monitoring base settings | DeviceModel | | **SetMonitoringLevel** | Set the severity level for monitoring | DeviceModel | | **SetNetworkProfile** | Configure network connection settings | Provisioning | | **SetVariableMonitoring** | Configure monitoring on device variables | DeviceModel | | **SetVariables** | Write device model variables | DeviceModel | | **UnpublishFirmware** | Remove published firmware from local controller | FirmwareManagement | The most significant architectural change in 2.0.1 is the introduction of **TransactionEvent**, which consolidates `StartTransaction`, `StopTransaction`, and in-transaction `MeterValues` into a single message with an `eventType` field (`Started`, `Updated`, `Ended`). This simplifies transaction tracking and eliminates race conditions common in 1.6 implementations. ## Key Messages Deep Dive The following sections provide detailed request/response examples for the six most commonly implemented and debugged OCPP messages. ### BootNotification BootNotification is the first meaningful message a charger sends after establishing a WebSocket connection. It registers the charger with the CPMS and receives time synchronization and heartbeat configuration. **OCPP 1.6 Request:** ```json [2, "boot-001", "BootNotification", { "chargePointVendor": "OCPPLab", "chargePointModel": "Emulator-Pro", "chargePointSerialNumber": "OCPPLAB-001-2025", "chargeBoxSerialNumber": "CB-001", "firmwareVersion": "2.5.0", "iccid": "8901260882902730001", "imsi": "310260000000001", "meterType": "ACMeter", "meterSerialNumber": "MTR-001" }] ``` **OCPP 1.6 Response (Accepted):** ```json [3, "boot-001", { "currentTime": "2025-03-20T10:00:00.000Z", "interval": 300, "status": "Accepted" }] ``` **OCPP 2.0.1 Request** (restructured with nested `chargingStation` object): ```json [2, "boot-001", "BootNotification", { "reason": "PowerUp", "chargingStation": { "model": "Emulator-Pro", "vendorName": "OCPPLab", "serialNumber": "OCPPLAB-001-2025", "firmwareVersion": "2.5.0" } }] ``` The `status` field in the response determines charger behavior: - **Accepted**: Charger operates normally, sends Heartbeat at the specified `interval`. - **Pending**: CPMS needs more time or configuration. Charger must not accept transactions. Retry at `interval`. - **Rejected**: Charger is not recognized. Charger must not accept transactions. Retry at `interval`. A charger stuck in `Pending` or `Rejected` is one of the most common deployment issues. Check the serial number, vendor name, and CPMS registration status when troubleshooting. ### StartTransaction vs. TransactionEvent In OCPP 1.6, `StartTransaction` and `StopTransaction` are separate messages. In 2.0.1, both are replaced by `TransactionEvent`. **OCPP 1.6 StartTransaction:** ```json [2, "tx-001", "StartTransaction", { "connectorId": 1, "idTag": "RFID-ABC123", "meterStart": 1500, "timestamp": "2025-03-20T10:05:00.000Z" }] ``` **OCPP 1.6 StartTransaction Response:** ```json [3, "tx-001", { "idTagInfo": { "status": "Accepted", "expiryDate": "2025-12-31T23:59:59.000Z" }, "transactionId": 42 }] ``` **OCPP 2.0.1 TransactionEvent (Started):** ```json [2, "tx-001", "TransactionEvent", { "eventType": "Started", "timestamp": "2025-03-20T10:05:00.000Z", "triggerReason": "Authorized", "seqNo": 0, "transactionInfo": { "transactionId": "TX-20250320-001" }, "idToken": { "idToken": "RFID-ABC123", "type": "ISO14443" }, "evse": { "id": 1, "connectorId": 1 } }] ``` **OCPP 2.0.1 TransactionEvent (Ended):** ```json [2, "tx-002", "TransactionEvent", { "eventType": "Ended", "timestamp": "2025-03-20T12:30:00.000Z", "triggerReason": "EVDeparted", "seqNo": 15, "transactionInfo": { "transactionId": "TX-20250320-001", "stoppedReason": "EVDisconnected" }, "meterValue": [{ "timestamp": "2025-03-20T12:30:00.000Z", "sampledValue": [{ "value": 32.5, "measurand": "Energy.Active.Import.Register", "unitOfMeasure": { "unit": "kWh" } }] }] }] ``` Key differences: In 2.0.1, the transaction ID is a string generated by the charger (not an integer assigned by the CPMS). Meter values can be included directly in `TransactionEvent` messages, reducing the number of separate `MeterValues` calls needed during a session. ### MeterValues MeterValues reports energy consumption, power levels, voltage, current, and other electrical measurements during a charging session. It is one of the highest-frequency messages in any OCPP deployment. **OCPP 1.6 MeterValues:** ```json [2, "meter-001", "MeterValues", { "connectorId": 1, "transactionId": 42, "meterValue": [{ "timestamp": "2025-03-20T10:15:00.000Z", "sampledValue": [ { "value": "1.85", "context": "Sample.Periodic", "format": "Raw", "measurand": "Energy.Active.Import.Register", "location": "Outlet", "unit": "kWh" }, { "value": "7200", "context": "Sample.Periodic", "measurand": "Power.Active.Import", "unit": "W" }, { "value": "230.1", "context": "Sample.Periodic", "measurand": "Voltage", "unit": "V" }, { "value": "31.3", "context": "Sample.Periodic", "measurand": "Current.Import", "unit": "A" } ] }] }] ``` **Sampling contexts determine when meter values are captured:** | Context | Description | |---|---| | `Sample.Periodic` | Taken at a regular interval configured via `MeterValueSampleInterval` | | `Sample.Clock` | Taken at clock-aligned intervals configured via `ClockAlignedDataInterval` | | `Transaction.Begin` | Taken at the start of a transaction | | `Transaction.End` | Taken at the end of a transaction | | `Trigger` | Taken in response to a TriggerMessage request | | `Interruption.Begin` | Taken when power delivery is interrupted | | `Interruption.End` | Taken when power delivery resumes | | `Other` | Any reading not covered by the other contexts | **Sampled vs. Clock-Aligned**: `Sample.Periodic` values are relative to the transaction start (e.g., every 60 seconds after charging begins). `Sample.Clock` values align to absolute clock boundaries (e.g., every 15 minutes on the hour: 10:00, 10:15, 10:30). Clock-aligned data is typically used for billing and regulatory reporting because it produces consistent time boundaries across all chargers. The CPMS response to MeterValues is always an empty object `{}`. There is no mechanism for the CPMS to reject or request retransmission of meter data within the protocol. ### StatusNotification StatusNotification reports the operational state of a connector or the charge point itself. It is sent whenever a state transition occurs. **OCPP 1.6 StatusNotification:** ```json [2, "status-001", "StatusNotification", { "connectorId": 1, "errorCode": "NoError", "status": "Charging", "timestamp": "2025-03-20T10:05:01.000Z", "info": "Vehicle connected and charging at 7.2kW", "vendorId": "OCPPLab", "vendorErrorCode": "" }] ``` **OCPP 1.6 Status Values:** | Status | Description | |---|---| | `Available` | Connector is free and ready for a new session | | `Preparing` | Connector is occupied but not yet charging (e.g., cable plugged in, awaiting authorization) | | `Charging` | Energy is actively being transferred to the EV | | `SuspendedEVSE` | Charging paused by the charger (e.g., load balancing, temperature limit) | | `SuspendedEV` | Charging paused by the vehicle (e.g., battery management, target SoC reached temporarily) | | `Finishing` | Transaction is stopping, energy transfer has ceased, connector not yet available | | `Reserved` | Connector is reserved for a specific user | | `Unavailable` | Connector is not available for charging (maintenance, out of service) | | `Faulted` | Connector has a fault condition — check `errorCode` for specifics | **OCPP 1.6 Error Codes in StatusNotification:** | Error Code | Description | |---|---| | `ConnectorLockFailure` | Failed to lock or unlock the connector | | `EVCommunicationError` | Communication failure with the vehicle | | `GroundFailure` | Ground fault detected | | `HighTemperature` | Temperature exceeded safe limits | | `InternalError` | Internal charger error | | `LocalListConflict` | Conflict in local authorization list | | `NoError` | No error (normal operation) | | `OtherError` | Error not covered by other codes | | `OverCurrentFailure` | Overcurrent detected | | `OverVoltage` | Voltage exceeded safe limits | | `PowerMeterFailure` | Power meter communication failure | | `PowerSwitchFailure` | Power relay or switch failure | | `ReaderFailure` | RFID reader or authorization device failure | | `ResetFailure` | Charger failed to reset | | `UnderVoltage` | Voltage below minimum safe level | | `WeakSignal` | Cellular or wireless signal too weak | In OCPP 2.0.1, `StatusNotification` is simplified to report only `connectorStatus` (`Available`, `Occupied`, `Reserved`, `Unavailable`, `Faulted`). Detailed error reporting moves to the `NotifyEvent` message and the device model. ### SetChargingProfile SetChargingProfile installs a charging profile on a connector for smart charging, load balancing, or demand response. It is the foundation of [smart charging](/blog/smart-charging-explained) in OCPP. **OCPP 1.6 SetChargingProfile (load limiting to 16A):** ```json [2, "profile-001", "SetChargingProfile", { "connectorId": 1, "csChargingProfiles": { "chargingProfileId": 100, "stackLevel": 0, "chargingProfilePurpose": "TxDefaultProfile", "chargingProfileKind": "Absolute", "chargingSchedule": { "chargingRateUnit": "A", "chargingSchedulePeriod": [ { "startPeriod": 0, "limit": 16.0 } ] } } }] ``` **Time-of-use smart charging example (off-peak boost):** ```json [2, "profile-002", "SetChargingProfile", { "connectorId": 0, "csChargingProfiles": { "chargingProfileId": 200, "stackLevel": 1, "chargingProfilePurpose": "ChargePointMaxProfile", "chargingProfileKind": "Recurring", "recurrencyKind": "Daily", "chargingSchedule": { "startSchedule": "2025-03-20T00:00:00.000Z", "chargingRateUnit": "A", "chargingSchedulePeriod": [ { "startPeriod": 0, "limit": 16.0 }, { "startPeriod": 25200, "limit": 8.0 }, { "startPeriod": 72000, "limit": 32.0 } ] } } }] ``` This profile limits the entire charge point (`connectorId: 0`) to 16A from midnight, reduces to 8A at 07:00 (peak hours, `startPeriod: 25200` = 7 hours x 3600 seconds), and boosts to 32A at 20:00 (`startPeriod: 72000` = 20 hours x 3600 seconds) during off-peak. **Charging Profile Purposes:** - **ChargePointMaxProfile**: Maximum power for the entire charge point. Applied to `connectorId: 0`. - **TxDefaultProfile**: Default profile applied to all transactions on a connector unless overridden. - **TxProfile**: Profile for a specific active transaction. Highest priority for that transaction. Profiles at higher `stackLevel` values take precedence when multiple profiles of the same purpose exist. The effective limit is always the minimum of all applicable profiles. ### RemoteStartTransaction RemoteStartTransaction instructs a charger to begin a charging session, typically triggered by a mobile app or backend system. It can optionally include a charging profile for the session. **OCPP 1.6 RemoteStartTransaction:** ```json [2, "remote-001", "RemoteStartTransaction", { "connectorId": 1, "idTag": "APP-USER-456", "chargingProfile": { "chargingProfileId": 300, "stackLevel": 0, "chargingProfilePurpose": "TxProfile", "chargingProfileKind": "Absolute", "chargingSchedule": { "chargingRateUnit": "W", "chargingSchedulePeriod": [ { "startPeriod": 0, "limit": 7400.0 }, { "startPeriod": 7200, "limit": 11000.0 } ] } } }] ``` **Response:** ```json [3, "remote-001", { "status": "Accepted" }] ``` This request starts a session on connector 1 for user `APP-USER-456`, beginning at 7.4 kW and increasing to 11 kW after 2 hours. The charger will respond `Accepted` if it can start the session, or `Rejected` if the connector is unavailable, faulted, or occupied. After accepting a `RemoteStartTransaction`, the charger must still send a `StartTransaction` message to the CPMS once energy transfer actually begins. The `RemoteStartTransaction` acceptance only means the charger will attempt to start; it does not guarantee the session will begin (the EV may not be plugged in, authorization may fail, etc.). In OCPP 2.0.1, this message is renamed to `RequestStartTransaction` and includes an `evseId` instead of `connectorId`, along with an optional `groupIdToken` for group authorization scenarios. ## How Should You Handle OCPP Errors? When a CALL message cannot be processed, the receiver sends a CALLERROR instead of a CALLRESULT. OCPP defines these standard [error codes](/blog/ocpp-error-codes-reference): | Error Code | Description | |---|---| | `NotImplemented` | The action is not supported by the receiver | | `NotSupported` | The action is recognized but not supported in this context | | `InternalError` | An internal error prevented processing | | `ProtocolError` | The message does not conform to the OCPP protocol | | `SecurityError` | A security violation was detected | | `FormationViolation` | The payload is syntactically incorrect (malformed JSON, wrong types) | | `PropertyConstraintViolation` | A field value violates its constraints (e.g., string too long, number out of range) | | `OccurrenceConstraintViolation` | A required field is missing or an unexpected field is present | | `TypeConstraintViolation` | A field has the wrong data type | | `GenericError` | Any error not covered by the above codes | Best practices for error handling: 1. **Always respond.** Never leave a CALL unanswered. If you cannot process it, send a CALLERROR. 2. **Use specific error codes.** `FormationViolation` is more useful than `GenericError` when the JSON is malformed. 3. **Include error details.** The `errorDetails` object should contain actionable information such as which field failed validation and why. 4. **Implement timeouts.** If no response arrives within 30 seconds (configurable), treat the request as failed and clean up any pending state. 5. **Log everything.** Every CALLERROR should be logged with the full request context for debugging. ## Frequently Asked Questions ### How many message types does OCPP 1.6 define? As enumerated in the [OCPP 1.6 specification](https://openchargealliance.org/protocols/open-charge-point-protocol/) published by the Open Charge Alliance (first released in 2015), the core profile defines 28 unique actions: 10 charger-initiated and 19 CPMS-initiated, with `DataTransfer` appearing in both directions. Each action has a corresponding `.conf` response structure, but these are not counted as separate messages. The [OCPP 1.6 Security Whitepaper](https://openchargealliance.org/ocpp-info-whitepapers/ocpp-1-6-security-whitepaper-4th-edition/), whose security extension was introduced in edition 2, adds 11 more actions (signed firmware, certificate management, log upload, and `SecurityEventNotification`), bringing the full count to roughly 39 when both the core and the security extension are implemented. ### What changed from OCPP 1.6 to OCPP 2.0.1 regarding messages? OCPP 2.0.1 roughly doubles the message count and reorganizes them into functional blocks. The most impactful change is replacing `StartTransaction`, `StopTransaction`, and in-transaction `MeterValues` with the unified `TransactionEvent` message. New functional areas include security certificate management, display messaging, device model reporting, and ISO 15118 support. See our detailed [comparison guide](/blog/ocpp-1-6-vs-2-0-1). ### Can I use DataTransfer for anything? `DataTransfer` is the escape hatch for vendor-specific functionality not covered by the standard. Both the charger and CPMS can initiate it. Common uses include custom diagnostics, proprietary load management, and feature flags. However, relying heavily on DataTransfer reduces interoperability because each vendor's payloads are different. ### What happens if the charger sends a message the CPMS does not support? The CPMS should respond with a CALLERROR using `NotImplemented` as the error code. The charger must handle this gracefully. For critical messages like `BootNotification`, this typically indicates a serious configuration or version mismatch. ### How do I test all these message types? Use an [OCPP emulator](/blog/introducing-ocpp-emulator) to simulate both charger and CPMS behavior. A good emulator lets you send any message type with custom payloads, inspect responses, and test error scenarios without physical hardware. This is essential for validating your implementation against the full spec before deploying to production chargers. ### Are there differences between OCPP-J and OCPP-S message types? The message types (actions) are identical between OCPP-J (JSON over WebSocket) and OCPP-S (SOAP over HTTP). The difference is the transport format: OCPP-J uses the JSON array format described in this guide, while OCPP-S wraps the same data in XML/SOAP envelopes. OCPP-J is the dominant implementation today, and OCPP 2.0.1 only supports JSON. Read our [WebSocket guide](/blog/ocpp-websocket-guide) for transport-level details. ## What's Next This reference covers the message catalog. For implementation, start with these focused guides: - **[What is OCPP?](/blog/what-is-ocpp)** — Protocol fundamentals and architecture overview - **[OCPP 1.6 vs 2.0.1](/blog/ocpp-1-6-vs-2-0-1)** — Detailed version comparison and migration guidance - **[OCPP WebSocket Guide](/blog/ocpp-websocket-guide)** — Connection lifecycle, security, and reconnection strategies - **[OCPP Error Codes Reference](/blog/ocpp-error-codes-reference)** — Deep dive into every error code with troubleshooting - **[Smart Charging Explained](/blog/smart-charging-explained)** — Charging profiles, load management, and demand response --- ## OCPP Error Codes: Complete Reference Guide for Developers Source: https://ocpplab.com/blog/ocpp-error-codes-reference Learn all 10 OCPP error codes, the CALLERROR message format, common causes, and step-by-step troubleshooting to debug EV charging infrastructure faster. **Quick answer:** OCPP-J (the JSON variant used in both OCPP 1.6 and 2.0.1) defines exactly **10 error codes** carried in a `CALLERROR` frame: `NotImplemented`, `NotSupported`, `InternalError`, `ProtocolError`, `SecurityError`, `FormationViolation`, `PropertyConstraintViolation`, `OccurrenceConstraintViolation`, `TypeConstraintViolation`, and `GenericError`. A `CALLERROR` frame is `[4, "messageId", "errorCode", "errorDescription", {errorDetails}]`. The same 10 codes are shared between OCPP 1.6 and 2.0.1. **OCPP error codes** are the standardized error responses defined by the Open Charge Point Protocol for communicating failures between charge points and the [CPMS (Charging Station Management System)](/blog/what-is-CPMS). Understanding these errors is essential for every developer building, integrating, or debugging EV charging infrastructure. When an OCPP message cannot be processed, the receiving party responds with a `CALLERROR` message containing a specific error code, a human-readable description, and optional error details. Misinterpreting these errors or failing to handle them correctly leads to stuck transactions, offline chargers, and frustrated drivers. The full error-code enum is normative in the **OCPP-J transport profile** published by the [Open Charge Alliance](https://www.openchargealliance.org/). As defined in the [OCPP 1.6](https://openchargealliance.org/protocols/open-charge-point-protocol/) and [OCPP 2.0.1](https://openchargealliance.org/protocols/open-charge-point-protocol/) specifications, the same **10 error codes apply to both versions** — though, as our [OCPP 1.6 vs 2.0.1 comparison](/blog/ocpp-1-6-vs-2-0-1) explains, their payload schemas differ. This guide covers every OCPP error code, their common causes, and how to resolve them. ## How Does OCPP Error Handling Work? OCPP uses a simple request-response model over [WebSocket](/blog/ocpp-websocket-guide). Every request (CALL) receives either a success response (CALLRESULT) or an error response (CALLERROR). There is no concept of partial success or warnings within the protocol itself. For a breakdown of the three frame types, see our [OCPP message types reference](/blog/ocpp-message-types-complete-reference). ### The CALLERROR Message Format A CALLERROR is a JSON array with message type `4`: ```json [4, "messageId", "errorCode", "errorDescription", {errorDetails}] ``` | Field | Type | Description | |-------|------|-------------| | `4` | Integer | Message type identifier for CALLERROR | | `messageId` | String | Must match the `messageId` of the original CALL | | `errorCode` | String | One of the standardized OCPP error codes | | `errorDescription` | String | Human-readable error explanation (max 255 characters) | | `errorDetails` | Object | Optional JSON object with additional error context | Per the OCPP-J transport profile defined in the [OCPP 1.6 specification](https://openchargealliance.org/protocols/open-charge-point-protocol/), the `errorDescription` field is capped at 255 characters, while the `errorDetails` object structure is implementation-defined. ### Example CALLERROR Exchange A charger sends an `Authorize` request: ```json [2, "auth-001", "Authorize", { "idTag": "RFID-XYZ789" }] ``` The CPMS encounters an internal database failure and responds: ```json [4, "auth-001", "InternalError", "Authorization service temporarily unavailable", {"retryAfter": 30}] ``` The `messageId` ("auth-001") matches the original request, identifying which CALL this error corresponds to. The `errorDetails` object can contain any additional information the sender deems useful, though its structure is not standardized. ## What Are All 10 OCPP Error Codes? ### NotImplemented **Description:** The requested action is not known by the receiver. **Common Causes:** - Sending an OCPP 2.0.1 action to a CPMS that only supports OCPP 1.6 - Typo in the action name (e.g., "BootNotification" vs "bootNotification" -- OCPP is case-sensitive) - Custom or proprietary actions that the other party does not recognize - Protocol version mismatch between charger and CPMS **How to Fix:** - Verify the action name matches the OCPP specification exactly, including casing - Confirm both parties are using the same OCPP version - Check the WebSocket subprotocol negotiation to ensure version agreement - Review the CPMS or charger documentation for supported action lists ```json [4, "msg-001", "NotImplemented", "Action 'DataTransfer' is not implemented", {}] ``` ### NotSupported **Description:** The action is recognized but intentionally not supported by the receiver. **Common Causes:** - Sending `SetChargingProfile` to a charger that does not support smart charging - Requesting `GetDiagnostics` from a charger without diagnostics capability - Using optional OCPP features that the implementation chose not to include - Feature profile not enabled on the charger firmware **How to Fix:** - Check the charger's supported feature profiles in its documentation or configuration - In OCPP 2.0.1, verify the device model's supported feature list - Implement fallback logic for optional features that may not be universally supported - Do not confuse with `NotImplemented` -- `NotSupported` means the receiver knows the action but explicitly declines it ```json [4, "msg-002", "NotSupported", "SetChargingProfile is not supported by this charge point", {"supportedProfiles": ["Core", "FirmwareManagement"]}] ``` ### InternalError **Description:** An internal error occurred in the receiver that prevented processing the request. **Common Causes:** - Database connection failure on the CPMS - Out-of-memory condition on the charge point - Unhandled exception in the message processing logic - Downstream service unavailable (payment gateway, authorization service) - File system full on the charge point (preventing log or cache writes) **How to Fix:** - Check server/charger logs for the underlying exception or error - Monitor system resources (CPU, memory, disk, database connections) - Implement retry logic with exponential backoff on the calling side - Ensure all downstream dependencies have health checks and circuit breakers - This is a catch-all for server-side failures, so root cause analysis requires log inspection ```json [4, "msg-003", "InternalError", "Database connection pool exhausted", {"timestamp": "2025-02-08T14:30:00Z"}] ``` ### ProtocolError **Description:** The payload does not conform to the OCPP protocol specification. **Common Causes:** - Sending a CALLRESULT with the wrong payload structure for the action - Message ID format violations - Sending a response to a message ID that was never sent - Incorrect message type identifier (e.g., using `2` instead of `3` for a response) - Violating the OCPP requirement that only one CALL can be pending per direction **How to Fix:** - Validate all messages against the OCPP JSON schema before sending - Ensure message IDs are correctly tracked and matched between CALL and CALLRESULT/CALLERROR - Verify that your implementation does not send a new CALL before receiving the response to the previous one - Use a protocol-level message validator in your development environment ```json [4, "msg-004", "ProtocolError", "Received CALLRESULT for unknown messageId", {"receivedMessageId": "unknown-123"}] ``` ### SecurityError **Description:** A security-related issue prevented processing the request. **Common Causes:** - Invalid or expired TLS client certificate - HTTP Basic Auth credentials rejected - Charge point identity does not match the certificate's Common Name - Attempting to perform an action that requires higher security profile authorization - Tampered message detected (in implementations using message signing) **How to Fix:** - Verify TLS certificate validity, chain completeness, and expiration dates - Confirm HTTP Basic Auth credentials match the CPMS configuration - Ensure the charge point's identity string matches across all security layers - Check that the security profile configured on the charger matches the CPMS expectations - Review certificate provisioning and rotation processes ```json [4, "msg-005", "SecurityError", "Client certificate CN does not match charge point identity", {"expected": "CP001", "received": "CP002"}] ``` ### FormationViolation **Description:** The payload is syntactically incorrect -- it is not valid JSON, or the JSON structure does not match the expected message format. **Common Causes:** - Malformed JSON (missing brackets, trailing commas, unescaped characters) - Sending a string where the protocol expects a JSON array - Incorrect encoding (the payload must be UTF-8) - Truncated messages due to WebSocket framing issues - Buffer overflow causing partial message transmission **How to Fix:** - Validate JSON syntax before sending any OCPP message - Ensure your WebSocket library correctly handles message framing and does not split messages - Use a JSON linter in your CI/CD pipeline to catch formation errors in test payloads - Check character encoding settings on both sides ```json [4, "msg-006", "FormationViolation", "Payload is not valid JSON", {"receivedPayload": "{malformed..."}] ``` ### PropertyConstraintViolation **Description:** A property value in the payload violates a defined constraint (e.g., string length, numeric range, enum value). **Common Causes:** - `idTag` exceeding the 20-character maximum length defined in the [OCPP 1.6 specification](https://openchargealliance.org/protocols/open-charge-point-protocol/) - Negative value for `meterValue` or `transactionId` - Enum value not in the allowed set (e.g., sending "Active" instead of "Charging" for ChargePointStatus) - Timestamp not in ISO 8601 format - String value exceeding `maxLength` defined in the OCPP JSON schema **How to Fix:** - Validate all property values against the OCPP JSON schema constraints before sending - Pay particular attention to string length limits, which vary by field - Use the exact enum values specified in the OCPP specification (case-sensitive) - Ensure numeric values fall within the defined ranges ```json [4, "msg-007", "PropertyConstraintViolation", "idTag exceeds maximum length of 20 characters", {"property": "idTag", "maxLength": 20, "actualLength": 25}] ``` ### OccurrenceConstraintViolation **Description:** A required property is missing from the payload, or a property that should appear only once appears multiple times. **Common Causes:** - Omitting required fields like `chargePointVendor` in `BootNotification` - Missing `connectorId` in `StatusNotification` - Omitting `idTag` in `StartTransaction` - Required nested objects not included (e.g., missing `chargingSchedule` in a `ChargingProfile`) **How to Fix:** - Cross-reference your message payloads against the OCPP specification for required vs optional fields - Implement schema validation that checks required field presence before sending - Be aware that required fields differ between OCPP 1.6 and 2.0.1 for the same action - Check for conditional requirements (fields that are required only when another field has a specific value) ```json [4, "msg-008", "OccurrenceConstraintViolation", "Required property 'chargePointVendor' is missing", {"action": "BootNotification", "missingProperty": "chargePointVendor"}] ``` ### TypeConstraintViolation **Description:** A property has the wrong data type (e.g., a string where an integer is expected). **Common Causes:** - Sending `connectorId` as a string `"1"` instead of integer `1` - Sending `meterValue` as a string instead of a number - Boolean values sent as strings (`"true"` instead of `true`) - Sending an integer where the schema expects a decimal number - Date/time values not formatted as strings **How to Fix:** - Ensure JSON serialization preserves correct types (a common issue in dynamically typed languages) - Validate payloads against the JSON schema with strict type checking - Be especially careful with languages that auto-convert between strings and numbers - Test with a schema validator that catches type mismatches ```json [4, "msg-009", "TypeConstraintViolation", "Property 'connectorId' must be integer, received string", {"property": "connectorId", "expectedType": "integer", "receivedType": "string"}] ``` ### GenericError **Description:** A catch-all error code for any error that does not fit the other categories. **Common Causes:** - Timeout waiting for a downstream system response - Rate limiting or throttling - Temporary resource contention - Implementation-specific errors that have no matching standard code - Edge cases not covered by the OCPP specification **How to Fix:** - Read the `errorDescription` carefully -- it is the primary source of information for GenericError - Check the `errorDetails` object for implementation-specific context - Contact the CPMS or charger vendor if the error description is unclear - Implement retry logic, as GenericError often indicates transient conditions ```json [4, "msg-010", "GenericError", "Request timed out waiting for authorization service", {"timeoutMs": 5000}] ``` ## Error Code Summary Table | Error Code | Severity | Retryable | Typical Source | |-----------|----------|-----------|---------------| | **NotImplemented** | High | No | Version mismatch, wrong action name | | **NotSupported** | Medium | No | Optional feature not available | | **InternalError** | High | Yes | Server-side failure | | **ProtocolError** | High | No | Message format violation | | **SecurityError** | High | No | Authentication/authorization failure | | **FormationViolation** | High | No | Invalid JSON syntax | | **PropertyConstraintViolation** | Medium | No | Invalid field value | | **OccurrenceConstraintViolation** | Medium | No | Missing required field | | **TypeConstraintViolation** | Medium | No | Wrong data type | | **GenericError** | Varies | Maybe | Catch-all for unclassified errors | ## How Do You Troubleshoot Common OCPP Errors? ### Charger Will Not Connect **Symptoms:** WebSocket connection fails or immediately closes after handshake. **Diagnostic Steps:** 1. Verify the CPMS WebSocket URL is correct, including the charge point identity in the path 2. Check that the OCPP subprotocol header is present and matches a version the CPMS supports 3. Confirm TLS certificates are valid if using WSS (check expiration, chain, and CN) 4. Ensure the CPMS is configured to accept the charge point's identity 5. Check firewall rules and load balancer configuration for WebSocket support 6. Verify that no other charge point is connected with the same identity ### Authorization Fails **Symptoms:** `Authorize` requests return `Invalid` or `Blocked` status, or trigger CALLERROR. **Diagnostic Steps:** 1. Verify the `idTag` is registered in the CPMS and is in `Accepted` status 2. Check `idTag` format and length (max 20 characters in OCPP 1.6) 3. Confirm the authorization cache (Local Auth List) is synchronized between charger and CPMS 4. Check if the parent `idTag` group is blocked or expired 5. Verify the authorization service is responsive (InternalError in the response indicates a backend failure) ### Transactions Stuck in Started State **Symptoms:** Transactions never receive a `StopTransaction` and remain open indefinitely. **Diagnostic Steps:** 1. Check if the charger disconnected during a transaction (WebSocket connection dropped) 2. Verify the charger is sending `StopTransaction` when the cable is unplugged or session times out 3. Look for `InternalError` responses to `StopTransaction` that may prevent the CPMS from processing the stop 4. Check for `transactionId` mismatches between `StartTransaction` response and subsequent `StopTransaction` 5. Implement transaction timeout logic on the CPMS side as a safety net ### Meter Values Missing or Incorrect **Symptoms:** Charging sessions show zero energy, or meter values have gaps or unrealistic values. **Diagnostic Steps:** 1. Verify `MeterValues` clock-aligned interval is configured on the charger 2. Check that the CPMS is correctly parsing the `sampledValue` array and its nested structure 3. Confirm `measurand` values match what you expect (Energy.Active.Import.Register for cumulative energy) 4. Check for timezone issues -- meter value timestamps should be in UTC 5. Verify that `MeterValues` messages are not being dropped due to WebSocket disconnections ## How Do You Debug OCPP Errors? ### WebSocket Inspection Use browser developer tools, `wscat`, or dedicated WebSocket clients to monitor raw OCPP messages. Capture the full message exchange including WebSocket handshake headers, subprotocol negotiation, and all CALL/CALLRESULT/CALLERROR frames. ### Message Logging Implement structured logging for every OCPP message with: - Timestamp (millisecond precision) - Direction (charger-to-CPMS or CPMS-to-charger) - Message type (CALL, CALLRESULT, CALLERROR) - Message ID - Action name - Full payload (redact sensitive fields like passwords) - Processing duration ### Timeout Analysis OCPP does not define a standard timeout for CALL responses, so the value is left to each implementation. Track response times for every message type to identify: - Slow actions that may indicate backend performance issues - Timeouts that cause the sender to assume failure and retry - Cascading timeouts from downstream service dependencies ## How Does OCPPLab Help Debug OCPP Errors? Reproducing OCPP errors with physical chargers is slow and limited. You cannot easily force a charger to send malformed JSON, trigger specific error codes, or reproduce timing-sensitive race conditions — which is why a dedicated [OCPP testing workflow](/blog/ocpp-testing-guide) matters. **OCPPLab** provides complete control over OCPP message flows for systematic error debugging: - **Full Message Inspection**: View every OCPP message with timestamps, raw JSON payloads, and decoded field values. Identify exactly where in a message exchange an error occurs. - **Error Injection**: Send specific CALLERROR responses to test how your CPMS handles each error code. Verify retry logic, fallback behavior, and error reporting. - **Malformed Message Testing**: Send messages with missing fields, wrong types, invalid JSON, or constraint violations to validate your CPMS error handling covers all edge cases. - **Scenario Replay**: Capture a problematic message sequence from production logs and replay it through OCPPLab to reproduce and diagnose the issue in a controlled environment. - **Concurrent Error Simulation**: Test how your CPMS behaves when multiple chargers simultaneously encounter errors, revealing race conditions and resource exhaustion issues. ## Frequently Asked Questions ### Are OCPP error codes the same in 1.6 and 2.0.1? The error codes themselves are identical between OCPP 1.6 and 2.0.1. Both versions use the same CALLERROR format and the same set of error code strings. However, 2.0.1 has additional actions and different payload schemas, so the specific constraint violations you encounter will differ. ### Should my CPMS retry after receiving a CALLERROR? It depends on the error code. `InternalError` and `GenericError` are often transient and worth retrying with exponential backoff. `NotImplemented`, `NotSupported`, `FormationViolation`, and constraint violations indicate permanent problems that retrying will not resolve. Always check the `errorDescription` for hints about whether the condition is temporary. ### How do I handle errors in production? Implement a layered approach: log every CALLERROR with full context, alert on elevated error rates, and build dashboards that track error codes by charger model and firmware version. Many production issues are firmware-specific, so correlating errors with charger metadata helps identify the root cause quickly. ### What happens if neither side sends a response? If a CALL receives no CALLRESULT or CALLERROR within the timeout period, the sender should consider the request failed. The OCPP specification does not define a specific timeout value, so it is left to each implementation. After a timeout, the sender may retry the request or close the connection and reconnect. ### Can I define custom error codes? No. The OCPP specification defines a fixed set of error codes, and both parties must use only these. If you need to communicate additional error context, use the `errorDescription` string and the `errorDetails` JSON object, which can contain any structured data you need. --- ## OCPP Security Profiles Explained: TLS & Certificates Source: https://ocpplab.com/blog/ocpp-security-profiles-explained OCPP 2.0.1 defines three mandatory security profiles. Learn how Profiles 1, 2, and 3 handle TLS, certificate management, and mutual TLS authentication. **Quick answer:** OCPP 2.0.1 defines three mandatory security profiles. **Profile 1** is HTTP Basic Auth over unencrypted `ws://` (only for isolated networks). **Profile 2** is HTTP Basic Auth over TLS `wss://` with server certificate validation — the practical minimum for production. **Profile 3** is mutual TLS (mTLS) where both the charger and CPMS authenticate with X.509 certificates — the strongest option, recommended for public infrastructure. OCPP 1.6 supports the same profile model (numbered 0–3) as an opt-in extension via the **Security Whitepaper edition 2**. Every EV charge point is a network-connected computer that processes payment data, controls high-voltage equipment, and communicates with backend systems over the public internet. A compromised charger is not a theoretical risk --- it is a physical safety hazard, a payment fraud vector, and a potential entry point into an operator's entire network. OCPP 2.0.1 introduced mandatory security profiles specifically because the previous generation of the protocol left security as an afterthought, and the industry paid for it. This guide covers the three OCPP 2.0.1 security profiles in detail: what each one provides, how they work at the protocol level, when to use each, and how to implement and test them correctly. > **Note on OCPP 1.6:** A similar profile-based security model was retroactively added to OCPP 1.6 through the **Security Whitepaper edition 2** (Profiles 0/1/2/3, plus certificate management, signed firmware, and `SecurityEventNotification`). The whitepaper is opt-in per deployment, so most of the installed 1.6 base still runs without it. OCPP 2.0.1's contribution is making the model **mandatory** and unifying the numbering — not inventing the profile concept itself. ## What Was the Security Problem in OCPP 1.6? The original [OCPP 1.6](/blog/what-is-ocpp) core specification treated security as optional. It mentioned TLS but did not mandate it, define authentication mechanisms, or provide any certificate management framework. The Security Whitepaper edition 2 later filled most of those gaps for 1.6 as an opt-in extension, but it was published years after 1.6 itself and is not present in every deployed charger. In practice, the core-only posture led to widespread vulnerabilities across production charging networks. ### What went wrong **Unencrypted WebSocket connections in production.** Independent security researchers have repeatedly documented OCPP 1.6 deployments running over unencrypted `ws://` rather than `wss://`. In 2021, [Pen Test Partners disclosed vulnerabilities](https://www.pentestpartners.com/security-blog/smart-car-chargers-plug-n-play-for-hackers/) (Pen Test Partners, "Smart car chargers. Plug-n-play for hackers?", 2021) across six EV charger brands — including chargers with no authentication and predictable device IDs affecting millions of devices. When `ws://` is used, every message --- including charger credentials, transaction data, and configuration commands --- travels in plaintext, and anyone on the same network segment can read and modify these messages. **No standardized authentication.** OCPP 1.6 does not define how a CPMS should verify that an incoming [WebSocket connection](/blog/ocpp-websocket-guide) actually comes from a legitimate charge point. Many implementations rely solely on the charger's serial number in the URL path (`/ocpp/CP001`), which is trivially spoofable. **No firmware signing.** When a CPMS pushes a firmware update to a charger over OCPP 1.6, there is no mechanism to verify the firmware's authenticity. An attacker who can intercept or modify the firmware URL can push arbitrary code to the charge point. **Man-in-the-middle exposure.** Without TLS, an attacker positioned between the charger and the CPMS can intercept messages, inject fraudulent transaction data, modify charging profiles, or issue remote commands to the charger --- including stopping or starting sessions, changing power limits, or resetting the device. ### Real-world risk scenarios These are not hypothetical. Publicly documented incidents and security research have demonstrated: - **Session hijacking**: Spoofing a charger identity to report phantom transactions or steal revenue from legitimate sessions. - **Free charging fraud**: Manipulating transaction messages to avoid billing. - **Charger bricking**: Pushing malicious firmware that renders charge points inoperable, requiring physical truck rolls to recover. - **Network lateral movement**: Using a compromised charge point as a pivot to access the operator's internal systems, including payment processing and customer databases. The Open Charge Alliance recognized these risks and made security a first-class concern in OCPP 2.0.1. ## What Are the OCPP 2.0.1 Security Profiles? OCPP 2.0.1 defines three security profiles that provide progressively stronger authentication and encryption. Every conformant implementation must support at least one profile, and the specification strongly recommends Profile 2 or 3 for any internet-facing deployment. The profile model is normative in the [OCPP 2.0.1 specification published by the Open Charge Alliance](https://openchargealliance.org/protocols/open-charge-point-protocol/), and the equivalent model for OCPP 1.6 lives in the [OCPP 1.6 Security Whitepaper edition 2](https://openchargealliance.org/protocols/open-charge-point-protocol/) (also from OCA). | | **Profile 1** | **Profile 2** | **Profile 3** | |---|---|---|---| | **Authentication** | HTTP Basic Auth | HTTP Basic Auth | Mutual TLS (client certificate) | | **Transport Encryption** | None (`ws://`) | TLS (`wss://`) | TLS (`wss://`) | | **Server Identity Verification** | None | Server certificate validated by charger | Server certificate validated by charger | | **Client Identity Verification** | Password in HTTP header | Password in HTTP header | Client certificate validated by server | | **Certificate Management** | Not applicable | Server certificate only | Server + client certificates | | **Protection Against MITM** | None | Yes (server authenticated) | Yes (both sides authenticated) | | **Recommended Use Case** | Isolated private networks | Standard production deployments | High-security and regulated environments | The profile is configured on the charge point via the `SecurityProfile` variable in the Security component, and the CPMS must be configured to accept connections at the corresponding security level. ## What Is Security Profile 1 (Basic Authentication)? Security Profile 1 provides the minimum level of identity verification: the charge point authenticates itself to the CPMS using HTTP Basic Authentication transmitted during the WebSocket handshake. No TLS encryption is used. ### How it works 1. The charge point initiates a WebSocket connection to the CPMS at a `ws://` endpoint. 2. The HTTP Upgrade request includes an `Authorization` header containing the Base64-encoded `chargePointId:password` string. 3. The CPMS decodes the credentials, validates them against its database, and either accepts the WebSocket upgrade or rejects it with HTTP 401. 4. All subsequent OCPP messages travel over the unencrypted WebSocket connection. ### Password management The charger's authentication password is configured via the `BasicAuthPassword` variable. OCPP 2.0.1 specifies that passwords must be at least 16 characters and should be rotated periodically. The CPMS can trigger a password change by sending a `SetVariables` request to update the `BasicAuthPassword`, after which the charger reconnects with the new credentials. ### When to use Profile 1 Profile 1 is appropriate only when: - The charger and CPMS communicate over a physically isolated private network (e.g., a dedicated VPN or private APN on a cellular connection). - No sensitive data traverses the connection, or the network itself provides encryption at a lower layer. - Regulatory requirements do not mandate transport-layer encryption. In every other scenario, Profile 1 is insufficient. The password travels in Base64 encoding (not encryption) and is visible to any network observer. Do not use Profile 1 over the public internet. ### Risks - All traffic is plaintext --- credentials, transaction data, and commands are fully exposed. - Susceptible to credential theft via packet capture. - No protection against man-in-the-middle attacks. - An attacker who captures the password can impersonate the charger indefinitely until the password is rotated. ## What Is Security Profile 2 (TLS with Server Certificate)? Security Profile 2 adds TLS encryption to the Basic Authentication mechanism. The charger verifies the CPMS server's identity via its TLS certificate, and all communication is encrypted. This is the recommended minimum for any production deployment. ### How it works 1. The charge point initiates a TLS handshake with the CPMS at a `wss://` endpoint. 2. The CPMS presents its server certificate. The charger validates the certificate against its trusted root certificate store (the `CACertificateStore` or a pre-provisioned root CA). 3. Once the TLS session is established, the charger sends the HTTP Upgrade request with the `Authorization` header containing Basic Auth credentials, just as in Profile 1 --- but now encrypted within the TLS tunnel. 4. The CPMS validates the credentials and accepts or rejects the connection. 5. All subsequent OCPP messages travel over the encrypted WebSocket connection. ### TLS configuration requirements OCPP 2.0.1 specifies concrete requirements for the TLS configuration: **Minimum TLS version**: TLS 1.2 is the minimum. TLS 1.3 is recommended where both sides support it. TLS 1.0 and 1.1 are explicitly prohibited. **Cipher suites**: The specification recommends cipher suites providing forward secrecy. Acceptable examples include: - `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256` - `TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384` - `TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256` - `TLS_AES_128_GCM_SHA256` (TLS 1.3) - `TLS_AES_256_GCM_SHA384` (TLS 1.3) Cipher suites without forward secrecy (e.g., RSA key exchange) or using CBC mode should be disabled. **Certificate requirements**: The server certificate must be a valid X.509v3 certificate. The charger validates the certificate chain up to a trusted root CA. The certificate's Common Name (CN) or Subject Alternative Name (SAN) must match the CPMS hostname. ### Certificate provisioning For Profile 2, you need to provision the charger with the root CA certificate that signed the CPMS server certificate. This can be done: - **At manufacturing**: Pre-load the charger with a set of trusted root CAs (similar to how browsers ship with trusted roots). - **During commissioning**: Install the root CA certificate via a local interface or initial unencrypted connection, then switch to Profile 2. - **Via OCPP**: Use the `InstallCertificate` message to push the root CA certificate to the charger (though this requires an already-established connection). ### When to use Profile 2 Profile 2 is appropriate for: - Standard production deployments over the public internet. - Environments where the CPMS identity must be verified but individual charger certificate management is operationally burdensome. - Deployments where HTTP Basic Auth provides sufficient client authentication for the threat model. Profile 2 protects against network eavesdropping and server impersonation. It does not protect against a stolen charger password being used from a different device --- the CPMS cannot distinguish between the real charger and an attacker using the same credentials from a different machine. ## What Is Security Profile 3 (Mutual TLS)? Security Profile 3 is the gold standard. Both the charger and the CPMS authenticate each other using X.509 certificates. No passwords are involved --- identity is proven cryptographically. ### How it works 1. The charge point initiates a TLS handshake with the CPMS at a `wss://` endpoint. 2. The CPMS presents its server certificate. The charger validates it against its trusted root CA store. 3. The CPMS requests the client certificate. The charger presents its own X.509 certificate. 4. The CPMS validates the charger's certificate against its trusted root CA store. If the certificate is valid and not revoked, the TLS handshake completes. 5. The WebSocket upgrade proceeds without an `Authorization` header --- the TLS client certificate has already authenticated the charger. 6. All communication is encrypted and both endpoints are cryptographically verified. ### Why mTLS is stronger With Profile 2, a stolen password can be used from any device. With Profile 3, the charger's private key never leaves the device. Even if an attacker captures network traffic, they cannot extract the private key from the TLS handshake. To impersonate a charger, an attacker would need physical access to extract the private key from the device's secure storage --- a significantly higher barrier. mTLS also eliminates the operational burden of password management. There are no passwords to rotate, no risk of weak passwords, and no credentials transmitted in HTTP headers. ### PKI requirements Profile 3 requires a functioning Public Key Infrastructure (PKI): **Certificate Authority (CA)**: You need a CA to issue certificates to both the CPMS and individual charge points. This can be: - A **private CA** operated by the CPO or CPMS vendor (most common for charge point certificates). - A **public CA** like [Let's Encrypt](https://letsencrypt.org/) or DigiCert for the CPMS server certificate. - A **managed PKI service** from a cloud provider (AWS Private CA, Azure Key Vault, Google Cloud CA Service). **Certificate lifecycle**: Each charge point needs its own unique certificate. This means provisioning certificates at manufacturing or commissioning, rotating them before expiry, and revoking them if a device is decommissioned or compromised. **Secure key storage**: The charger must store its private key in a secure element or trusted platform module (TPM) to prevent extraction. The specification recommends hardware-backed key storage. ### When to use Profile 3 Profile 3 is appropriate for: - High-security deployments in regulated industries (government facilities, military installations, critical infrastructure). - Networks where charger impersonation is a material threat. - Operators who have the infrastructure to manage a PKI and certificate lifecycle. - Deployments that require compliance with standards like [ISO 15118 Plug & Charge](/blog/iso-15118-plug-and-charge), which also relies on certificate-based authentication. The primary barrier to Profile 3 adoption is operational complexity. Managing certificates for thousands of charge points requires automation, monitoring for approaching expiry dates, and a revocation strategy. For many operators, Profile 2 provides sufficient security with significantly less operational overhead. ## How Does Certificate Management Work in OCPP 2.0.1? OCPP 2.0.1 includes dedicated messages for managing certificates on charge points over the OCPP connection itself. This is critical for Profile 2 and Profile 3 deployments where certificates need to be updated remotely. ### InstallCertificate The CPMS sends `InstallCertificate` to push a new certificate to the charge point. The message specifies the certificate type: - `CentralSystemRootCertificate` --- Root CA used to validate the CPMS server certificate. - `ManufacturerRootCertificate` --- Root CA used to validate firmware signing certificates. - `V2GRootCertificate` --- Root CA for [ISO 15118](https://www.iso.org/standard/55366.html) Vehicle-to-Grid communication. The charger validates the certificate format and stores it. If storage is full or the certificate is malformed, the charger responds with `Rejected`. ### GetInstalledCertificateIds The CPMS sends `GetInstalledCertificateIds` to query which certificates are currently installed on the charger. The response includes the certificate hash (issuer name hash, issuer key hash, serial number) for each installed certificate. This allows the CPMS to audit a charger's certificate store and determine if updates are needed. ### DeleteCertificate The CPMS sends `DeleteCertificate` to remove a specific certificate from the charge point, identified by its certificate hash data. This is used to revoke trust in a compromised CA or remove expired certificates. ### CertificateSigningRequest For Profile 3, when a charger needs a new client certificate (initial provisioning or renewal), it generates a key pair locally and sends a `SignCertificate` request containing the CSR (Certificate Signing Request). The CPMS forwards the CSR to the CA, obtains the signed certificate, and delivers it back to the charger via `CertificateSigned`. This ensures the private key is generated on the charger and never transmitted. ### Certificate rotation workflow A typical certificate renewal for Profile 3 follows this sequence: 1. The CPMS monitors certificate expiry dates (queried via `GetInstalledCertificateIds`). 2. Before expiry, the CPMS triggers the charger to generate a new CSR via `TriggerMessage` with `SignCertificate`. 3. The charger generates a new key pair and sends `SignCertificate` with the CSR. 4. The CPMS submits the CSR to the CA and receives the signed certificate. 5. The CPMS sends `CertificateSigned` with the new certificate. 6. The charger installs the new certificate and begins using it on the next TLS handshake. This entire workflow happens over the existing OCPP connection without physical access to the charger. ## How Do Signed Firmware Updates Work? OCPP 2.0.1 addresses the firmware tampering risk from OCPP 1.6 with cryptographic signature verification for firmware updates. ### How signed firmware works 1. The CPMS sends a `SignedUpdateFirmware` request containing the firmware download URL, the expected signing certificate, and the firmware signature. 2. The charger downloads the firmware from the specified URL. 3. Before installing, the charger verifies the firmware signature against the signing certificate. The signing certificate itself is validated against the `ManufacturerRootCertificate` installed on the charger. 4. If the signature is valid, the charger installs the firmware and reports `Installed` via `FirmwareStatusNotification`. 5. If verification fails, the charger rejects the update and reports `InvalidSignature`. ### Secure boot chain Signed firmware is most effective when combined with secure boot: 1. **Hardware root of trust**: The bootloader is stored in read-only memory and cannot be modified. 2. **Chain of trust**: The bootloader verifies the OS image signature before loading it. The OS verifies application firmware signatures before executing. 3. **Runtime integrity**: The charge point periodically verifies its own firmware integrity and reports anomalies. Together, signed firmware and secure boot ensure that only authorized code runs on the charge point, from power-on through normal operation. ## Implementation Recommendations ### Choosing the right profile **Start with Profile 2** for most deployments. It provides encrypted communication and server authentication with manageable operational complexity. The majority of production OCPP 2.0.1 networks run Profile 2. **Use Profile 3** when: - Your threat model specifically includes charger impersonation. - Regulatory requirements mandate mutual authentication. - You are deploying ISO 15118 Plug & Charge (which requires its own certificate infrastructure, making the incremental cost of mTLS lower). - You have or can build the PKI infrastructure to manage per-device certificates. **Avoid Profile 1** for internet-facing deployments. If you must use it, ensure the network provides encryption at a lower layer (IPsec VPN, private APN with encryption). ### TLS setup checklist For Profile 2 and 3 deployments: 1. **Obtain a server certificate** from a public CA for your CPMS endpoint. Use a SAN that matches your WebSocket URL hostname. 2. **Configure TLS 1.2 minimum** on your CPMS. Disable TLS 1.0, 1.1, and all weak cipher suites. 3. **Enable forward secrecy** by prioritizing ECDHE cipher suites. 4. **Provision chargers with the root CA certificate** that signs your server certificate. For public CAs, most charger firmware includes standard root stores. 5. **Implement OCSP stapling** or CRL checking on the CPMS to enable certificate revocation validation. 6. **Monitor certificate expiry** and automate renewal. A single expired certificate can take down connectivity for your entire fleet. ### Certificate authority options | Approach | Pros | Cons | Best for | |----------|------|------|----------| | **Public CA** (Let's Encrypt, DigiCert) | Trusted by default, automated renewal (ACME), no infrastructure to run | Cannot issue client certificates for charge points (typically), cost per certificate at scale | CPMS server certificates | | **Private CA** (self-hosted, e.g., step-ca, EJBCA) | Full control, no per-certificate cost, can issue client certificates | Requires operational expertise, must distribute root CA to all chargers | Charge point client certificates for Profile 3 | | **Managed PKI** (AWS Private CA, Azure Key Vault) | Managed infrastructure, API-driven, audit logging | Per-certificate cost, cloud vendor dependency | Organizations without PKI expertise | For most operators, a hybrid approach works well: public CA for the CPMS server certificate (Profile 2) and private or managed CA for charge point client certificates (Profile 3). ## How to Test OCPP Security Profiles Security configuration is one of the most common sources of interoperability issues in OCPP deployments. A charger that works perfectly on an unencrypted connection may fail silently when TLS is enabled due to certificate chain issues, cipher suite mismatches, or incorrect hostname validation. ### What to test **Profile 1 testing:** - Verify the charger sends correct Basic Auth credentials in the WebSocket upgrade request. - Test with incorrect passwords --- the CPMS should reject with HTTP 401. - Confirm password rotation works: update `BasicAuthPassword` via `SetVariables`, verify the charger reconnects with the new password. **Profile 2 testing:** - Verify TLS handshake completes successfully with a valid server certificate. - Test with an expired server certificate --- the charger should refuse to connect. - Test with a self-signed certificate not in the charger's trust store --- connection should fail. - Verify cipher suite negotiation uses forward-secrecy suites. - Test `InstallCertificate` for updating the root CA on the charger. - Confirm the charger validates the server certificate's hostname against the connection URL. **Profile 3 testing:** - Verify mutual TLS handshake with valid client and server certificates. - Test with a revoked client certificate --- the CPMS should reject the connection. - Test the full `SignCertificate` / `CertificateSigned` workflow for certificate provisioning. - Verify certificate rotation without connection downtime. - Test `GetInstalledCertificateIds` to audit the charger's certificate store. - Confirm `DeleteCertificate` correctly removes certificates and the charger stops trusting the deleted CA. **Firmware signing testing:** - Send a `SignedUpdateFirmware` with a valid signature --- firmware should install. - Send a `SignedUpdateFirmware` with a tampered signature --- charger should reject with `InvalidSignature`. - Test with an expired signing certificate. ### Testing with OCPPLab [OCPPLab](/) provides an OCPP emulator that supports all three security profiles, allowing you to test your CPMS or charge point firmware against each profile configuration without deploying physical hardware. You can simulate TLS connections, certificate exchanges, and the full certificate lifecycle management workflow, catching configuration issues before they reach production. For a broader overview of OCPP testing strategies and tools, see our [OCPP testing guide](/blog/ocpp-testing-guide). ## Frequently Asked Questions ### Is OCPP 2.0.1 security mandatory? Yes. Every OCPP 2.0.1 implementation must support at least one security profile. The specification does not allow unprotected connections without a declared profile. However, the choice of which profile to implement is left to the deployer. In practice, conformance testing programs from the OCA verify security profile support. ### Can I upgrade from Profile 1 to Profile 2 or 3 remotely? Yes, but with caveats. You can push a root CA certificate via `InstallCertificate` over an existing Profile 1 connection, then change the `SecurityProfile` variable to 2 via `SetVariables`. The charger will reconnect using TLS. Upgrading to Profile 3 requires provisioning a client certificate, which involves the `SignCertificate` workflow. The initial Profile 1 connection is unencrypted, so this upgrade path should ideally happen on a trusted network during commissioning. ### What happens if a charger's certificate expires? If a Profile 3 charger's client certificate expires, the CPMS will reject the TLS handshake and the charger will be unable to connect. This is why proactive certificate monitoring and renewal is critical. Most implementations trigger renewal 30-60 days before expiry. If a certificate does expire, the charger typically requires a local intervention (physical access or local API) to install a new certificate or temporarily downgrade to Profile 2 with Basic Auth to re-establish connectivity. ### Do I need a separate PKI for OCPP and ISO 15118? They are technically separate trust chains. The OCPP PKI handles charger-to-CPMS authentication. The ISO 15118 PKI (V2G PKI) handles vehicle-to-charger authentication for Plug & Charge. However, some operators share infrastructure components (the same CA software, HSMs, and monitoring tools) between the two PKIs to reduce operational costs. The root certificates are distinct and installed via different certificate types in `InstallCertificate`. ### How does OCPP security relate to PCI DSS compliance? OCPP security profiles help meet PCI DSS requirements for encrypting cardholder data in transit, but they are not sufficient on their own. PCI DSS covers the entire payment processing chain, including data storage, access controls, and network segmentation. Profile 2 or 3 addresses the transport encryption requirement between the charger and CPMS. Additional measures are needed for end-to-end payment security. ### Can I use Let's Encrypt certificates for my CPMS? Yes, and many operators do. Let's Encrypt certificates are trusted by most charger firmware out of the box (since chargers typically ship with standard root CA stores). The 90-day validity requires automated renewal via ACME, which is straightforward for server-side certificates. Let's Encrypt does not issue client certificates, so you will need a separate CA for Profile 3 charge point certificates. ## Further Reading - [What is OCPP? The Complete Guide](/blog/what-is-ocpp) --- Foundational overview of the protocol, message types, and architecture. - [OCPP 1.6 vs 2.0.1: Complete Comparison](/blog/ocpp-1-6-vs-2-0-1) --- Detailed comparison including security, smart charging, and migration guidance. - [OCPP WebSocket Guide](/blog/ocpp-websocket-guide) --- Deep dive into WebSocket connection management, TLS configuration, and reconnection strategies. - [OCPP Testing Guide](/blog/ocpp-testing-guide) --- Comprehensive guide to testing OCPP implementations, including security profile validation. --- ## OCPP WebSocket Communication: A Developer's Guide Source: https://ocpplab.com/blog/ocpp-websocket-guide Learn how OCPP uses WebSocket for real-time EV charger communication: connection lifecycle, 3 JSON message types, heartbeat, reconnection, and WSS security. **Quick answer:** OCPP uses WebSocket as the transport layer for real-time, bidirectional messaging between EV chargers and the Central System (CPMS). A persistent connection lets either side send messages instantly without HTTP polling. Messages travel as JSON arrays (CALL, CALLRESULT, CALLERROR), with heartbeats, exponential-backoff reconnection, and TLS/WSS security profiles keeping connections reliable and secure. **OCPP WebSocket communication** is the transport layer that enables real-time, bidirectional messaging between EV chargers and their [Central System (CPMS)](/blog/what-is-CPMS). [OCPP](https://openchargealliance.org/protocols/ocpp-protocols/) is the open standard maintained by the Open Charge Alliance, and WebSocket is the channel it rides on. Unlike traditional REST APIs where the client polls for updates, WebSocket maintains a persistent connection — allowing either side to send messages at any time without the overhead of repeated HTTP handshakes. Understanding how OCPP uses WebSocket is essential for every developer building or integrating with EV charging infrastructure. Most OCPP bugs in production trace back to WebSocket-level issues: connection drops, message ordering problems, or security misconfigurations. ## Why Does OCPP Use WebSocket? OCPP chose WebSocket over alternatives for specific technical reasons: - **Bidirectional**: Both the charger and CPMS can initiate messages. The CPMS needs to send commands (RemoteStart, Reset) to chargers without the charger polling for them - **Persistent**: A single TCP connection stays open for hours or days, eliminating reconnection overhead - **Low latency**: Messages arrive in milliseconds, critical for real-time operations like smart charging profile updates - **Firewall friendly**: WebSocket upgrades from HTTP, traversing corporate firewalls and proxies that block raw TCP - **Lightweight**: Minimal framing overhead compared to HTTP request/response cycles OCPP 1.6 supports both WebSocket (JSON) and SOAP, while [OCPP 2.0.1](https://openchargealliance.org/protocols/open-charge-point-protocol/) uses WebSocket exclusively, having dropped SOAP support entirely. For a fuller breakdown of the differences, see [OCPP 1.6 vs 2.0.1](/blog/ocpp-1-6-vs-2-0-1). ## How Does the WebSocket Connection Lifecycle Work? ### 1. WebSocket Handshake The charge point initiates a WebSocket connection to the CPMS, following the upgrade handshake defined in [RFC 6455](https://datatracker.ietf.org/doc/html/rfc6455). The URL follows a specific pattern: ``` ws://CPMS.example.com/ocpp/CP001 wss://CPMS.example.com/ocpp/CP001 ``` The path typically includes the charge point identity (`CP001`). The CPMS uses this to identify which charger is connecting. The HTTP upgrade request includes OCPP-specific subprotocols: ``` GET /ocpp/CP001 HTTP/1.1 Host: CPMS.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Protocol: ocpp1.6, ocpp2.0.1 Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== ``` The CPMS responds with the selected subprotocol: ``` HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Protocol: ocpp1.6 ``` ### 2. BootNotification Immediately after the WebSocket connection is established, the charge point sends a `BootNotification` message: ```json [2, "19223201", "BootNotification", { "chargePointVendor": "EVManufacturer", "chargePointModel": "FastCharger-50", "chargePointSerialNumber": "SN-001234", "firmwareVersion": "3.2.1" }] ``` The CPMS responds with the registration status and heartbeat interval: ```json [3, "19223201", { "status": "Accepted", "currentTime": "2025-02-13T10:00:00.000Z", "interval": 300 }] ``` ### 3. Normal Operation Once registered, the charge point and CPMS exchange messages for charging operations, status updates, and remote commands. The connection remains open indefinitely. ### 4. Disconnection and Reconnection When the connection drops (network failure, CPMS restart, charger power cycle), the charge point is responsible for reconnecting. The CPMS must restore the charger's state from the last known information. ## OCPP JSON Message Format OCPP defines three message types, all transmitted as JSON arrays over WebSocket. For the full catalog of actions carried inside these envelopes, see the [OCPP message types reference](/blog/ocpp-message-types-complete-reference): ### CALL (Message Type 2) A request message sent by either party. Format: ```json [2, "uniqueMessageId", "ActionName", {payload}] ``` **Example — Charger sends StatusNotification:** ```json [2, "msg-4501", "StatusNotification", { "connectorId": 1, "errorCode": "NoError", "status": "Charging", "timestamp": "2025-02-13T10:15:00.000Z" }] ``` **Example — CPMS sends RemoteStartTransaction:** ```json [2, "cmd-7890", "RemoteStartTransaction", { "connectorId": 1, "idTag": "RFID-ABC123" }] ``` ### CALLRESULT (Message Type 3) A successful response to a CALL. The message ID must match the original CALL: ```json [3, "uniqueMessageId", {payload}] ``` **Example — CPMS responds to StatusNotification:** ```json [3, "msg-4501", {}] ``` **Example — Charger responds to RemoteStartTransaction:** ```json [3, "cmd-7890", { "status": "Accepted" }] ``` ### CALLERROR (Message Type 4) An error response to a CALL. Used when the message cannot be processed: ```json [4, "uniqueMessageId", "errorCode", "errorDescription", {errorDetails}] ``` **Example — Unknown action error:** ```json [4, "msg-9999", "NotImplemented", "This action is not supported", {}] ``` ### Standard OCPP Error Codes These are the codes carried in the `errorCode` slot of a CALLERROR; for a complete walkthrough with troubleshooting tips, see the [OCPP error codes reference](/blog/ocpp-error-codes-reference). | Error Code | Meaning | |-----------|---------| | `NotImplemented` | Requested action is not known or supported | | `NotSupported` | Action is recognized but not supported | | `InternalError` | Internal error in the receiver | | `ProtocolError` | Payload does not conform to protocol | | `SecurityError` | Security issue (e.g., invalid certificate) | | `FormationViolation` | Payload is syntactically incorrect | | `PropertyConstraintViolation` | Property value violates constraints | | `OccurrenceConstraintViolation` | Required property is missing | | `TypeConstraintViolation` | Property has wrong type | | `GenericError` | Catch-all for other errors | ## How Does the Heartbeat Mechanism Work? The **Heartbeat** message serves two purposes: confirming the charge point is still connected, and synchronizing its clock with the CPMS. ```json [2, "hb-001", "Heartbeat", {}] ``` ```json [3, "hb-001", { "currentTime": "2025-02-13T10:05:00.000Z" }] ``` The heartbeat interval is set by the CPMS in the `BootNotification` response, and operators commonly configure it to anywhere from under a minute to several minutes depending on fleet size and tolerance for stale state. If the CPMS does not receive a heartbeat within the expected window, it should consider the charge point offline. **Important implementation details:** - Any OCPP message resets the heartbeat timer — if a charger sends `MeterValues`, it does not need to send a separate Heartbeat until the next interval - The CPMS should allow some tolerance (e.g., 2x the interval) before marking a charger offline, accounting for network jitter - Charge points should use the `currentTime` from the response to correct clock drift ## What Are the Best Reconnection Strategies? Network disconnections are inevitable. A robust OCPP implementation needs a reliable reconnection strategy. ### Exponential Backoff The recommended approach for charge point reconnection: ``` Attempt 1: Wait 1 second Attempt 2: Wait 2 seconds Attempt 3: Wait 4 seconds Attempt 4: Wait 8 seconds ... Maximum: Wait 300 seconds (5 minutes) ``` Adding random jitter (0-30% of the wait time) prevents the "thundering herd" problem — where hundreds of chargers reconnect simultaneously after a CPMS restart. ### CPMS-Side Reconnection Handling When a charge point reconnects, the CPMS must: 1. Accept the new WebSocket connection 2. Process the `BootNotification` (may return `Accepted` or `Pending`) 3. Request current status via `TriggerMessage` for `StatusNotification` 4. Reconcile any transactions that were active during disconnection 5. Re-apply any pending charging profiles or configuration changes ### Connection Monitoring | Strategy | Implementation | Typical Interval | |----------|---------------|-----------------| | **OCPP Heartbeat** | Application-level ping | 60-300 seconds | | **WebSocket Ping/Pong** | Protocol-level keepalive | 30-60 seconds | | **TCP Keepalive** | OS-level connection check | 60-120 seconds | | **Load Balancer Health Check** | Infrastructure-level | 10-30 seconds | Use multiple layers. WebSocket Ping/Pong detects dead connections faster than OCPP Heartbeat, while TCP Keepalive catches cases where both endpoints think the connection is alive but an intermediate device has dropped it. ## How Do TLS and WSS Secure OCPP? Production OCPP deployments must use encrypted WebSocket connections (WSS — WebSocket Secure): ### OCPP Security Profiles OCPP 2.0.1 defines three mandatory security profiles. The numbering below matches the **OCPP 2.0.1 specification**. For a deeper treatment, see [OCPP security profiles explained](/blog/ocpp-security-profiles-explained). | Profile | Authentication | Encryption | Required by OCPP 2.0.1? | |---------|---------------|-----------|-------------| | **Profile 1** | HTTP Basic Auth | None — unencrypted (ws://) | Yes (at minimum) | | **Profile 2** | HTTP Basic Auth | TLS with server certificate (wss://) | Optional, recommended | | **Profile 3** | TLS client certificate (mutual auth) | TLS with client + server certificates (wss://) | Optional, strongest | > **OCPP 1.6 uses different numbering.** The OCPP 1.6 Security Whitepaper edition 2 defines Profiles **0–3**, where 1.6 Profile 0 ≈ 2.0.1 Profile 1 (ws:// + Basic Auth), 1.6 Profile 1 ≈ 2.0.1 Profile 2 (wss:// + Basic Auth), and 1.6 Profile 2 ≈ 2.0.1 Profile 3 (mTLS). 1.6 Profile 3 adds a signed Basic Auth token on top of mTLS. Plain-core 1.6 deployments without the whitepaper extension use ws:// with no authentication. ### TLS Implementation Checklist - Use TLS 1.2 or higher (TLS 1.3 preferred) - Validate server certificates on the charge point side - For Profile 3, manage client certificate provisioning and rotation - Pin certificates or use a dedicated CA for your charging network - Configure cipher suites to exclude weak algorithms (no RC4, no 3DES) - Handle certificate expiration gracefully with automated renewal ## How Do You Debug OCPP WebSocket Issues? ### Common Problems and Solutions **Connection refused**: The CPMS is not listening on the expected port or the charge point URL path is incorrect. Verify the WebSocket endpoint URL and that the subprotocol header matches. **Connection drops after 60 seconds**: A load balancer or proxy is closing idle connections. Ensure WebSocket Ping/Pong frames are being sent, or configure the infrastructure to allow long-lived connections. **Messages not received**: Check that both sides handle WebSocket fragmentation correctly. Some OCPP libraries buffer incomplete frames, and large messages (like firmware update notifications) may be split across multiple WebSocket frames. **Authentication failures**: Verify that HTTP Basic Auth credentials or TLS client certificates are correctly configured. Check certificate chain completeness — intermediate CA certificates are a frequent omission. **Message ordering issues**: OCPP requires that a CALL is answered before the next CALL is sent in the same direction. However, both the charger and CPMS can each have one outstanding CALL simultaneously — one in each direction. Sending a second CALL in the same direction before receiving a response to the first causes undefined behavior. ## Testing WebSocket Communication with OCPPLab Debugging WebSocket issues with physical chargers is time-consuming — you cannot easily inspect what the charger is sending, inject specific errors, or reproduce timing-sensitive bugs. **OCPPLab** provides full visibility into OCPP WebSocket communication: - **Message Inspector**: View every WebSocket frame with exact timestamps, including Ping/Pong - **Connection Simulation**: Test reconnection scenarios, slow networks, and connection drops - **Error Injection**: Send malformed JSON, unknown actions, or out-of-sequence messages to test CPMS error handling - **Security Profile Testing**: Validate all OCPP security profiles including TLS client certificate authentication - **Multi-Connection Load**: Open hundreds of simultaneous WebSocket connections to stress-test your CPMS Whether you are debugging a single charger's connection issue or validating that your CPMS handles 5,000 concurrent WebSocket connections, OCPPLab gives you the control and visibility that physical hardware cannot. ## Frequently Asked Questions ### Can OCPP work over HTTP instead of WebSocket? OCPP 1.6 also has a SOAP variant (OCPP 1.6S), but it is legacy and rarely used in new deployments. OCPP 2.0.1 requires WebSocket exclusively. WebSocket is strongly recommended for all new implementations because it enables server-initiated messages (which HTTP cannot do without polling). ### How many WebSocket connections can a CPMS handle? This depends entirely on the CPMS architecture. A well-optimized CPMS on modern infrastructure can comfortably handle tens of thousands of concurrent WebSocket connections, and far more with horizontal scaling. The bottleneck is typically database writes (MeterValues), not the WebSocket connections themselves. ### What happens to active transactions when WebSocket disconnects? The charge point continues charging locally. Transaction data (MeterValues) is typically queued and sent after reconnection. The CPMS should detect the disconnection and await reconnection, then reconcile any missed data. OCPP 2.0.1 handles this more gracefully than 1.6 with its improved transaction model. ### Should I use a WebSocket library or implement the protocol myself? Always use an established WebSocket library. Implementing the WebSocket protocol from scratch introduces unnecessary risk. For OCPP specifically, use an OCPP library that handles message routing, ID generation, and timeout management on top of the WebSocket layer. ### How do I handle WebSocket connections behind a load balancer? Use sticky sessions (session affinity) to ensure a charge point always connects to the same CPMS instance, or implement a shared session store. The load balancer must support WebSocket upgrade and long-lived connections. Configure appropriate idle timeout values to prevent premature disconnection. --- ## How to Implement OCPI Roaming: A Complete Guide Source: https://ocpplab.com/blog/how-to-implement-ocpi-roaming Implement OCPI 2.1.1 roaming for your EV charging network. A step-by-step guide to all 7 modules, credentials, hub integration, and testing for CPOs and eMSPs. **Quick answer:** To implement OCPI roaming, define your role (CPO, eMSP, or both), choose OCPI 2.1.1, and pick a roaming hub or direct P2P. Build version discovery and credential exchange first, then Locations, Tokens, Sessions, CDRs, and Tariffs, and connect through a hub like GIREVE or Hubject. Expect a basic build to take several weeks. Implementing OCPI roaming is one of the most impactful things you can do for your EV charging business. It connects your network to thousands of chargers (if you are an eMSP) or thousands of drivers (if you are a CPO). But the protocol documentation is dense, the edge cases are numerous, and the testing options are limited. This guide walks you through the full OCPI 2.1.1 implementation process, step by step. In our experience, a basic implementation takes a small team several weeks. A production-grade implementation with hub certification, robust error handling, and real-time sync takes considerably longer—on the order of several months, depending on your existing infrastructure. We are going to cover every module you need, in the order you should build them. ## Before You Start Before writing a single line of code, you need to make three decisions. ### 1. Define Your Role: CPO, eMSP, or Both Your role determines which OCPI modules you implement and in which direction data flows. - **CPO (Charge Point Operator)**: You own and operate chargers. You push location data, receive authorization requests, send session updates, and generate CDRs. - **eMSP (e-Mobility Service Provider)**: You manage drivers and their payments. You push tokens, receive session data, receive CDRs, and display tariffs. - **Both**: Many companies operate as both CPO and eMSP. You will need to implement both sides of every module. If you are unsure about the distinction, read our breakdown of [CPO vs eMSP roles](/blog/cpo-vs-emsp-explained) before continuing. ### 2. Choose Your OCPI Version OCPI 2.1.1 is the recommended starting point. It has the broadest adoption across European roaming hubs, is well-documented in the [official OCPI specification](https://github.com/ocpi/ocpi) maintained by the [EVRoaming Foundation](https://evroaming.org/ocpi/), and covers all core roaming use cases. OCPI 2.2 and 2.2.1 add features like smart charging commands and improved tariff structures, but hub support varies. Start with 2.1.1, then upgrade modules incrementally. ### 3. Select a Roaming Hub or Direct P2P You have two connectivity options: - **Hub-based roaming** (GIREVE, Hubject, e-clearing.net): One integration gives you access to hundreds of partners. The hub handles message routing and often provides certification testing. This is the standard approach. - **Direct peer-to-peer**: You connect directly to each partner. More control, but you need to manage each connection individually. Only practical if you have a small number of partners. For most companies, hub-based roaming through [GIREVE](/blog/gireve-hub-integration) or Hubject is the right call. The rest of this guide assumes hub-based integration, though the module implementation is identical for P2P. ## Step 1: How Do You Implement Version Discovery? Every OCPI implementation starts with the `/versions` endpoint. This is the entry point that tells partners which OCPI versions you support and where to find each module. Your `/versions` endpoint returns a list of supported versions: ```json { "status_code": 1000, "data": [ { "version": "2.1.1", "url": "https://your-platform.com/ocpi/2.1.1" } ] } ``` When a partner hits the version-specific URL, they get the list of module endpoints: ```json { "status_code": 1000, "data": { "version": "2.1.1", "endpoints": [ { "identifier": "credentials", "url": "https://your-platform.com/ocpi/2.1.1/credentials" }, { "identifier": "locations", "url": "https://your-platform.com/ocpi/2.1.1/locations" }, { "identifier": "tokens", "url": "https://your-platform.com/ocpi/2.1.1/tokens" }, { "identifier": "sessions", "url": "https://your-platform.com/ocpi/2.1.1/sessions" }, { "identifier": "cdrs", "url": "https://your-platform.com/ocpi/2.1.1/cdrs" }, { "identifier": "tariffs", "url": "https://your-platform.com/ocpi/2.1.1/tariffs" } ] } } ``` Implementation notes: - Use HTTPS. No exceptions. - All responses follow the same envelope: `status_code`, `data`, `timestamp`, and optionally `status_message`. - The `status_code` 1000 means success. Anything in the 2xxx or 3xxx range indicates an error. This endpoint is trivial to build, but get it right. Every partner interaction begins here. ## Step 2: How Does Credential Exchange Work? The credential exchange is the OCPI handshake. It establishes mutual trust between two parties by exchanging authentication tokens. Here is the flow: 1. **Party A** receives an initial token (TOKEN_A) out-of-band, typically through a hub portal or direct email. 2. **Party A** uses TOKEN_A to call Party B's `/versions` endpoint, discovering the credentials module URL. 3. **Party A** sends a `POST /credentials` request to Party B, including Party A's own credentials (its URL and a new token for Party B to use). 4. **Party B** validates TOKEN_A, stores Party A's credentials, and responds with Party B's credentials (including TOKEN_B). 5. **From this point forward**, Party A uses TOKEN_B to authenticate requests to Party B, and Party B uses the token Party A provided to authenticate requests to Party A. The POST body looks like this (OCPI 2.1.1 — note `country_code` is the alpha-3 ISO 3166-1 code; OCPI 2.2.1 uses alpha-2): ```json { "url": "https://party-a.com/ocpi/versions", "token": "party-a-token-for-party-b-to-use", "party_id": "PAR", "country_code": "FRA", "business_details": { "name": "Party A" } } ``` Critical implementation details: - **Store both tokens securely.** These are bearer tokens used for all subsequent API calls. - **TOKEN_A is single-use.** After the credential exchange completes, TOKEN_A should be invalidated. Only the newly exchanged tokens are valid. - **Support `PUT /credentials`** for token rotation. Partners will periodically update their tokens, and your system must handle this without downtime. - **Validate the token on every request.** Check the Authorization header against your stored tokens. Return a 401 if the token does not match. If you are integrating through a hub like GIREVE, the hub manages the initial token distribution and may handle parts of the credential exchange on your behalf. But you still need to implement the credentials module. ## Step 3: How Do You Implement the Locations Module (CPO)? If you are a CPO, the Locations module is your most important implementation. It publishes your charger infrastructure to the roaming network. OCPI models charging infrastructure as a three-level hierarchy: - **Location**: A physical site (e.g., a parking garage, a highway rest stop). Contains address, coordinates, opening hours, and facilities. - **EVSE**: An Electric Vehicle Supply Equipment unit at that location. Each EVSE has a unique `evse_uid` and a status (`AVAILABLE`, `BLOCKED`, `CHARGING`, `INOPERATIVE`, `OUTOFORDER`, `PLANNED`, `REMOVED`, `RESERVED`, `UNKNOWN`). - **Connector**: A physical plug on an EVSE. Defined by connector type (Type 2, CCS, CHAdeMO), power type (AC/DC), and max power. A typical location object: ```json { "id": "LOC001", "type": "ON_STREET", "name": "Main Street Charging Hub", "address": "123 Main Street", "city": "Paris", "country": "FRA", "coordinates": { "latitude": "48.8566", "longitude": "2.3522" }, "evses": [ { "uid": "EVSE001", "status": "AVAILABLE", "connectors": [ { "id": "1", "standard": "IEC_62196_T2", "format": "SOCKET", "power_type": "AC_3_PHASE", "max_voltage": 400, "max_amperage": 32 } ] } ], "last_updated": "2025-03-16T10:30:00Z" } ``` You need to support two data flow patterns: - **Pull (GET)**: Partners can fetch your full location list via pagination. Implement `GET /locations` with `offset` and `limit` query parameters, and support `date_from`/`date_to` filtering so partners can pull only recent changes. - **Push (PUT/PATCH)**: For real-time updates, push changes to connected partners or the hub. When an EVSE status changes from AVAILABLE to CHARGING, send a `PATCH` to the partner's receiver endpoint immediately. Real-time status updates are critical. Drivers rely on up-to-date availability information. If your status updates lag by more than a few seconds, the user experience degrades rapidly, with drivers arriving at chargers that show as available but are actually in use. ## Step 4: How Do You Implement the Tokens Module (eMSP)? If you are an eMSP, the Tokens module lets CPOs authorize your drivers at their chargers. A token represents a driver's authorization credential, typically linked to an RFID card, an app account, or both. You push your tokens to connected CPOs so they can perform local authorization without calling back to your server for every charge session. A token object: ```json { "uid": "RFID-001234567890", "type": "RFID", "auth_id": "USER-12345", "issuer": "Your eMSP Name", "valid": true, "whitelist": "ALLOWED", "last_updated": "2025-03-16T08:00:00Z" } ``` The `whitelist` field controls authorization behavior. OCPI defines four values: - **ALWAYS**: The CPO must always authorize locally without contacting the eMSP. - **ALLOWED**: Local authorization is allowed, and the CPO may also call the eMSP for real-time verification when it wants to. - **ALLOWED_OFFLINE**: Local authorization is allowed only when the CPO cannot reach the eMSP (offline fallback). - **NEVER**: The CPO must always do a real-time authorization request to the eMSP — never authorize locally. (Note: to reject a token entirely, set the token's `valid` flag to `false` rather than using a `whitelist` value — there is no `NOT_ALLOWED` value in `WhitelistType`.) For real-time authorization (when `whitelist` is `NEVER` or when the CPO wants to double-check), the CPO sends a `POST /tokens/{token_uid}/authorize` request to the eMSP. Your eMSP must respond within a few seconds. Slow responses mean drivers waiting at chargers, which is unacceptable. Push token updates to CPOs whenever a token is created, modified, or revoked. A driver losing their RFID card should result in an immediate token invalidation pushed to all connected CPOs. ## Step 5: How Do You Implement the Sessions Module? The Sessions module tracks active charging sessions in real time. CPOs push session data to eMSPs so drivers can see their ongoing charge in their app. A session goes through these states: 1. **ACTIVE**: Charging is in progress. The CPO sends periodic updates with current energy delivered and cost. 2. **COMPLETED**: Charging finished. Final session data is sent. 3. **INVALID**: Something went wrong. The session is flagged for review. The CPO creates a session when charging starts and pushes updates to the eMSP via `PUT /sessions/{session_id}`. Updates should be sent frequently; the more often you push, the better the driver experience, at the cost of more traffic. Match your cadence to what your hub partner expects. A session object includes: ```json { "id": "SESSION-001", "start_datetime": "2025-03-16T10:00:00Z", "kwh": 15.5, "auth_id": "USER-12345", "location": { "...location reference..." }, "currency": "EUR", "total_cost": 8.25, "status": "ACTIVE", "last_updated": "2025-03-16T10:30:00Z" } ``` Key implementation points: - **Idempotency**: Use `PUT` semantics. If the eMSP receives the same session update twice, it should overwrite, not duplicate. - **Cost calculation**: The CPO calculates the running cost based on published tariffs. The eMSP displays this to the driver. - **Session references**: Link sessions to locations, EVSEs, and connectors so the eMSP can show context to the driver. ## Step 6: How Do You Implement the CDRs Module? Charge Detail Records (CDRs) are the billing backbone of OCPI roaming. After a session completes, the CPO generates a CDR and pushes it to the eMSP. A CDR is the final, immutable record of a charging session. It contains everything needed for settlement: ```json { "id": "CDR-001", "start_date_time": "2025-03-16T10:00:00Z", "stop_date_time": "2025-03-16T10:45:00Z", "auth_id": "USER-12345", "total_energy": 22.5, "total_time": 2700, "total_cost": 12.75, "currency": "EUR", "charging_periods": [ { "start_date_time": "2025-03-16T10:00:00Z", "dimensions": [ { "type": "ENERGY", "volume": 22.5 }, { "type": "TIME", "volume": 0.75 } ] } ], "last_updated": "2025-03-16T10:46:00Z" } ``` The CDR lifecycle: 1. CPO generates the CDR after the session ends. 2. CPO pushes the CDR to the eMSP via `POST /cdrs`. 3. The eMSP validates the CDR against the session data and published tariffs. 4. If accepted, the eMSP processes the charge to the driver and settles with the CPO according to their roaming agreement. CDRs are critical for revenue. Every field matters. Missing or incorrect data leads to billing disputes, which are expensive to resolve manually. Validate your CDR generation against multiple tariff scenarios before going live. ## Step 7: How Do You Implement the Tariffs Module? The Tariffs module lets CPOs publish their pricing so eMSPs can display costs to drivers before they start charging. OCPI tariffs support multiple price components: - **ENERGY**: Price per kWh of energy delivered. - **TIME**: Price per hour of charging time. - **FLAT**: A fixed fee per session. - **PARKING_TIME**: Price per hour after charging completes (to discourage blocking chargers). A tariff example: ```json { "id": "TARIFF-001", "currency": "EUR", "elements": [ { "price_components": [ { "type": "FLAT", "price": 1.00, "step_size": 1 }, { "type": "ENERGY", "price": 0.35, "step_size": 1 }, { "type": "PARKING_TIME", "price": 5.00, "step_size": 300 } ] } ], "last_updated": "2025-03-16T08:00:00Z" } ``` The `step_size` field defines billing granularity. A `step_size` of 1 for energy means billing per Wh. A `step_size` of 300 for parking time means billing in 5-minute blocks. Getting step_size wrong is one of the most common tariff bugs, so test your cost calculations thoroughly. Tariffs can include restrictions (time of day, min/max kWh, specific connector types) that determine when each tariff element applies. This complexity is where most implementations struggle. Start simple, with a flat energy tariff, then add complexity. ## Step 8: Hub Integration With your modules implemented, it is time to connect to a roaming hub. ### GIREVE [GIREVE](/blog/gireve-hub-integration) is the dominant European roaming hub for OCPI. Their integration process: 1. **Sign a roaming agreement** with GIREVE. 2. **Connect to their test environment** (IOP QA). Implement version discovery and credential exchange against their test endpoints. 3. **Pass certification tests.** GIREVE runs automated tests against each module. They test standard flows, edge cases, and error handling. 4. **Go live on production.** Once certified, GIREVE connects you to their partner network. GIREVE has specific requirements beyond the OCPI spec, such as mandatory fields, data quality checks, and response time limits. Read [GIREVE's integration documentation](https://www.gireve.com/) carefully. ### Hubject Hubject primarily uses [OICP](https://github.com/hubject/oicp) (their own protocol), but increasingly supports OCPI as well. If you are evaluating both, see our [comparison of OCPI vs OICP vs OCHP](/blog/ocpi-vs-oicp-vs-ochp). ### Hub-Specific Considerations - **Message routing**: Hubs add a routing layer. Your `country_code` and `party_id` are used to route messages to the right partner. - **Data quality**: Hubs enforce data quality standards. Incomplete location data or missing GPS coordinates will be rejected. - **Response times**: Hubs typically require responses within a short, defined window, so optimize your endpoints and check your hub's documented limits. - **Pagination**: Hubs pull large datasets. Your pagination implementation must handle thousands of records efficiently. ## How Do You Test Your OCPI Implementation? This is where most teams struggle. Testing OCPI properly requires a counterpart, a CPO to test your eMSP code and an eMSP to test your CPO code. Your testing options: - **Test against the hub's QA environment.** This is necessary but limited. Hub test environments often have restricted scenarios and slow feedback cycles. - **Test against a real partner.** Slow, requires coordination, and you risk exposing bugs in a semi-production setting. - **Build your own mock server.** Time-consuming to build and maintain. You end up spending as much time on the mock as on the real implementation. - **Use OCPPLab.** Our platform simulates both CPO and eMSP endpoints, letting you test every module and every edge case without waiting for a partner or hub. You can run through the full credential exchange, push locations, authorize tokens, create sessions, and generate CDRs, all against a simulated counterpart that validates your implementation against the OCPI spec. A solid testing strategy covers: - **Happy path**: Full flow from credential exchange through CDR generation. - **Error handling**: Invalid tokens, malformed requests, timeout scenarios. - **Edge cases**: Timezone boundaries in CDRs, tariff changes mid-session, concurrent session updates. - **Performance**: Pagination with thousands of locations, high-frequency status updates. ## What Are the Most Common OCPI Implementation Pitfalls? After working with dozens of OCPI implementations, these are the issues we see most frequently. **Timezone handling in CDRs.** OCPI requires UTC timestamps. But charger hardware often reports local time. If your conversion is wrong, CDR costs will be calculated against the wrong tariff period. Always store and transmit in UTC. Convert to local time only at the display layer. **Tariff calculation mismatches.** The CPO calculates costs. The eMSP verifies costs. If their tariff interpretations differ (usually because of `step_size` rounding), every CDR triggers a billing dispute. Test tariff calculations with the same test cases on both sides. **Stale location data.** If your EVSE status updates fail silently, drivers see outdated availability. Implement monitoring on your push mechanism. Alert when updates fail or when an EVSE has not reported a status change in an unusually long time. **Token caching gone wrong.** CPOs cache eMSP tokens for offline authorization. If your cache invalidation is broken, revoked tokens still authorize sessions. Implement cache TTLs and honor real-time token updates from eMSPs. **Pagination off-by-one errors.** OCPI pagination uses `offset` and `limit`. Off-by-one errors cause partners to miss records or fetch duplicates. Test with datasets of exactly `limit` size, `limit + 1`, and `limit - 1`. **Ignoring the `last_updated` field.** Every OCPI object has a `last_updated` timestamp. Partners use this for incremental sync. If you do not update this field when data changes, partners will miss updates. Make sure every data mutation updates `last_updated`. ## FAQ ### How long does a full OCPI implementation take? A basic implementation covering version discovery, credentials, locations, and sessions takes a small backend team several weeks. Adding CDRs, tariffs, token real-time authorization, and hub certification extends this to several months. The protocol itself is not complex, but edge cases, testing, and hub certification add significant time. ### Can I implement OCPI without connecting to a hub? Yes. OCPI supports direct peer-to-peer connections. You exchange credentials directly with each partner. This works if you have a small number of partners, but does not scale. Most companies start with hub integration. ### Which OCPI modules are mandatory? For OCPI 2.1.1, only the Credentials module is technically mandatory. But for practical roaming, you need Locations (CPO), Tokens (eMSP), Sessions, and CDRs at minimum. Tariffs are strongly recommended so eMSPs can display pricing to drivers. ### How does OCPI relate to OCPP? [OCPP](/blog/what-is-ocpp) is the protocol between a charger and its management system (CPO backend). [OCPI](/blog/what-is-ocpi) is the protocol between CPO backends and eMSP backends for roaming. They solve different problems but work together: OCPP gets data from the charger to the CPO, and OCPI shares that data with roaming partners. ### Do I need to support both pull and push for every module? In practice, yes. Pull (GET with pagination) is used for initial data sync and recovery. Push (PUT/PATCH/POST) is used for real-time updates. Hubs typically rely on pull for bulk data and push for real-time changes. Implement both from the start. ### What authentication does OCPI use? OCPI uses token-based authentication via the `Authorization` header with a `Token` prefix (e.g., `Authorization: Token abc123`). Tokens are exchanged during the credential handshake and can be rotated via `PUT /credentials`. There is no OAuth, no API keys, just bearer tokens exchanged through the protocol itself. ## Next Steps If you are starting your OCPI implementation, begin with version discovery and credential exchange. Get those working against a test counterpart before moving to the data modules. Build Locations or Tokens next (depending on your role), then Sessions, CDRs, and Tariffs. For a deeper understanding of the protocol itself, read our [introduction to OCPI](/blog/what-is-ocpi). If you are evaluating which roaming protocol to adopt, our [comparison of OCPI, OICP, and OCHP](/blog/ocpi-vs-oicp-vs-ochp) covers the tradeoffs. And when you are ready to test, use [OCPPLab](/) to validate your implementation against simulated CPO and eMSP endpoints before going live with real partners. --- ## CPO vs eMSP: Understanding EV Charging Roles Explained Source: https://ocpplab.com/blog/cpo-vs-emsp-explained CPO vs eMSP: the two core EV charging roles. Learn how they differ, their business models, and the 7-step OCPI flow that connects chargers to EV drivers. **Quick answer:** A CPO (Charge Point Operator) owns, installs, and operates physical EV charging stations and their CPMS backend, while an eMSP (e-Mobility Service Provider) is the customer-facing layer giving drivers apps, authentication, billing, and roaming access. They connect through the OCPI protocol, and a single company can act as both. The EV charging ecosystem has two fundamental roles: **CPO (Charge Point Operator)** and **eMSP (e-Mobility Service Provider)**. Understanding the difference is essential for anyone building, operating, or integrating with charging infrastructure. ## CPO: Charge Point Operator A **CPO** owns, installs, and operates physical EV charging stations. They are responsible for: - **Hardware**: Purchasing, installing, and maintaining chargers - **Network Operations**: Monitoring uptime, handling faults, scheduling maintenance - **Grid Connection**: Managing electrical infrastructure and grid integration - **CPMS Management**: Running the [CPMS backend](/blog/what-is-CPMS) that controls chargers via [OCPP](/blog/what-is-ocpp), the [Open Charge Alliance](https://openchargealliance.org/protocols/open-charge-point-protocol/) communication standard - **Location Management**: Securing sites, managing access, signage ### CPO Examples - **Fastned** (Netherlands) — Operates highway fast-charging stations - **IONITY** (Europe) — Joint venture operating ultra-fast chargers across Europe - **ChargePoint** (US) — Both CPO and eMSP, operating an extensive US charging network - **Allego** (Europe) — Pan-European charging network operator - **EVgo** (US) — Operates DC fast charging stations ## eMSP: e-Mobility Service Provider An **eMSP** provides EV drivers with access to charging stations. They are the customer-facing layer: - **Driver Apps**: Mobile applications for finding, starting, and paying for charging - **Authentication**: RFID cards, app-based tokens, [Plug & Charge](/blog/iso-15118-plug-and-charge) certificates ([ISO 15118-20](https://www.iso.org/standard/77845.html)) - **Billing**: Processing payments, subscriptions, and invoice generation - **Roaming**: Enabling access to multiple CPO networks via [OCPI](/blog/what-is-ocpi), the [EVRoaming Foundation](https://evroaming.org/ocpi/) standard - **Customer Support**: Handling driver inquiries and disputes ### eMSP Examples - **Plugsurfing** — Aggregates multiple charging networks into one app - **NewMotion (Shell Recharge)** — Provides roaming access across Europe - **Chargemap** — French eMSP with pan-European coverage - **Electromaps** — Spanish eMSP expanding across Southern Europe ## What Are the Key Differences Between CPO and eMSP? | Aspect | CPO | eMSP | |--------|-----|------| | **Core Asset** | Physical chargers | Customer relationships | | **Revenue Model** | Energy sales, site fees | Service fees, subscriptions | | **Technology** | CPMS + OCPP | Driver app + OCPI | | **Customer** | Site owners, grid operators | EV drivers | | **Key Metric** | Uptime, utilization rate | Active users, sessions | | **Capex** | High (hardware + installation) | Low (software-based) | ## How Do CPOs and eMSPs Work Together? The connection between CPOs and eMSPs happens via the **OCPI protocol**: 1. CPO publishes charger locations, availability, and pricing via OCPI 2. eMSP pulls this data and shows it to drivers in their app 3. Driver selects a charger and requests to start charging 4. eMSP sends authorization token to CPO via OCPI 5. CPO validates and starts the charging session via OCPP 6. After charging, CPO sends a CDR (Charge Detail Record) to eMSP 7. eMSP bills the driver, then settles with the CPO ## Can a Company Be Both CPO and eMSP? Yes — and many are. Companies like ChargePoint, Tesla, and Shell Recharge operate as both: - **As CPO**: They operate their own charging stations - **As eMSP**: They provide driver-facing apps and roaming access This vertical integration simplifies the user experience but can limit interoperability if not connected to roaming networks. ## How Do You Test CPO and eMSP Integrations? Building or integrating CPO/eMSP functionality requires testing: - **OCPP flows** (CPO side): Charger communication, authorization, [smart charging](/blog/smart-charging-explained) - **OCPI flows** (Roaming): Location sharing, session management, CDR exchange - **End-to-end scenarios**: Driver authenticates via eMSP app → CPO starts charging **OCPPLab** supports both OCPP and OCPI testing, letting you simulate the full charging ecosystem — from charger to CPMS to roaming hub — without any physical infrastructure. --- ## Smart Charging Explained: How EV Load Management Works Source: https://ocpplab.com/blog/smart-charging-explained Learn how smart charging controls EV power with OCPP charging profiles across 6 strategies—load balancing, peak shaving, demand response, ISO 15118, and V2G. **Quick answer:** Smart charging dynamically controls the power delivered to EVs based on grid capacity, energy prices, renewable availability, and driver needs. Using OCPP charging profiles, it orchestrates when and how fast vehicles charge, cutting peak demand substantially, lowering costs, preventing grid overload, and enabling load balancing, peak shaving, demand response, and vehicle-to-grid revenue. **Smart charging** is the ability to dynamically control the power delivered to electric vehicles based on real-time constraints such as grid capacity, energy prices, renewable availability, and driver preferences. Rather than every EV drawing maximum power the moment it plugs in, smart charging orchestrates when and how fast vehicles charge — reducing costs, preventing grid overload, and enabling new revenue streams. As EV adoption accelerates, smart charging is no longer optional. Without it, a parking garage with 50 Level 2 chargers each pulling 7.4 kW would need a 370 kW grid connection — equivalent to a small industrial facility. Smart charging can substantially reduce that peak demand, making large-scale EV charging deployable without massive electrical upgrades. ## How Does Smart Charging Work with OCPP? [OCPP](/blog/what-is-ocpp), maintained by the [Open Charge Alliance](https://openchargealliance.org/protocols/open-charge-point-protocol/), defines smart charging through **Charging Profiles** — structured instructions sent from the [CPMS](/blog/what-is-CPMS) to the charge point that specify power limits over time. ### OCPP 1.6 Smart Charging In [OCPP 1.6](/blog/ocpp-1-6-vs-2-0-1), smart charging uses the `SetChargingProfile` and `GetCompositeSchedule` messages: - **ChargingProfile**: Defines a power schedule with time-based periods - **ChargingProfilePurpose**: `ChargePointMaxProfile`, `TxDefaultProfile`, or `TxProfile` - **ChargingRateUnit**: Power limits expressed in Watts (W) or Amps (A) - **StackLevel**: Priority system for overlapping profiles (higher level wins) ### OCPP 2.0.1 Smart Charging OCPP 2.0.1 significantly enhances smart charging capabilities: - **Composite Schedules**: The CPMS can request the charge point to calculate the effective schedule from all active profiles - **Charging Needs**: The EV communicates its energy requirements to the CPMS via [ISO 15118](/blog/iso-15118-plug-and-charge) - **External Constraints**: The Charging Station reports external power limits to the CPMS via `NotifyChargingLimit`, while the CPMS applies grid constraints using `SetChargingProfile` with `ChargingStationExternalConstraints` purpose - **Cost-Based Charging**: Real-time energy prices influence charging schedules - **Priority-Based Stacking**: More granular control with separate profiles per EVSE and per transaction ## What Are the Main Load Balancing Strategies? Load balancing distributes available electrical capacity across multiple charge points. There are two primary approaches: ### Static Load Balancing A fixed power budget is divided equally (or according to preset rules) among connected EVs. The total never exceeds the site's electrical capacity. **Example**: A site with 100 kW capacity and 10 connected EVs allocates 10 kW per charger, regardless of whether some EVs are nearly full or just started. ### Dynamic Load Balancing Power allocation adjusts in real-time based on actual site consumption, EV battery state, driver priority, and departure time. **Example**: The same 100 kW site monitors building consumption in real-time. If the building uses only 40 kW, 60 kW is available for EV charging and distributed based on each vehicle's needs. ### Comparison of Load Balancing Strategies | Aspect | Static Load Balancing | Dynamic Load Balancing | |--------|----------------------|----------------------| | **Implementation** | Simple, rule-based | Complex, requires real-time data | | **Hardware Required** | Basic OCPP chargers | Smart meter + OCPP chargers + energy management system | | **Grid Efficiency** | Moderate (conservative limits) | High (uses full available capacity) | | **User Experience** | Predictable but slower | Optimized charging speeds | | **Cost** | Lower setup cost | Higher setup, lower operating cost | | **Best For** | Small sites (under 10 chargers) | Large sites, fleet depots, commercial buildings | | **OCPP Feature** | ChargePointMaxProfile | TxProfile with real-time updates | ## What Is Peak Shaving? **Peak shaving** reduces maximum power drawn from the grid during high-demand periods. This is critical because commercial electricity tariffs often include **demand charges** — fees based on your highest 15-minute power peak in a billing period. Smart charging achieves peak shaving by: 1. **Monitoring** real-time site power consumption via smart meters 2. **Predicting** upcoming peak periods using historical data and schedules 3. **Throttling** EV charging power when site consumption approaches the peak threshold 4. **Restoring** full charging power when demand drops A well-implemented peak shaving strategy can meaningfully reduce electricity costs for sites with significant EV charging load. ## What Is Demand Response? **Demand response** is when EV charging adjusts in response to [signals from the grid operator or energy market](https://www.ferc.gov/power-sales-and-markets/demand-response). Unlike peak shaving (which serves the site owner), demand response serves the broader electrical grid. Use cases include: - **Grid balancing**: Reducing EV charging when the grid is stressed - **Renewable integration**: Increasing charging when solar or wind generation is high - **Price response**: Shifting charging to low-price periods in real-time energy markets - **Frequency regulation**: Rapid power adjustments to stabilize grid frequency OCPP 2.0.1 supports demand response through external charging limit notifications and cost-based charging profiles. ## How Does ISO 15118 Enable Smart Charging? **[ISO 15118](https://www.iso.org/standard/55366.html)** is the communication protocol between the EV and the charger (not to be confused with OCPP, which is between the charger and the CPMS). It enables two transformative smart charging features: ### Plug and Charge The EV automatically authenticates and begins charging when plugged in — no app, no RFID card. Authentication happens via X.509 digital certificates exchanged between the EV and the charger. OCPP 2.0.1 integrates with ISO 15118 to relay these certificates to the CPMS. ### Charging Needs Communication Via ISO 15118, the EV can communicate: - Current battery state of charge (SoC) - Target SoC and departure time - Maximum acceptable charging power - Energy amount requested This information flows from the EV through the charger (via ISO 15118) to the CPMS (via OCPP 2.0.1), enabling truly optimized smart charging. ## What Is Vehicle-to-Grid (V2G)? **Vehicle-to-Grid (V2G)** enables EVs to feed stored energy back to the grid. Instead of being passive consumers, EVs become mobile batteries that can support grid stability. V2G requires: - **Bidirectional chargers**: Hardware capable of both AC/DC charging and discharging - **[ISO 15118-20](https://www.iso.org/standard/77845.html)**: The latest version of the vehicle-charger protocol with V2G support - **OCPP 2.0.1**: Backend communication for managing bidirectional energy flows - **Grid integration**: Agreements with utilities and grid operators ### V2G Use Cases - **Peak shaving**: Discharge EVs during peak demand, recharge overnight - **Frequency regulation**: Rapid charge/discharge cycles to stabilize grid frequency - **Renewable buffering**: Store excess solar during the day, discharge in the evening - **Emergency backup**: Use EV batteries as backup power for buildings ## Smart Charging Strategy Comparison | Strategy | Goal | Complexity | Savings Potential | OCPP Support | |----------|------|-----------|-------------------|--------------| | **Static Load Balancing** | Prevent overload | Low | Moderate (infrastructure) | 1.6 + 2.0.1 | | **Dynamic Load Balancing** | Optimize utilization | Medium | High (infrastructure) | 1.6 + 2.0.1 | | **Peak Shaving** | Reduce demand charges | Medium | Moderate (electricity) | 1.6 + 2.0.1 | | **Demand Response** | Grid flexibility | High | Revenue from grid services | 2.0.1 | | **Time-of-Use Optimization** | Shift to cheap hours | Low | Modest (electricity) | 1.6 + 2.0.1 | | **V2G** | Bidirectional energy | Very High | Revenue from energy trading | 2.0.1 | ## Testing Smart Charging Smart charging is one of the most complex areas of [OCPP implementation](/blog/ocpp-implementation-guide). A single miscalculation in a charging profile can overload a site's electrical infrastructure or leave EVs undercharged. **OCPPLab** lets you test smart charging scenarios without risking physical hardware: - Simulate multiple EVs with different battery sizes, SoC levels, and departure times - Send and validate charging profiles across OCPP 1.6 and 2.0.1 - Test composite schedule calculations with overlapping profiles - Verify load balancing behavior under various site consumption patterns - Simulate ISO 15118 charging needs communication via OCPP 2.0.1 - Validate peak shaving logic with configurable power thresholds Teams building smart charging features use OCPPLab to test hundreds of edge cases that would be impossible to reproduce with physical chargers — such as 50 EVs simultaneously requesting full power. ## Frequently Asked Questions ### What is the difference between smart charging and managed charging? They are often used interchangeably. "Smart charging" typically refers to the technical capability (OCPP profiles, load management), while "managed charging" is a broader term that includes utility programs and driver-facing features. ### Does smart charging damage EV batteries? No. Smart charging controls the power level within the EV's accepted range. In fact, slower charging through smart charging can extend battery life compared to always charging at maximum power. ### Do all OCPP chargers support smart charging? Most OCPP 1.6 chargers support basic charging profiles, but implementation quality varies. OCPP 2.0.1 chargers are required to support smart charging as part of core protocol compliance. Always verify smart charging support with your charger manufacturer. ### Can smart charging work without ISO 15118? Yes. OCPP-based smart charging works without ISO 15118 — the CPMS sends power limits to the charger based on site-level data. ISO 15118 adds vehicle-specific intelligence (like SoC and departure time) that makes smart charging more precise, but it is not a requirement. ### What hardware do I need for smart charging? At minimum, you need OCPP-capable chargers and a CPMS with smart charging logic. For dynamic load balancing, you also need a smart meter at the grid connection point. For V2G, you need bidirectional chargers and ISO 15118-20 compatible vehicles. --- ## ISO 15118 & Plug and Charge: EV Authentication Guide Source: https://ocpplab.com/blog/iso-15118-plug-and-charge ISO 15118 enables Plug and Charge: automatic EV authentication with no app or card. Learn how it works with OCPP 2.0.1, its 7-step flow, and how to test it. **Quick answer:** ISO 15118 is the communication standard between EVs and chargers that enables Plug and Charge — plug in and your EV automatically authenticates and starts charging with no app, RFID card, or credit card. It uses TLS encryption and X.509 certificates, requires OCPP 2.0.1 on the backend, and also enables Vehicle-to-Grid. **[ISO 15118](https://www.iso.org/standard/55366.html)** is the International Organization for Standardization's communication standard between electric vehicles and charging stations. It enables **Plug and Charge (PnC)** — the ability to simply plug in your EV and have it automatically authenticate and start charging, with no app, RFID card, or credit card needed. The [ISO 15118-20](https://www.iso.org/standard/77845.html) revision (2022) extends the standard with full bidirectional / V2G support. Think of it as the EV equivalent of tapping your phone to pay — except you just plug in the cable. ## How Does Plug and Charge Work? 1. **Driver plugs in** the charging cable 2. **Vehicle and charger** establish a TLS-secured communication channel 3. **Vehicle presents** its digital certificate (installed by the manufacturer or eMSP) 4. **Charger forwards** the certificate to the [CPMS](/blog/what-is-CPMS) for validation 5. **CPMS validates** the certificate chain and authorizes the session 6. **Charging begins** automatically — no user interaction needed 7. **Billing** is handled via the contract associated with the vehicle's certificate In practice the handshake completes in a few seconds, so the experience feels close to instant from plug-in to charging. ## How Does ISO 15118 Work With OCPP? **Core [OCPP 1.6](/protocols/ocpp-1-6)** does not support ISO 15118. It lacks the message types needed for vehicle-side certificate provisioning (no `Get15118EVCertificate`). The optional **OCPP 1.6 Security Whitepaper edition 2** does add `SignCertificate`, `CertificateSigned`, `InstallCertificate`, `DeleteCertificate`, and `GetInstalledCertificateIds` for CPMS-charger certificate management (see the OCA's [Using ISO 15118 Plug & Charge with OCPP 1.6](https://openchargealliance.org/ocpp-info-whitepapers/using-iso-15118-plug-charge-with-ocpp-1-6/) whitepaper and our [OCPP security profiles](/blog/ocpp-security-profiles-explained) guide), but it does not include the EV-contract-certificate flow that Plug & Charge requires. **[OCPP 2.0.1](/protocols/ocpp-2-0-1)** has [full ISO 15118 support](https://openchargealliance.org/protocols/open-charge-point-protocol/) including: - `Get15118EVCertificate` — Vehicle requests a new charging contract certificate (2.0.1-only) - `CertificateSigned` — CPMS installs certificates on the charger (also in 1.6 Security Whitepaper edition 2) - `SignCertificate` — Charger requests its own security certificate (also in 1.6 Security Whitepaper edition 2) - Certificate management for the entire PKI (Public Key Infrastructure) chain | Feature | OCPP 1.6 | OCPP 2.0.1 | |---------|----------|------------| | Plug and Charge | Not supported (no `Get15118EVCertificate`) | Full support | | CPMS-charger certificate management | Available via Security Whitepaper edition 2 (opt-in) | Complete PKI integration in core | | Vehicle Communication | Not available | ISO 15118-2 and 15118-20 | | Bidirectional Charging | Not supported | V2G ready | ## What Is Vehicle-to-Grid (V2G)? ISO 15118 also enables **Vehicle-to-Grid (V2G)** — the ability for EVs to send power back to the grid during peak demand. This requires: - Bidirectional chargers (DC) - ISO 15118-20 support (the latest revision) - Grid operator integration - OCPP 2.0.1 for backend communication V2G turns every parked EV into a potential grid battery, helping utilities manage peak loads through [smart charging](/blog/smart-charging-explained) and enabling EV owners to earn money by selling electricity back. ## Testing ISO 15118 with OCPPLab Testing Plug and Charge is complex because it involves: - Certificate chain validation (Root CA → Sub-CA → Leaf certificates) - TLS handshake between vehicle and charger - OCPP 2.0.1 certificate management messages - Multiple failure scenarios (expired certs, revoked certs, unknown CAs) **OCPPLab** simulates the complete ISO 15118 flow including certificate exchange, allowing you to test Plug and Charge without physical vehicles or chargers. ## Frequently Asked Questions ### Which EVs support Plug and Charge? A growing number of automakers — spanning both premium and mainstream brands — support Plug and Charge on select models, and the list continues to expand as ISO 15118 adoption widens. Check your specific vehicle and network for current support. ### Is Plug and Charge secure? Yes. ISO 15118 uses TLS encryption and PKI (Public Key Infrastructure) with X.509 certificates — the same security model used for HTTPS on the web. ### Do I need OCPP 2.0.1 for Plug and Charge? For the backend (CPMS) side, yes. OCPP 2.0.1 is required to manage certificates and process ISO 15118 authentication. The charger itself communicates with the vehicle via ISO 15118 directly. --- ## EV Charging Glossary: 50+ Terms Every Developer Should Know Source: https://ocpplab.com/blog/ev-charging-glossary A developer reference defining 50+ EV charging terms across OCPP, OCPI, CPMS, CPO, eMSP, ISO 15118, and smart charging, so you can ship integrations faster. **Quick answer:** This glossary defines 50+ EV charging terms developers need, spanning protocols like OCPP and OCPI, roles like CPO, CPMS, and eMSP, plus concepts like AC and DC charging, authorization, CDRs, smart charging, and ISO 15118 Plug and Charge. It's a quick reference whether you're building a CPMS, deploying chargers, or developing a driver app. The EV charging industry has its own vocabulary. Whether you're a developer building a [CPMS](/blog/what-is-CPMS), a [CPO](/blog/cpo-vs-emsp-explained) deploying chargers, or an eMSP building a driver app, this glossary covers every term you need to know. ## A ### AC Charging Charging an EV using alternating current. The vehicle's onboard charger converts AC to DC. AC delivers lower power than DC, which generally suits longer dwell times such as home, workplace, or overnight charging. Also called Level 1 (120V) or Level 2 (240V) charging in North America. ### AFIR (Alternative Fuels Infrastructure Regulation) EU regulation requiring member states to deploy public EV charging infrastructure along major highways. Mandates ad-hoc payment access at all public chargers. ### Authorization The process of verifying whether an EV driver is allowed to use a charging station. Methods include RFID cards, mobile apps, Plug and Charge ([ISO 15118](/blog/iso-15118-plug-and-charge)), and credit card terminals. ## B ### BootNotification The first OCPP message a charger sends when connecting to a CPMS. Contains the charger's vendor, model, serial number, and firmware version. The CPMS responds with an accepted/rejected status and a heartbeat interval. ## C ### CDR (Charge Detail Record) A record of a completed charging session used for billing. Contains start time, end time, energy delivered, costs, and authentication details. Exchanged between CPO and eMSP via [OCPI](/blog/what-is-ocpi). ### Connector The physical plug on a charging station. Common types: Type 1 (J1772), Type 2 (Mennekes), CCS1, CCS2, CHAdeMO, Tesla NACS. ### CPO (Charge Point Operator) The company that owns and operates physical EV charging stations. Responsible for hardware, maintenance, and network operations. ### CPMS (Charge Point Management System) Older term for CPMS. See CPMS. ### CPMS (Charging Station Management System) The backend software platform that manages a network of EV chargers via [OCPP](/blog/what-is-ocpp). Handles authorization, billing, monitoring, and remote operations. ## D ### DC Fast Charging Charging an EV using direct current, bypassing the vehicle's onboard charger. Delivers substantially higher power than AC, which can charge a battery in tens of minutes rather than hours, making it common at highway and rapid-charging sites. ### Demand Response Programs where charging is adjusted based on grid conditions. During peak demand, charging power is reduced. During surplus (e.g., high solar/wind production), charging is increased. ## E ### eMSP (e-Mobility Service Provider) A company that provides EV drivers with access to charging stations. Offers apps, RFID cards, and billing. Connects to CPOs via OCPI for roaming. ### EVSE (Electric Vehicle Supply Equipment) Technical term for an EV charging station. Includes the charger, connector, cable, and safety systems. ## G ### GIREVE A major EV charging roaming hub in Europe. Connects a large number of CPOs and eMSPs via OCPI, enabling cross-network charging access. ## H ### Heartbeat A periodic OCPP message sent by a charger to its CPMS to confirm the connection is alive. The interval is set by the CPMS in the BootNotification response. ### Hubject A global roaming platform for EV charging. Uses both OCPI and its proprietary [OICP protocol](https://github.com/hubject/oicp). Known for its Plug&Charge PKI infrastructure. ## I ### IdTag In OCPP 1.6, the identifier used to authorize a charging session. The [OCPP 1.6 specification](https://openchargealliance.org/protocols/open-charge-point-protocol/) defines it as a string of up to 20 characters, representing an RFID card UID, app token, or other identifier. ### ISO 15118 International standard for communication between EVs and chargers. Enables Plug and Charge (automatic authentication) and Vehicle-to-Grid (V2G). The bidirectional power transfer requirements are defined in [ISO 15118-20](https://www.iso.org/standard/77845.html). ## L ### Load Balancing Distributing available electrical capacity across multiple chargers to prevent circuit overload. Can be static (fixed limits) or dynamic (real-time adjustment based on actual consumption). ## M ### MeterValues OCPP message containing energy meter readings from a charger. Includes data like energy consumed (Wh), power (W), voltage (V), current (A), and state of charge (%). ## O ### OCA (Open Charge Alliance) The [organization that develops and maintains the OCPP protocol](https://openchargealliance.org/protocols/open-charge-point-protocol/). Members include charger manufacturers, CPMS vendors, and energy companies. ### OCPI (Open Charge Point Interface) [Open protocol for EV charging roaming](https://evroaming.org/ocpi/). Enables data exchange between CPOs and eMSPs for cross-network charging. Current version: 2.2.1. ### OCPP (Open Charge Point Protocol) Open standard for communication between EV chargers and CPMS backends. Uses WebSocket transport with JSON messages. Current versions: [1.6 and 2.0.1](/blog/ocpp-1-6-vs-2-0-1). ### OICP (Open InterCharge Protocol) Hubject's proprietary roaming protocol. Alternative to OCPI for connecting CPOs and eMSPs. ## P ### Peak Shaving Reducing power consumption during periods of high grid demand by lowering charging power or pausing sessions temporarily. ### Plug and Charge Automatic authentication when an EV is plugged into a charger. No app or RFID needed. Enabled by ISO 15118 and OCPP 2.0.1. ## R ### RemoteStartTransaction OCPP message sent from CPMS to charger instructing it to begin a charging session. Used when a driver starts charging via a mobile app. ### Roaming The ability for EV drivers to charge on any network using a single account or app. Enabled by OCPI or OICP protocols. ## S ### Smart Charging Optimizing EV charging based on grid capacity, energy prices, renewable energy availability, or user preferences. Managed via OCPP [charging profiles](/blog/smart-charging-explained). ### StatusNotification OCPP message sent by a charger to report its current status: Available, Preparing, Charging, SuspendedEV, SuspendedEVSE, Finishing, Reserved, Unavailable, or Faulted. ## T ### TLS (Transport Layer Security) Encryption protocol used to secure OCPP WebSocket connections. OCPP 2.0.1 defines three [security profiles](/blog/ocpp-security-profiles-explained) with increasing TLS requirements. ## V ### V2G (Vehicle-to-Grid) Technology enabling EVs to send stored energy back to the electrical grid. Requires bidirectional chargers and ISO 15118-20 support. ## W ### WebSocket The transport protocol used by OCPP for persistent, bidirectional communication between chargers and CPMS. Enables real-time message exchange without polling. --- ## Test Your Knowledge Ready to put these concepts into practice? **OCPPLab** lets you simulate the entire EV charging ecosystem — deploy virtual chargers, test OCPP/OCPI flows, and validate your CPMS implementation. [Start your free simulation →](/dashboard) ---