EV Roaming with OCPI

IoTEV ChargingOCPIIntegration
Share on LinkedIn

Your charging network works flawlessly for subscribers — but a visiting driver with a competing app sees "unknown RFID" because nobody implemented OCPI token routing between your CPO and their eMSP. Roaming is the B2B layer that makes public charging feel universal while money and liability flow correctly behind the scenes. OCPI (Open Charge Point Interface) standardizes how locations, tariffs, live sessions, and charge detail records sync between operators. Getting it wrong means authorized sessions that never settle, duplicate CDRs, or drivers blocked at peak travel weekends.

OCPI module map

Module Purpose
credentials Registration, endpoint discovery, version handshake
locations EVSE metadata, connectors, opening hours, geo
tariffs Price components for transparency
tokens RFID/app token whitelist sync
sessions Active session state mirroring
cdrs Final billable charge detail records
commands Remote start/stop (optional)
chargingprofiles Smart charging (advanced)

Version negotiation starts at /versions → pick 2.2.1 → exchange credentials tokens for authenticated calls.

Roaming topology

Driver (eMSP App) ──► eMSP platform
                           │
                      OCPI (Hub or direct)
                           │
                      CPO platform ── OCPP ──► Charger

Hub (Gireve, Hubject, e-clearing) reduces N×M bilateral integrations — one OCPI connection to hub, many roaming partners.

Direct bilateral common for strategic partners with custom SLAs.

Authorization flow

POST /ocpi/2.2.1/tokens/DE-ABC-12345678-9/authorize
Authorization: Token CPO-credentials-token
{
  "location_id": "LOC-001",
  "evse_uids": ["EVSE-3"],
  "connector_id": "1"
}

Response:

{
  "data": {
    "allowed": "ALLOWED",
    "authorization_reference": "auth-ref-9921",
    "info": { "language": "en", "text": "OK" }
  },
  "status_code": 1000
}

CPO stores authorization_reference on OCPP StartTransaction. Real-time auth for Plug & Charge maps PCID/EMAID to token record.

Deny reasons must propagate to charger display where OCPP supports it.

Sessions and CDRs

During charging, CPO pushes session PATCH:

{
  "id": "sess-441",
  "kwh": 18.4,
  "status": "ACTIVE",
  "start_date_time": "2026-01-24T14:02:00Z",
  "cdr_token": { "uid": "DE-ABC-12345678-9", "type": "RFID" },
  "auth_method": "AUTH_REQUEST"
}

On completion, CDR is immutable financial record:

{
  "id": "cdr-441",
  "total_cost": { "excl_vat": 12.50, "incl_vat": 14.88, "currency": "EUR" },
  "total_energy": 18.4,
  "tariffs": [{ "id": "T1", "currency": "EUR", "elements": [...] }],
  "signed_data": { "encoding_method": "OCMF", "public_key": "..." }
}

eMSP bills driver; clearing settles CPO↔eMSP per contract. Idempotency keys on CDR POST prevent double payment on retries.

Locations and tariffs sync

eMSP apps display CPO locations from OCPI GET /locations delta sync (date_from, date_to). Stale maps cause "station not found" rage.

Tariff complexity (idle fees, time-of-use) must match payment engine — OCPI tariff IDs linked to internal tariff engine version.

Geo indexing for "nearest available" pulls from synced location objects — include STATUS updates via push or frequent poll.

Production pitfalls

Monitor: auth deny rate, CDR reject rate, session stuck without CDR > 24h.

Testing

Roaming is revenue infrastructure — treat OCPI adapters as critical path, not partner integration side project.

OCPI module architecture

Separate OCPI concerns into modules matching the spec:

ocpi/
├── credentials/     # Token exchange, version negotiation
├── locations/       # Station sync, status updates
├── sessions/        # Real-time session tracking
├── cdr/             # Charge detail records (billing)
├── tariffs/         # Pricing sync
└── tokens/          # Authorization whitelist

Each module has its own sync schedule and error handling:

Module Sync frequency Failure impact
Locations Every 15 min Stale map, user frustration
Tokens Real-time push Auth denied at station
Sessions Real-time push Billing delay
CDR On session end Revenue loss if lost
Tariffs Daily Wrong price displayed

CDR module is highest priority — lost CDRs mean lost revenue with no recovery path.

Hub vs peer-to-peer roaming

Peer-to-peer: eMSP connects directly to each CPO's OCPI endpoint. Simple for few partners; N×M connection matrix at scale.

Hub (Gireve, e-clearing.net): Single connection to hub; hub routes to all connected CPOs/eMSPs. Simplifies integration but adds hub fees and single point of dependency.

eMSP ──→ Hub ←── CPO_A
              ←── CPO_B
              ←── CPO_C

Start peer-to-peer for first 2–3 partners to learn OCPI. Move to hub when partner count exceeds 10.

Reconciliation and clearing

CDRs flow: CPO → eMSP (via OCPI) → clearing house → settlement:

-- Reconciliation: match CDRs to sessions
SELECT c.cdr_id, s.session_id, c.total_cost, s.authorized_amount
FROM cdrs c
JOIN sessions s ON c.session_id = s.session_id
WHERE c.total_cost != s.authorized_amount  -- discrepancies
   OR c.status = 'pending' AND c.created_at < NOW() - INTERVAL '24 hours';

Alert on CDRs pending >24 hours. Discrepancies between authorized amount and CDR total need manual review before clearing.

Failure modes

Production checklist

Version OCPI modules explicitly in partner contracts — roaming failures at 2 AM trace to unsupported endpoint versions, not network issues.

Resources

Frequently asked questions

What roles exist in OCPI?

Common roles: CPO (Charge Point Operator runs chargers), eMSP (e-Mobility Service Provider sells to drivers), Hub (routes between networks), NAP (national access point in some regions), and SCSP (smart charging). A company can hold multiple roles. Roaming connects CPO locations to eMSP tokens via bilateral or hub agreements.

How does OCPI authorize a charging session?

CPO calls eMSP POST /tokens/{uid}/authorize (or realtime auth) with token UID from RFID/app. eMSP responds allowed/denied with authorization reference. Session starts via OCPP on charger; CPO pushes session updates; on stop, CPO sends CDR to eMSP for billing.

What is the difference between OCPI and OCPP?

OCPP connects charge point hardware to CPO backend (charger management). OCPI connects CPO backend to eMSP backend (roaming/commerce). You need both in public networks: OCPP for physical control, OCPI for cross-network driver authorization and settlement.

Hiring a senior Android / Flutter engineer?

I architect and ship production mobile software — Kotlin, Jetpack Compose, Flutter — for robotics, EV infrastructure, fintech, and real-time systems. Open to remote roles in Europe and the US.

Get in touch →