OCPI Protocol Software Development: Building EV Roaming Integrations That Survive Production
OCPI — the Open Charge Point Interface — is the EV roaming protocol that lets a Charge Point Operator (CPO) and an e-Mobility Service Provider (eMSP) exchange session, tariff, and Charge Detail Record (CDR) data across network boundaries. The specification is published by the EVRoaming Foundation and looks, on paper, like a settled vocabulary. In production, it isn’t. Every OCPI codebase running against real counterparties has local dialect: module combinations the spec permits but partners interpret differently, tariff shapes flattened by one side and not the other, credential handshakes that work on day one and drift by quarter three. OCPI software development is the discipline of building for that divergence on purpose, not of implementing the specification and hoping it ports.
OCPI Is a Shared Vocabulary, Not a Shared Implementation
Read the OCPI specification end to end and the surface impression is precision. Modules are defined. Endpoints are defined. JSON schemas are documented down to the field. Two engineers who both implemented the spec correctly should produce platforms that interoperate cleanly.
They will not. The spec is a vocabulary, not a compiler. It defines the words you and your roaming partners will use, the grammar for arranging them, and the semantic ranges each word can carry. It does not, and cannot, define the dialect any individual implementer chooses inside that space. Two 2.2.1-compliant platforms can both pass conformance tests and still produce CDRs that disagree on session totals because each side interpreted a tariff component slightly differently, rounded at a different point, or attached calibration-law metadata in a free-text field one partner reads and the other does not.
The implications for OCPI implementation are direct. The development plan is mostly not about implementing the specification. It is about designing a codebase that assumes your partner’s OCPI is not the same as yours, contains partner-specific divergence in one place, and keeps the rest of the platform partner-agnostic. Teams that miss this build a platform that is correct against the spec and fragile against the market.
The clearest signal that a team has missed it is partner-specific code paths bleeding into the data model. The moment a CDR generator has an if partner == X branch, the codebase has lost the property that makes OCPI software maintainable across a roaming portfolio.
Build-Once, Reuse-Across-Partners Is the Only OCPI Software That Survives Contact With Production
Partner-specific code is the original sin of OCPI development. It always looks faster in week one. The first roaming partner has a slightly unusual handshake, the team carves a small exception. The second partner has a different tariff edge case, another exception. By the fourth partner, what was supposed to be a single OCPI integration is four roaming integrations sharing a name. Adding the fifth partner takes longer than adding the first.
The way to avoid that trajectory is a partner-adapter boundary drawn deliberately at the start of the project. Above the boundary sits everything that must be partner-agnostic: the canonical data model, the CDR generator, the settlement pipeline, the API exposed to internal services. Below it sits everything that is allowed to know about a specific partner: the inbound parser that normalises their tariff shape into the canonical model, the outbound serializer that flattens the canonical model into what they accept, the credential handshake, the version routing.
The boundary is enforceable in the type system. The canonical data model has no field for partner identity except as metadata. Adapter code can read and write the canonical model but cannot extend it. Any pull request that adds a field to the canonical model to accommodate a partner-specific quirk is a signal the boundary has been violated and the canonical model should be rolled back to its partner-agnostic shape.
This is the architectural property that makes OCPI integration cheap to extend across partners. The fifth partner takes the same time as the first because the partner-specific code has nowhere to leak into. The same property is what made our EV roaming solutions work commercially when an operator concentrated traffic on a few high-volume corridors and needed bilateral OCPI to pay back inside a quarter.
Version-aware routing is a related decision and it belongs at build time, not runtime. A platform that decides "do I speak 2.2.1 or 2.3 to this partner" by inspecting a flag on every request will quietly accumulate a runtime version table that becomes the most fragile part of the system. The same decision made at adapter selection — one adapter implementation per partner-version pair, picked once at credential handshake — keeps the version conversation out of the hot path.
The OCPI Module That Earns Its Keep Is the One Finance Can Audit
Most OCPI development time is spent on the modules engineers find interesting: Locations, Sessions, Commands, ChargingProfiles. The modules that actually move money are Tariffs, CDRs, and the Tokens-and-Credentials handshake that authorises charging in the first place. Those are also the modules that ship broken most often, because the team building them is usually the one furthest from the finance organisation that has to live with the output.
A CDR is not a logging artefact. It is a financial primary record. A roaming partner’s accounts payable team will reconcile against it, a tax authority may audit it years later, a regulator under AFIR may inspect it for price-transparency compliance. The features that make a CDR shippable from an engineering perspective — fast generation, low storage cost, tolerant deserialisation — are not the features that make it auditable.
What an audit-ready CDR carries:
- Per-component pricing that survives the round-trip: energy, time, parking, idle, subscription discount, tax, each as a structured field with its own price and currency, never collapsed into a free-text note.
- Calibration-law references where the local market requires them (Eichrecht in Germany, similar regimes elsewhere), with an immutable link to the meter reading that produced the energy line.
- Tariff-version provenance showing which version of the tariff the partner published was in effect at session start, session end, and the moment the CDR was generated. Three timestamps, three references, no implicit "latest tariff" reads.
- Partner-version provenance: the OCPI version the CDR was emitted under, the version the partner accepted it under, and the schema validation outcome on both sides.
- Reconciliation handles: a stable session ID, an idempotency key, and a foreign key into the operator’s internal billing record so finance can trace any line on any invoice back to a specific session and a specific CDR.
That list looks like overhead in week three of an OCPI build. By the end of the first quarter of partner certification it stops looking like overhead and starts looking like the difference between a platform that scales and one that bleeds reconciliation effort forever. The reconciliation trap that most first-time teams stumble into is when session kilowatt-hour totals reconcile across partners but tax, currency, or idle-fee components do not. The platform looks correct on the dashboard and produces invoices that finance teams refuse to sign.
For operators planning the platform-level move from 2.2.1 to 2.3, the migration of the tariff-and-CDR object pair is the heaviest piece of work and is covered in the OCPI 2.2.1 to 2.3 migration guide.
The SDK Question: Why “Use This OCPI Library” Is Rarely the Right Answer
A reasonable engineering instinct on starting an OCPI project is to look for a library that has done the protocol work already. The EVRoaming Foundation maintains a list of public OCPI tools. GitHub has reference implementations. Medium articles describe FastAPI-based and Spring-based OCPI libraries. The instinct is sound. The execution rarely is.
A good OCPI library gives a development team three useful things:
- Schemas and validators for every module of the spec, in a shape that can be mechanically updated as the spec evolves.
- A reference message-flow for the Credentials handshake, version negotiation, and the standard module endpoints.
- A test harness that exercises the protocol surface against a known counterparty implementation.
Those three are pure value. They cut weeks off the early phase of a build and reduce the surface area of bugs the team has to discover bilaterally.
What an OCPI library cannot give:
- Partner-specific divergence handling. Every library encodes one author’s interpretation of how the spec should be implemented. That interpretation does not match every partner’s interpretation. Code that adopts the library’s interpretation as the canonical model inherits the library’s blind spots.
- Settlement-grade CDR generation. Open-source libraries optimise for protocol-level correctness, not for the audit-grade output described above. Adapting them to an operator’s finance, tax, and regulatory requirements is most of the work.
- Version migration planning. Libraries follow the spec; they do not handle the partner ecosystem’s actual version distribution, which is always two versions wider than the library’s currently-supported set.
The right way to use an OCPI library is as a reference implementation that informs the validators and the schema layer, not as a foundation that the canonical data model and the settlement pipeline are built on top of. A pre-built, certified codebase such as our OCPI Accelerator is a different proposition: it ships the partner-adapter boundary, the canonical data model, and the audit-grade CDR generator as production scaffolding, not as a library to be wired up.
The Four-Layer OCPI Codebase That Actually Scales
Done well, an OCPI codebase has four clearly-separated layers. Partner-specific code is allowed in exactly one of them; the canonical model and the audit primitives are confined to the other three. The boundary is what makes the codebase scale across partners and survive across versions.

The contract layer at the top exposes a partner-agnostic API to the rest of the operator’s platform: internal services, the eMSP app, the operator’s billing system. They never see partner identity except as metadata.
The partner-adapter layer is the only place partner-specific code is allowed to exist. Every roaming partner has one adapter implementation per OCPI version they speak. The adapter parses inbound payloads into the canonical data model, serializes outbound payloads from it, handles the credential handshake, and owns version negotiation. Adding a new partner is a new adapter; it is not a refactor of the layers above or below.
The canonical data model layer holds the operator’s interpretation of Sessions, CDRs, Tariffs, and Tokens. It must be partner-agnostic by construction. Any change to this layer that exists to accommodate a single partner’s quirk is a signal the partner-adapter boundary has been violated and the change should roll back into an adapter.
The settlement layer at the bottom consumes the canonical CDRs and produces the audit-grade artefacts described in the previous section: invoices, reconciliation tables, regulator-facing reports, calibration-law evidence. It depends only on the canonical model. It never reaches across into partner adapters; if it needs partner context, it gets it through metadata fields the adapter wrote into the canonical model on ingestion.
That four-layer shape is what distinguishes an OCPI codebase that earns its keep from one that runs as a series of glued-together partner integrations. The architectural moat is in the boundary, not in the code.
The Development Phases That Actually Ship Something
A first OCPI integration end-to-end runs roughly a quarter of work for an operator starting from a certified accelerator codebase, and three to four quarters from scratch. The protocol is rarely the schedule risk. The places where teams underestimate are predictable.
| Phase | Typical duration | Core work | Where first-time teams lose the schedule |
|---|---|---|---|
| 1. Discovery and specification lock | 2-3 weeks | Draw the partner-adapter boundary. Lock the canonical data-model shape. Pick OCPI versions in scope, modules in scope, hub-versus-bilateral routing strategy, and the audit fields the settlement layer will require. Secure finance, product, and compliance sign-off. | Treating this phase as preamble. Decisions deferred past spec lock compound the cost of every later phase, especially when canonical-model changes have to ripple through partner adapters that have already been built. |
| 2. Core build | 4-6 weeks (accelerator) 10-14 weeks (from scratch) |
Build the contract layer, the canonical data model, the settlement pipeline, and the first partner adapter. Pass conformance against the Open Charge Alliance test harness. Generate the first audit-grade CDR end-to-end. | Letting partner-specific code leak above the adapter boundary into the canonical model. By the time it’s caught, the data model has accreted partner-specific fields the team has to roll back — paid twice. |
| 3. Partner certification | 4-6 weeks (per first batch of partners) | Bilateral testing against each significant counterparty. Session-linking, token authorisation (RFID, app, Plug & Charge), tariff structure, CDR delivery, and hub-specific routing all revalidate against partner-specific assumptions. | Running too many partners in parallel and losing the context to triage failures. The long tail of partner quirks only surfaces in integration testing; running three at once turns three discoverable bug populations into one indistinguishable noise floor. |
| 4. Hardening and settlement validation | 2-4 weeks | Reconciliation runs nightly. Finance and tax teams sign off on the CDR shape against real invoices. Regulator-facing reports are generated against representative data and reviewed for AFIR or local-equivalent compliance. Cutover to production roaming traffic. | Treating this phase as the last week of the project. The bug class it exists to catch — tax, currency, calibration-law, idle-fee components that reconcile partially but not fully — is invisible until real-world data flows for at least one full billing cycle. |
The first phase, discovery and specification lock, is where the partner-adapter boundary is drawn. The team commits to the canonical model shape, the OCPI versions they will support, the modules in scope, the routing strategy across hubs and bilateral connections, and the audit fields the settlement layer will require. Decisions made later than this phase compound the cost of every subsequent phase.
The second phase, the core build, produces the contract layer, the canonical data model, the settlement pipeline, and the first partner adapter. Most of the visible engineering activity sits here. The phase ends when the first adapter passes conformance against the Open Charge Alliance test harness and produces an audit-grade CDR end-to-end.
The third phase, partner certification, is bilateral and slow. Each significant counterparty has to test against the new platform, and each brings slightly different assumptions about session-linking, token handling, tariff structure, and CDR delivery. Tooling helps with the common paths; the long tail of partner-specific quirks only surfaces in integration testing. First-time teams routinely double-book this phase by running it in parallel for too many partners and losing the context to triage failures.
The fourth phase, hardening and settlement validation, is where the platform either holds in production or rolls back. Reconciliation runs nightly. Finance and tax teams sign off on the CDR shape against real invoices. Regulator-facing reports are generated against representative data and reviewed for AFIR or local-equivalent compliance. Operators who treat this phase as the last week of the project miss the bug class it exists to catch.
For the rest of the cluster context — version migration shape, hub-versus-bilateral economics, the position of OCPI against neighbouring protocols — the OCPI protocol architecture guide is the companion piece.
The OCPI Codebase Is a Long-Lived Asset, Not a One-Off Project
Roaming agreements rotate. OEM partnerships shift. Hub memberships are renegotiated every couple of years. Through all of that, the OCPI codebase stays. The protocol versions advance — 2.1.1 to 2.2.1 to 2.3 to whatever 3.0 settles into — and the codebase that absorbed the versions cleanly outlives the ones that fought them. The platform that an operator builds today is the platform that runs the company’s roaming surface for a decade if it is built well, and is rebuilt every three years if it is not.
The argument across this piece is that the durable OCPI codebase is built for divergence, not for the spec. Partner-adapter boundaries hold. Canonical data models stay partner-agnostic. CDRs and tariffs survive a finance audit. Libraries and SDKs are reference inputs, not foundations. The four layers stay separable, and the version conversation lives in adapter selection rather than in branching logic spread across the platform.
For operators ready to make OCPI a long-lived asset rather than a project, Codibly offers OCPI and OICP interoperability services covering partner-by-partner build, conformance, and settlement validation. The OCPI Accelerator ships the partner-adapter boundary, the canonical data model, and the audit-grade CDR generator as production scaffolding rather than a library that has to be wired up. The boundary, the canonical model, and the audit-grade settlement layer are where the work actually lives.
Frequently Asked Questions
OCPI (Open Charge Point Interface) is the open EV roaming protocol that lets a Charge Point Operator and an e-Mobility Service Provider exchange location, session, tariff, token, and Charge Detail Record data across network boundaries. It is published by the EVRoaming Foundation and is the de facto standard for cross-network EV charging in Europe and a growing part of the US market. The full architecture is covered in the OCPI protocol architecture guide.
They are unrelated projects that share an unfortunate three-letter prefix. OCPI is the EV roaming protocol described in this article — the Open Charge Point Interface, hosted at evroaming.org. OpenCPI is an open-source framework for FPGA and heterogeneous-computing software development, hosted at opencpi.gitlab.io and developed in the embedded-systems and defence community. They have no technical relationship, no shared specification, and no shared community.
OCPI is a protocol specification that defines the data model, message structure, and message flows for EV roaming exchanges between CPOs and eMSPs. APIs are the implementation surface that realises a protocol like OCPI on a specific platform. Two operators can both implement the OCPI specification and expose differently-shaped APIs to their internal services; what they share is the OCPI message contract on the wire, not the API shape inside their stack.
OCPP (Open Charge Point Protocol) connects a charging station to its operator’s backend (the CPMS). OCPI connects two operators’ backends to each other for cross-network roaming. A CPO typically runs OCPP to control its hardware and OCPI to expose its network to roaming partners. The full breakdown is in the OCPI vs OCPP reference.
For an operator starting from a certified accelerator codebase, a first end-to-end OCPI integration with one or two partners typically runs ten to fourteen weeks: roughly two to three weeks of discovery and specification lock, four to six weeks of core build through to first conformance pass, and four to six weeks of partner certification overlapping into the hardening and settlement-validation phase. From scratch the same work runs three to four quarters because the canonical data model, the settlement pipeline, and the partner-adapter boundary all have to be designed and built rather than configured.