OCPI 2.2.1
Rollyy implements the Open Charge Point Interface (OCPI) 2.2.1 as an eMSP (e-Mobility Service Provider). This allows Rollyy to connect to any OCPI-compliant charging network (CPO) and enables the autonomous robot to start, stop, and monitor charging sessions across Europe.
Architecture
Rollyy Robot → Rollyy API → OCPI Handshake → CPO Network
↓
Locations / Tariffs / Sessions / CDRs
Rollyy acts as the EMSP. CPOs (charge point operators like Virta, Shell, Hubject) act as the CPO side.
Authentication
OCPI uses token-based auth in the Authorization header — different from the standard API key:
Authorization: Token <ocpi_token>
Tokens are exchanged during the OCPI handshake. You do not set these manually.
Onboarding a CPO
Register a CPO connection
Initiates the full OCPI 2.2.1 handshake: version discovery → credentials exchange → token swap.
Endpoint: POST /ocpi/register
Auth: X-API-Key
Request:
{
"cpo_name": "Virta",
"versions_url": "https://ocpi.virta.global/ocpi/versions"
}
Response:
{
"connection_id": "550e8400-e29b-41d4-a716-446655440000",
"cpo_name": "Virta",
"status": "active",
"modules": ["credentials", "locations", "sessions", "commands", "tariffs", "tokens"]
}
List CPO connections
Endpoint: GET /ocpi/connections
Auth: X-API-Key
Response:
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"cpo_name": "Virta",
"versions_url": "https://ocpi.virta.global/ocpi/versions",
"status": "active",
"modules": ["credentials", "locations", "sessions", "commands", "tariffs"]
}
]
Connect to a roaming hub
One-click connection to Hubject or Gireve — gives access to all hub member CPOs.
Endpoint: POST /v1/roaming/connect?hub={hub}
Supported hubs: hubject, gireve
Example:
curl -X POST "https://api.rollyy.com/v1/roaming/connect?hub=hubject" \
-H "X-API-Key: your_api_key"
Response:
{
"status": "connected",
"hub": "hubject",
"connection_id": "660e8400-e29b-41d4-a716-446655440001"
}
Roaming status
Endpoint: GET /v1/roaming/status
Response:
{
"connections": [
{
"connection_id": "660e8400-...",
"name": "Hubject",
"type": "hub",
"status": "active",
"modules": ["locations", "sessions", "commands", "tariffs"]
}
],
"hubs_connected": 1,
"direct_connected": 1
}
Locations
Sync locations from a CPO
Pulls all EVSE locations from a registered CPO into Rollyy's database.
Endpoint: PUT /ocpi/2.2.1/locations/{location_id} (CPO pushes to us)
CPOs push location updates automatically after handshake. You can also trigger a pull via the charging assets sync.
Serve our locations to CPOs
Endpoint: GET /ocpi/2.2.1/locations
Returns all OCPI-sourced charging assets in Rollyy's database.
Commands
Used by the robot to start and stop charging sessions at a CPO EVSE.
Start a charging session
Endpoint: POST /ocpi/2.2.1/commands/START_SESSION
Auth: X-API-Key
Request:
{
"evse_uid": "FI-VRT-E12345",
"location_id": "FI-VRT-L001",
"robot_job_id": "550e8400-e29b-41d4-a716-446655440000"
}
Response:
{
"session_id": "770e8400-e29b-41d4-a716-446655440002",
"robot_job_id": "550e8400-e29b-41d4-a716-446655440000",
"cpo_result": "ACCEPTED",
"status": "pending"
}
CPO result values:
ACCEPTED— CPO accepted the command, session startingTIMEOUT— CPO accepted but no immediate confirmation (session may still start)REJECTED— CPO refused (returns HTTP 400)
Stop a charging session
Endpoint: POST /ocpi/2.2.1/commands/STOP_SESSION
Auth: X-API-Key
Request:
{
"ocpi_session_id": "770e8400-e29b-41d4-a716-446655440002"
}
Response:
{
"session_id": "770e8400-e29b-41d4-a716-446655440002",
"cpo_result": "ACCEPTED",
"status": "stopping"
}
Command callback
CPOs post async command results here after processing.
Endpoint: POST /ocpi/2.2.1/commands/callback
This is called by the CPO — you do not call this directly.
Sessions
Receive session update (CPO pushes)
Endpoint: PUT /ocpi/2.2.1/sessions/{session_id}
Called by the CPO to push live session updates. Handled automatically.
Sync sessions from CPO (pull fallback)
Use when a CPO doesn't push updates automatically.
Endpoint: GET /ocpi/2.2.1/sessions/sync/{connection_id}
Auth: X-API-Key
Response:
{ "synced": 3 }
Get session for a robot job
Endpoint: GET /ocpi/2.2.1/sessions/job/{job_id}
Auth: X-API-Key
Response:
{
"session_id": "770e8400-e29b-41d4-a716-446655440002",
"status": "active",
"energy_kwh": 12.5,
"cost": 4.38,
"currency": "EUR",
"duration_minutes": 22,
"start_time": "2026-03-30T08:00:00Z",
"end_time": null,
"robot_job_status": "charging"
}
Session status values:
| Status | Meaning |
|---|---|
pending | Waiting for CPO confirmation |
active | Charging in progress |
stopping | Stop command sent |
completed | Session finished |
failed | Error or rejected |
CDRs (Charge Detail Records)
CDRs are the authoritative billing records sent by the CPO after a session ends. On receipt, Rollyy automatically updates the session cost and triggers payment.
Receive CDR (CPO pushes)
Endpoint: PUT /ocpi/2.2.1/cdrs/{cdr_id}
Called by the CPO. Handled automatically — triggers Stripe payment in background.
Sync CDRs from CPO (pull fallback)
Endpoint: POST /ocpi/2.2.1/cdrs/sync/{connection_id}
Auth: X-API-Key
Response:
{ "synced": 2 }
Tariffs
Sync tariffs from a CPO
Endpoint: POST /ocpi/2.2.1/tariffs/sync/{connection_id}
Auth: X-API-Key
Response:
{ "synced": 5 }
Estimate cost before charging
Endpoint: GET /ocpi/2.2.1/tariffs/estimate
Query parameters:
asset_id— charging asset UUIDkwh— expected energy (optional)duration_minutes— expected duration (optional)
Example:
curl "https://api.rollyy.com/ocpi/2.2.1/tariffs/estimate?asset_id=abc&kwh=20&duration_minutes=30" \
-H "X-API-Key: your_api_key"
Response:
{
"tariff_id": "VRT-001",
"currency": "EUR",
"elements": [...],
"estimate": {
"estimated_cost": 7.00,
"currency": "EUR"
}
}
Reconcile session cost
Compare CPO-reported cost vs. tariff-calculated cost after a session.
Endpoint: GET /ocpi/2.2.1/tariffs/reconcile/{session_id}
Response:
{
"session_id": "770e8400-...",
"cpo_reported_cost": 7.20,
"calculated_cost": 7.00,
"currency": "EUR",
"discrepancy": 0.20,
"energy_kwh": 20.0,
"duration_minutes": 30
}
Tokens
Rollyy manages driver tokens that CPOs use to authorise charging.
Authorise a token (CPO calls this)
Endpoint: GET /ocpi/2.2.1/tokens/{token_uid}/authorize
Returns ALLOWED or NOT_ALLOWED.
Revoke a token
Endpoint: DELETE /ocpi/2.2.1/tokens/{token_uid}
Auth: X-API-Key
Response:
{ "revoked": true }
Smart Charging
Control charge rate and schedule for an active session.
Set charging profile
Endpoint: POST /v1/sessions/{session_id}/charging-profile
Auth: User JWT
Request:
{
"max_charge_rate_kw": 11.0,
"departure_time": "2026-03-30T18:00:00Z"
}
Response:
{
"session_id": "770e8400-...",
"profile_set": true,
"max_charge_rate_kw": 11.0,
"departure_time": "2026-03-30T18:00:00Z",
"periods": [
{ "start_period": 0, "limit": 11000 }
]
}
Clear charging profile
Endpoint: DELETE /v1/sessions/{session_id}/charging-profile
Resumes full-speed charging.
Discovery Endpoints
These are called by CPOs during handshake — you do not call them directly.
| Endpoint | Purpose |
|---|---|
GET /ocpi/versions | Returns supported OCPI versions |
GET /ocpi/2.2.1/details | Returns all module endpoints |
GET /ocpi/2.2.1/credentials | Returns Rollyy credentials |
POST /ocpi/2.2.1/credentials | CPO posts their credentials |
Supported Modules
| Module | Role | Description |
|---|---|---|
credentials | RECEIVER | Handshake token exchange |
locations | RECEIVER | CPO pushes charger locations to us |
sessions | RECEIVER | CPO pushes live session updates |
commands | SENDER | We send START/STOP to CPO |
tariffs | RECEIVER | CPO pushes pricing |
tokens | SENDER | We expose driver tokens for CPO validation |
charging_profiles | SENDER | We send smart charging schedules |