OCPI 2.2 added two modules that 2.1.1 lacked. Charging Profiles lets a Smart Charging Service Provider (SCSP), or an eMSP acting as one, ask a CPO to limit the power of a specific session. Hub Client Info lets a roaming hub tell its connected parties who else is reachable. They are less commonly implemented than locations or CDRs, but both matter as networks scale: one for grid and price-aware charging, the other for operating behind a hub.
This is part 9 of the OCPI 2.2.1 series. For the underlying smart charging concepts, see smart charging and load management and the OCPP view in OCPP 1.6 smart charging.
Charging Profiles: who does what
The CPO implements the Receiver interface, because it controls the chargers. The SCSP implements the Sender interface, which, as with commands, mainly receives asynchronous results and unsolicited updates. Profiles are always addressed per session, not per EVSE or location: OCPI does not let an outside party set site-wide limits. The CPO keeps responsibility for its own site constraints and combines the SCSP's request with them.
The ChargingProfile object
{
"start_date_time": "2026-10-26T18:00:00Z",
"duration": 7200,
"charging_rate_unit": "W",
"min_charging_rate": 1380,
"charging_profile_period": [
{ "start_period": 0, "limit": 11000 },
{ "start_period": 3600, "limit": 3700 }
]
}charging_rate_unitisWorA. Ampere limits are per phase, as in OCPP.charging_profile_periodentries start atstart_periodseconds after the profile start and run until the next entry.duration(seconds) andstart_date_timeare optional; without them the profile applies from now, indefinitely for the session.- This is deliberately close to the OCPP
ChargingSchedule, so the CPO can translate it directly into aTxProfilefor the session's transaction.
Setting a profile
PUT /ocpi/cpo/2.2.1/chargingprofiles/SESS-000123 HTTP/1.1
Host: cpo.example.com
Authorization: Token OWU4MGE1OWMtNmEyZi00YjVkLThlMWMtMmYzYTRiNWM2ZDdl
Content-Type: application/json
X-Request-ID: 1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d
X-Correlation-ID: 1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d{
"charging_profile": {
"charging_rate_unit": "W",
"charging_profile_period": [
{ "start_period": 0, "limit": 7400 }
]
},
"response_url": "https://scsp.example.com/ocpi/2.2.1/chargingprofiles/results/set-55f1"
}Like commands, the CPO answers synchronously with a ChargingProfileResponse and later posts the actual outcome to response_url:
{
"data": { "result": "ACCEPTED", "timeout": 30 },
"status_code": 1000,
"timestamp": "2026-10-26T18:00:01Z"
}| Operation | Synchronous ChargingProfileResponseType | Async result object |
|---|---|---|
PUT {url}/{session_id} set profile | ACCEPTED, NOT_SUPPORTED, REJECTED, TOO_OFTEN, UNKNOWN_SESSION | ChargingProfileResult |
GET {url}/{session_id}?duration=...&response_url=... get active profile | same | ActiveChargingProfileResult (includes the ActiveChargingProfile) |
DELETE {url}/{session_id}?response_url=... clear profile | same | ClearProfileResult |
The async result objects carry a result of type ChargingProfileResultType: ACCEPTED, REJECTED or UNKNOWN. TOO_OFTEN deserves attention: chargers and CPO back-ends cannot process a new profile every few seconds, and a CPO should protect itself rather than queue an unbounded stream of updates to a charger over a cellular link.
The active profile
A GET asks the CPO for the profile actually in effect for the next duration seconds. The answer, an ActiveChargingProfile, is the combination of everything that limits the session: the SCSP's request, the CPO's own site limits, and the vehicle. It is typically derived from OCPP GetCompositeSchedule. The CPO can also push changes to it unsolicited, with PUT on the SCSP's Receiver at {url}/{session_id}, for example when local load balancing lowers the limit.
Practical mapping to OCPP
- The session must have an OCPP transaction; set the profile as a
TxProfilebound to thattransactionId. - Choose a
stackLevelthat sits correctly relative to the CPO's ownTxDefaultProfileand site-level profiles, so site safety limits still win. - Convert units if the charger only supports one
chargingRateUnit(many AC chargers preferA). Converting W to A needs the number of phases and the nominal voltage. - When the session ends, the profile goes with it. There is nothing to clear afterwards.
The OCPP side of these operations is covered in OCPP 1.6 smart charging and OCPP 2.0.1 smart charging.
Hub Client Info
When you connect to a hub, you have one OCPI connection but many potential counterparties. The hubclientinfo module tells you which ones exist and whether they are currently reachable. The object is small:
{
"party_id": "EXA",
"country_code": "NL",
"role": "EMSP",
"status": "CONNECTED",
"last_updated": "2026-10-26T07:30:00Z"
}ConnectionStatus | Meaning |
|---|---|
CONNECTED | Party is connected to the hub and reachable. |
OFFLINE | Party is connected but currently unreachable; requests to it will fail or time out at the hub. |
PLANNED | Connection is planned, not yet live. |
SUSPENDED | Connection is suspended, typically for commercial or contractual reasons. |
The hub pushes these with PUT {url}/{country_code}/{party_id} to the party's Receiver interface, and parties can pull the full list from the hub's Sender interface with GET and the usual pagination. Use it to decide whether to push to a party at all, and to show correct partner status in your own operations tooling.
Working with hubs in practice
- Routing headers are mandatory through hubs. Every request needs
OCPI-from-country-code,OCPI-from-party-id,OCPI-to-country-codeandOCPI-to-party-id(see Part 3). Missing or wrong headers are rejected or, worse, routed to the wrong party. - 4xxx status codes.
4001unknown receiver,4002timeout on the forwarded request,4003connection problem. These come from the hub, not your partner; retry4002and4003, and fix configuration on4001. - Broadcast vs addressed messages. Some data, such as locations and tariffs, is usually meant for every eMSP on the hub; sessions and CDRs are always for one specific eMSP. How a hub handles broadcast pushes differs between hubs; read its integration guide rather than assuming.
- Hubs validate. Hubs commonly enforce stricter validation than the spec (field lengths, mandatory
evse_id, coordinate formats). Test against the hub's own test environment, not only against a peer. - Timeouts multiply. A real-time authorization through a hub involves two HTTP hops plus the eMSP's processing. Budget for it, as discussed in Part 5.
- Mixed topologies. It is normal to reach some partners via a hub and others directly. Keep routing decisions per partner and make sure you never deliver the same CDR via both paths.
The commercial side of hub vs peer-to-peer roaming is covered in EV roaming explained.
Key takeaways
- Charging Profiles are per session, sent by an SCSP to the CPO's Receiver, with synchronous
ChargingProfileResponseand asynchronous results toresponse_url. - The CPO combines the request with its own constraints; the
ActiveChargingProfileis what is actually applied. - Hub Client Info tells you which parties a hub can reach and their
ConnectionStatus. - Through a hub, routing headers are mandatory and
4xxxcodes tell you where the failure was.
Next: Part 10, mapping OCPP to OCPI, where all the modules come together inside a CSMS.

