Reservation Section — Migration Guide
Use cases H01–H04 (Reservation). Perspective: CSMS Developer.
Created by tzi.app — your guide to migrating from OCPP 2.0.1 to OCPP 2.1.
1. Summary of Changes
High-Level Overview
| Area | Change Type | Description |
|---|---|---|
| Connector/EVSE status reporting | Replaced | StatusNotificationRequest replaced by NotifyEventRequest across H01, H02, H04; 2.1 adds EVSE-level notifications alongside connector-level |
| IdTokenType | Field size increase | idToken max length: 36 → 255 chars |
| IdTokenEnumType → IdTokenEnumStringType | Type changed | Changed from a closed enum to a string type (max 20 chars) |
| StatusInfoType | Field size increase | additionalInfo max length: 512 → 1024 chars |
| ConnectorEnumType → ConnectorEnumStringType | Type changed | Changed from a closed enum to a string type (max 20 chars); new values added (cCHAdeMO, cGBT) |
| ReservationUpdateStatusEnumType | New value | NoTransaction added — sent when matching token is presented but no transaction starts within EVConnectionTimeout |
| H03.FR.11 | New requirement | CS sends ReservationStatusUpdateRequest with NoTransaction when token matches but no transaction starts within timeout |
| EVConnectionTimeout | New config variable | Timeout (seconds) after token presentation before cable must be connected; drives the NoTransaction status |
| Integer field constraints | Clarified | id and reservationId now explicitly specify >= 0 |
| customData | New field | All messages gain an optional customData field (with required vendorId string, max 255) |
| Schema IDs | New | All message schemas now have URN-based identifiers (e.g., urn:OCPP:Cp:2:2025:1:ReserveNowRequest) |
| EVSE-level NotifyEvent | New | 2.1 adds NotifyEventRequest with component.name = "EVSE" in addition to "Connector" for availability state changes |
2. Cross-Cutting Change: StatusNotification Replaced by NotifyEvent
In OCPP 2.0.1, connector state changes in reservation flows used StatusNotificationRequest (with NotifyEventRequest as an alternative). In OCPP 2.1, NotifyEventRequest is the primary mechanism and StatusNotificationRequest is explicitly deprecated.
Affected Use Cases
| Use Case | 2.0.1 | 2.1 |
|---|---|---|
| H01 S2 (Reserve specific EVSE) | CS sends StatusNotificationRequest (connectorStatus=Reserved) | CS sends NotifyEventRequest for both Connector-level AND EVSE-level (AvailabilityState=Reserved) |
| H02 (Cancel Reservation) | CS sends StatusNotificationRequest (connectorStatus=Available) | CS sends NotifyEventRequest for connector(s) with AvailabilityState=Available |
| H04 (Reservation Expired) | CS sends StatusNotificationRequest (connectorStatus=Available), noted as deprecated | CS sends NotifyEventRequest for both Connector-level AND EVSE-level (AvailabilityState=Available) |
New EVSE-Level Notifications in 2.1
OCPP 2.1 introduces EVSE-level NotifyEventRequest messages in addition to connector-level ones. In 2.0.1, only connector-level status
was reported.
2.1 — After reserving a specific EVSE, the CS sends TWO NotifyEventRequests:
{
"eventData": [{
"component": {
"name": "Connector",
"evse": { "id": 1, "connectorId": 1 }
},
"variable": { "name": "AvailabilityState" },
"actualValue": "Reserved"
}]
}{
"eventData": [{
"component": {
"name": "EVSE",
"evse": { "id": 1 }
},
"variable": { "name": "AvailabilityState" },
"actualValue": "Reserved"
}]
}CSMS Migration Action
- Replace
StatusNotificationRequesthandler withNotifyEventRequesthandler that filters for bothcomponent.name = "Connector"andcomponent.name = "EVSE"withvariable.name = "AvailabilityState". - Extract the state from
actualValueinstead ofconnectorStatus. - Handle multiple
NotifyEventRequestmessages per reservation event (one per connector, one per EVSE).
3. Data Type & Schema Changes
3.1 IdTokenType
| Field | 2.0.1 | 2.1 | Action |
|---|---|---|---|
idToken | string (max 36) | string (max 255, case-insensitive) | Increase max length validation from 36 to 255 |
type | IdTokenEnumType (closed enum) | IdTokenEnumStringType (string, max 20) | Change from enum validation to string validation; accept unknown values gracefully |
additionalInfo[].additionalIdToken | Not explicitly documented | string (max 255) | Add field length validation |
additionalInfo[].type | Not explicitly documented | string (max 50) | Add field length validation |
3.2 StatusInfoType
| Field | 2.0.1 | 2.1 | Action |
|---|---|---|---|
additionalInfo | string (max 512) | string (max 1024) | Increase max length validation from 512 to 1024 |
3.3 ConnectorEnumType → ConnectorEnumStringType
| Aspect | 2.0.1 | 2.1 | Action |
|---|---|---|---|
| Type | ConnectorEnumType (closed enum) | ConnectorEnumStringType (string, max 20) | Change from enum validation to string validation |
| New values | — | cCHAdeMO, cGBT added | Accept new connector types |
| Removed values | cG105, s309-1P-16A, s309-1P-32A, s309-3P-16A, s309-3P-32A, sBS1361, sCEE-7-7, Other1PhMax16A, Other1PhOver16A, Other3Ph, Pan, wInductive, wResonant, Undetermined, Unknown | Not listed in 2.1 common values (may still be valid as string) | Since the type is now a string (max 20), these values may still be sent; accept unknown values gracefully |
3.4 Integer Field Constraints
| Field | 2.0.1 | 2.1 | Action |
|---|---|---|---|
ReserveNowRequest.id | integer | integer (>= 0) | Add explicit non-negative validation |
CancelReservationRequest.reservationId | integer | integer (>= 0) | Add explicit non-negative validation |
ReservationStatusUpdateRequest.reservationId | integer | integer (>= 0) | Add explicit non-negative validation |
3.5 CustomData Field (New in 2.1)
All reservation messages now support an optional customData field:
{
"customData": {
"vendorId": "string (max 255, REQUIRED if customData present)"
}
}Affected messages: ReserveNowRequest, ReserveNowResponse, CancelReservationRequest, CancelReservationResponse, ReservationStatusUpdateRequest, ReservationStatusUpdateResponse
Action: Accept and pass through customData in all reservation messages. Store or log vendorId for vendor-specific extensions.
3.6 ReservationUpdateStatusEnumType — New Value
| Value | 2.0.1 | 2.1 | Description |
|---|---|---|---|
Expired | Yes | Yes | Reservation expired (expiryDateTime reached) |
Removed | Yes | Yes | Reservation removed (EVSE faulted/unavailable) |
| NoTransaction | No | Yes | Matching token presented but no transaction started within EVConnectionTimeout |
4. Use Case Changes (H01–H04)
Reserve Now
| Aspect | 2.0.1 | 2.1 | Impact |
|---|---|---|---|
| S2 connector status notification | CS sends StatusNotificationRequest(Reserved) for all connectors of reserved EVSE | CS sends NotifyEventRequest for both Connector-level and EVSE-level with AvailabilityState=Reserved | Replace handler; expect two types of NotifyEvent messages |
| S2 alternative notification | NotifyEventRequest mentioned as alternative | StatusNotificationRequest mentioned as deprecated alternative | Swap primary/fallback handling |
| FR.20 (unspecified EVSE, all reserved) | CS sends StatusNotification / NotifyEvent with connectorStatus=Reserved | CS sends NotifyEventRequest with AvailabilityState=Reserved | Update handler |
| FR.23 (specific EVSE reserved) | CS sends connector status Reserved for all connectors | CS sends NotifyEventRequest for all connectors with AvailabilityState=Reserved | Update handler |
No breaking changes to ReserveNowRequest or ReserveNowResponse message structures. The core fields (id, expiryDateTime, idToken, evseId, connectorType, groupIdToken) remain the same. Only field size limits and type constraints have changed.
Cancel Reservation
| Aspect | 2.0.1 | 2.1 | Impact |
|---|---|---|---|
| Status notification after cancel | CS sends StatusNotificationRequest(Available) or NotifyEventRequest(AvailabilityState=Available) | CS sends NotifyEventRequest with AvailabilityState=Available; StatusNotificationRequest is deprecated | Update handler to primarily use NotifyEventRequest |
No breaking changes to CancelReservationRequest or CancelReservationResponse message structures.
Use a Reserved EVSE
| Aspect | 2.0.1 | 2.1 | Impact |
|---|---|---|---|
| New requirement H03.FR.11 | Not present | If token matches but no transaction starts within EVConnectionTimeout, CS sends ReservationStatusUpdateRequest with NoTransaction | New handler required — handle NoTransaction status update |
| Connector status after consumption | CS sends status changes via StatusNotification or NotifyEvent | CS sends NotifyEventRequest | Update handler |
CSMS migration action: Add handling for ReservationStatusUpdateRequest with reservationUpdateStatus = "NoTransaction". This represents a new terminal state for a reservation where the correct
token was presented but the EV driver did not complete the charging session
setup within the timeout.
Reservation Ended, Not Used
| Aspect | 2.0.1 | 2.1 | Impact |
|---|---|---|---|
| Status notification for expired reservation | CS sends StatusNotificationRequest(Available), noted as deprecated | CS sends NotifyEventRequest for both Connector-level AND EVSE-level with AvailabilityState=Available | Update handler; expect EVSE-level notifications |
| Sequence diagram | Shows single StatusNotificationRequest before ReservationStatusUpdateRequest | Shows two NotifyEventRequest messages (Connector + EVSE) before ReservationStatusUpdateRequest | Handle multiple NotifyEvent messages per expiry event |
No breaking changes to ReservationStatusUpdateRequest or ReservationStatusUpdateResponse message structures (beyond the new NoTransaction enum value).
5. New Reservation Status: NoTransaction
Overview
OCPP 2.1 introduces a new ReservationUpdateStatusEnumType value: NoTransaction. This covers a scenario not addressed in 2.0.1 — when the correct token is presented
at the Charging Station but the EV driver fails to start a transaction within the EVConnectionTimeout period.
When It Occurs
- EV Driver presents a token that matches the reservation's
idTokenorgroupIdToken. - The Charging Station recognizes the match and consumes the reservation.
- The EV Driver does not plug in the cable
(or does not meet
TxStartPointconditions) within theEVConnectionTimeoutperiod. - The Charging Station sends
ReservationStatusUpdateRequestwithreservationUpdateStatus = "NoTransaction".
New Configuration Variable
| Variable | Type | Description | Impact on CSMS |
|---|---|---|---|
EVConnectionTimeout | integer (seconds) | Timeout after token presentation before cable must be connected. | If token matches reservation but no transaction starts within this timeout,
CS sends ReservationStatusUpdateRequest with NoTransaction. CSMS should be aware of this value to set appropriate user
expectations. |
Updated Reservation Lifecycle
ReserveNowResponse
(status=Accepted)
|
v
[Active]
|
+-------------+-------------+--------------+-----------------+
v v v v v
[Consumed] [Expired] [Cancelled] [Removed] [NoTransaction]
(H03: tx (H04: (H02: CSMS (H01.FR.16/17: (H03.FR.11:
started) timeout) cancels) EVSE fault) token matched,
no tx started)CSMS Implementation
// In ReservationStatusUpdateRequest handler:
case "NoTransaction":
reservation.status = "no_transaction"
reservation.endReason = "no_cable_connected"
notifyDriver(reservation, "You were identified but did not start charging within the timeout.")
// The EVSE is now available for other users6. Migration Checklist
Message Handler Updates
- Replace StatusNotificationRequest handler with NotifyEventRequest handler for reservation-related availability state changes in H01, H02, and H04 flows
- Handle EVSE-level NotifyEventRequest (component.name = "EVSE") in addition to connector-level (component.name = "Connector") — new in 2.1
- Handle ReservationStatusUpdateRequest with reservationUpdateStatus = "NoTransaction" (new in 2.1, requirement H03.FR.11)
- Accept and pass through customData in all reservation messages
Schema Validation Updates
- IdTokenType.idToken max length: 36 → 255
- IdTokenType.type: closed enum (IdTokenEnumType) → string (max 20, IdTokenEnumStringType); accept unknown values
- StatusInfoType.additionalInfo max length: 512 → 1024
- ConnectorEnumType → ConnectorEnumStringType: closed enum → string (max 20); accept new values (cCHAdeMO, cGBT) and unknown values
- ReserveNowRequest.id: add explicit >= 0 validation
- CancelReservationRequest.reservationId: add explicit >= 0 validation
- ReservationStatusUpdateRequest.reservationId: add explicit >= 0 validation
New Enum Values
ReservationUpdateStatusEnumType: addNoTransaction
New Configuration Variables
EVConnectionTimeout(integer, seconds): be aware of this timeout that drivesNoTransactionstatus updates
Database Schema Updates
- Add no_transaction as a valid reservation status (in addition to existing active, used/consumed, expired, cancelled, removed)
- Consider renaming used status to consumed to align with 2.1 terminology
Reservation Lifecycle Updates
- Add NoTransaction as a terminal state in the reservation state machine
- Handle the transition: Active → NoTransaction (triggered by ReservationStatusUpdateRequest with NoTransaction)