Reservation Flows - CSMS Developer Guide
Based on OCPP 2.1 Edition 2 Specification (Part 2), Section H (Reservation). This guide covers all reservation flows (H01–H04), including reserve now, cancel reservation, use reserved EVSE, and reservation lifecycle management from the CSMS perspective using OCPP-J (JSON over WebSocket).
1. Overview
IntroductionThe Reservation functional block enables an EV Driver to reserve an EVSE at a Charging Station until a certain expiry time, ensuring the EVSE cannot be occupied by another user. The CSMS initiates reservations and cancellations, and handles incoming status updates from Charging Stations.
Key Constraints
Available EVSEs Only
Only available EVSEs can be reserved. The Charging Station cannot predict when an occupied EVSE will become available.
Reservation Targets
The CSMS can reserve: a specific EVSE (by evseId), a specific connector type (by connectorType), or an unspecified EVSE (neither).
Authorization Recommended
It is recommended to validate the identifier with an AuthorizeRequest after receiving a ReserveNowResponse and before the start of the transaction.
Occupied EVSE Strategy
A CSMS may support reservation for occupied EVSEs by delaying the ReserveNowRequest until the EVSE becomes available, but there is no guarantee it will be available in time.
CSMS Roles
Sender for:
ReserveNowRequest CancelReservationRequestReceiver for:
ReservationStatusUpdateRequest NotifyEventRequest AuthorizeRequest2. Messages Summary
Reference| Message | Direction | Initiated By | CSMS Role |
|---|---|---|---|
ReserveNowRequest | CSMS → CS | CSMS | Sender |
ReserveNowResponse | CS → CSMS | CS | Receiver — process status |
CancelReservationRequest | CSMS → CS | CSMS | Sender |
CancelReservationResponse | CS → CSMS | CS | Receiver — process status |
ReservationStatusUpdateRequest | CS → CSMS | CS | Receiver — handle update |
ReservationStatusUpdateResponse | CSMS → CS | CSMS | Sender — acknowledge |
NotifyEventRequest | CS → CSMS | CS | Receiver — track EVSE availability |
AuthorizeRequest | CS → CSMS | CS | Receiver — authorize token, return groupIdToken |
3. H01 — Reserve Now (CSMS-Initiated)
CSMS-Initiated| Use Case ID | H01 |
| Objective | Enable an EV Driver to reserve an EVSE at a Charging Station until a certain expiry time |
| Actors | Charging Station, CSMS, EV Driver |
| OCPP Messages | ReserveNowRequest / ReserveNowResponse |
S1 — Reserve an Unspecified EVSE
The EV Driver requests a reservation without specifying a particular EVSE. The Charging Station picks any available EVSE.
EV Driver CSMS Charging Station
| | |
|--- reserve ----->| |
| |--- ReserveNowRequest ----------->|
| | (id, expiryDateTime, idToken) |
| | (NO evseId) |
| | |
| |<-- ReserveNowResponse ------------|
| | (status = Accepted) |
|<-- notification -| |{
"id": 12345,
"expiryDateTime": "2025-12-15T14:30:00Z",
"idToken": {
"idToken": "AABBCCDD",
"type": "ISO14443"
}
}| Field | Type | Required | Description |
|---|---|---|---|
id | integer (≥ 0) | Yes | Unique reservation ID generated by CSMS. If it matches an existing reservation on the CS, the old one is replaced. |
expiryDateTime | string (ISO 8601) | Yes | When the reservation expires. |
idToken | IdTokenType | Yes | The token the reservation is for. |
evseId | integer (≥ 0) | No | Omitted for unspecified EVSE reservation. |
connectorType | string (max 20) | No | Omitted for unspecified EVSE reservation. |
groupIdToken | IdTokenType | No | Optional group token — allows any token in the same group to use the reservation. |
CSMS Implementation Steps
- Receive reservation request from EV Driver (via app/API).
- Generate a unique
id(integer ≥ 0) for the reservation. - Set
expiryDateTimeto the desired expiry time. - Populate
idTokenwith the EV Driver's token info. - Do NOT include
evseIdorconnectorType. - Optionally include
groupIdTokenif group-based reservation is desired. - Send
ReserveNowRequestto the target Charging Station. - Process the
ReserveNowResponse.
Prerequisite: The Charging Station has at least one available EVSE.
S2 — Reserve a Specific EVSE
The EV Driver requests a reservation for a specific EVSE at the Charging Station.
EV Driver CSMS Charging Station
| | |
|--- reserve ----->| |
| |--- ReserveNowRequest ----------->|
| | (id, expiryDateTime, idToken, |
| | evseId) |
| | |
| |<-- ReserveNowResponse ------------|
| | (status = Accepted) |
| | |
| |<-- NotifyEventRequest ------------|
| | (component=Connector, |
| | variable=AvailabilityState, |
| | actualValue=Reserved) |
| | |
| |--- NotifyEventResponse ---------->|
| | |
| |<-- NotifyEventRequest ------------|
| | (component=EVSE, |
| | variable=AvailabilityState, |
| | actualValue=Reserved) |
| | |
| |--- NotifyEventResponse ---------->|
|<-- notification -| |{
"id": 12346,
"expiryDateTime": "2025-12-15T14:30:00Z",
"evseId": 1,
"idToken": {
"idToken": "AABBCCDD",
"type": "ISO14443"
},
"groupIdToken": {
"idToken": "GROUP001",
"type": "Central"
}
}CSMS Implementation Steps
- Same as S1, but include
evseIdspecifying the target EVSE. - Send
ReserveNowRequest. - Process
ReserveNowResponse. - Expect incoming
NotifyEventRequestmessages from the Charging Station reporting connector and EVSE availability changes toReserved. - Respond to each
NotifyEventRequestwith an emptyNotifyEventResponse. - Update internal EVSE state tracking to reflect
Reservedstatus.
Prerequisite: The specified EVSE has status Available.
Post-conditions on success
- Charging Station accepted the
ReserveNowRequest - Charging Station sent
NotifyEventRequestwithcomponent.name = "Connector",variable.name = "AvailabilityState",actualValue = "Reserved"
Alternative: Instead of NotifyEventRequest, the Charging Station may send the deprecated StatusNotificationRequest with connectorStatus = Reserved.
S3 — Reserve a Connector Type
The EV Driver requests a reservation for a specific connector type (e.g. CCS2, CHAdeMO) without specifying a particular EVSE.
EV Driver CSMS Charging Station
| | |
|--- reserve ----->| |
| |--- ReserveNowRequest ----------->|
| | (id, expiryDateTime, idToken, |
| | connectorType, NO evseId) |
| | |
| |<-- ReserveNowResponse ------------|
| | (status = Accepted) |
|<-- notification -| |{
"id": 12347,
"expiryDateTime": "2025-12-15T14:30:00Z",
"connectorType": "cCCS2",
"idToken": {
"idToken": "AABBCCDD",
"type": "ISO14443"
}
}| Field | Value | Description |
|---|---|---|
connectorType | string (max 20) | Connector type enum value (e.g. cCCS1, cCCS2, cCHAdeMO, etc.). Values defined in Appendix as ConnectorEnumStringType. |
evseId | omitted | Do NOT include evseId when reserving by connector type. |
CSMS Implementation Steps
- Same as S1, but include
connectorTypeand do NOT includeevseId. - Send
ReserveNowRequest. - Process
ReserveNowResponse.
Prerequisite: The Charging Station has at least one available EVSE with the specified connector type.
Handling the ReserveNowResponse
When the CSMS receives a ReserveNowResponse,
it must handle each possible status value:
{
"status": "Accepted",
"statusInfo": {
"reasonCode": "string (max 20)",
"additionalInfo": "string (max 1024)"
}
}| Status | Meaning | CSMS Action |
|---|---|---|
Accepted | Reservation was successful. | Store reservation (id, station, evseId, idToken, expiry) in DB. Mark reservation as active. Optionally notify EV Driver. |
Rejected | Charging Station is configured to not accept reservations. | Inform EV Driver that reservation failed. Consider retrying on a different station. |
Occupied | All targeted EVSEs have status Reserved or Occupied. | Inform EV Driver. Optionally queue and retry later. |
Faulted | All targeted EVSEs have status Faulted. | Inform EV Driver. Do not retry on same station/EVSE until fault is resolved. |
Unavailable | All targeted EVSEs have status Unavailable. | Inform EV Driver. Do not retry until station reports availability. |
Reservation Replacement (H01.FR.02)
If the id in ReserveNowRequest matches
an existing reservation on the Charging Station, the old reservation is replaced with the new one. The CSMS can use this to update an existing reservation's parameters.
Requirements Reference (H01)
These are the Charging Station requirements. The CSMS must be aware of these behaviors to correctly interpret responses and status updates.
| Req ID | What the CS Does | CSMS Implication |
|---|---|---|
H01.FR.01 | If configured to not accept reservations, returns Rejected. | Handle Rejected status. |
H01.FR.02 | If id matches existing reservation, replaces it. | Use same id to update a reservation. Use new id for a new reservation. |
H01.FR.03 | If id does not match, returns Accepted on success. | Normal success path. |
H01.FR.04 | Accepts reservation without evseId if at least one EVSE is Available AND ReservationNonEvseSpecific = true. | Only send without evseId if station supports it. |
H01.FR.06 | Accepts reservation with connectorType if at least one EVSE with that connector type is Available AND ReservationNonEvseSpecific = true. | Only send with connectorType if station supports it. |
H01.FR.07 | When accepted without evseId, CS ensures one EVSE remains available for the reserved IdToken during validity. | CSMS can trust the reservation is honored. |
H01.FR.09 | When accepted with connectorType, CS ensures one connector of that type remains available. | CSMS can trust the reservation is honored. |
H01.FR.11 | Returns Occupied if all targeted EVSEs are Reserved or Occupied. | Handle Occupied status. |
H01.FR.12 | Returns Faulted if all targeted EVSEs are Faulted. | Handle Faulted status. |
H01.FR.14 | Returns Unavailable if all targeted EVSEs are Unavailable. | Handle Unavailable status. |
H01.FR.15 | When transaction starts for reserved IdToken, CS sends reservationId in TransactionEventRequest. | CSMS should match reservationId in incoming TransactionEventRequest to mark reservation as consumed. |
H01.FR.16 | When targeted EVSE status changes to Faulted, CS cancels reservation and sends ReservationStatusUpdate with Removed. | Handle incoming ReservationStatusUpdateRequest. |
H01.FR.17 | When targeted EVSE status changes to Unavailable, CS cancels reservation and sends ReservationStatusUpdate with Removed. | Handle incoming ReservationStatusUpdateRequest. |
H01.FR.18 | If ReservationNonEvseSpecific = true, CS accepts reservations on unspecified EVSE. | Check station config before sending unspecified reservation. |
H01.FR.19 | If ReservationNonEvseSpecific is not set or false, CS rejects unspecified EVSE reservations. | Expect Rejected if station doesn't support this. |
H01.FR.20 | When accepted without evseId and available EVSEs = reservations count, CS sends NotifyEventRequest for all connectors with AvailabilityState = Reserved. | Expect and handle these NotifyEventRequest messages. |
H01.FR.23 | When accepted with evseId, CS sends NotifyEventRequest for all connectors of that EVSE with AvailabilityState = Reserved. | Expect and handle these NotifyEventRequest messages. |
H01.FR.24 | When reservations for a specific connectorType equals available EVSEs with that type, CS sends NotifyEventRequest for connectors with AvailabilityState = Reserved. | Expect and handle these NotifyEventRequest messages. |
4. H02 — Cancel Reservation (CSMS-Initiated)
CSMS-Initiated| Use Case ID | H02 |
| Objective | Cancel an existing reservation on a Charging Station |
| Actors | Charging Station, CSMS, EV Driver |
| OCPP Messages | CancelReservationRequest / CancelReservationResponse |
User CSMS Charging Station
| | |
|-- cancel request ->| |
| |--- CancelReservationRequest ----->|
| | (reservationId) |
| | |
| |<-- CancelReservationResponse -----|
| | (status = Accepted) |
| | |
| |<-- NotifyEventRequest ------------|
| | (component=Connector, |
| | variable=AvailabilityState, |
| | actualValue=Available) |
| | |
| |--- NotifyEventResponse ---------->|{
"reservationId": 12345
}| Field | Type | Required | Description |
|---|---|---|---|
reservationId | integer (≥ 0) | Yes | The ID of the reservation to cancel (same id used in the original ReserveNowRequest). |
CSMS Implementation Steps
- Receive cancellation request from EV Driver or internal logic.
- Look up the reservation by its ID to find the associated Charging Station.
- Send
CancelReservationRequestwith thereservationId. - Process the
CancelReservationResponse. - If Accepted: mark reservation as cancelled in the database. Expect incoming
NotifyEventRequestmessages indicating connectors/EVSEs are nowAvailable. Respond to each with aNotifyEventResponse. Update internal EVSE state tracking. - If Rejected: the reservation ID was not found on the Charging Station. Verify the reservation state in the CSMS database.
Important: The Charging Station does NOT send a ReservationStatusUpdateRequest when a reservation is cancelled by the CSMS, because the CSMS is already aware of the cancellation.
Handling the CancelReservationResponse
{
"status": "Accepted",
"statusInfo": {
"reasonCode": "string (max 20)",
"additionalInfo": "string (max 1024)"
}
}| Status | Meaning | CSMS Action |
|---|---|---|
Accepted | Reservation was found and cancelled. | Remove/deactivate reservation in DB. Update EVSE state. |
Rejected | No matching reservationId found on Charging Station. | Log the mismatch. Check if reservation was already expired/consumed. Clean up DB state. |
Requirements Reference (H02)
| Req ID | What the CS Does | CSMS Implication |
|---|---|---|
H02.FR.01 | Returns Rejected if no matching reservationId. | Handle gracefully — may have already expired. |
H02.FR.02 | Cancels the reservation if reservationId is valid. | Expect success. |
H02.FR.03 | If a specific EVSE was reserved, allows charging again on that EVSE. | EVSE becomes available. |
H02.FR.04 | Sends StatusNotificationRequest (deprecated) or NotifyEventRequest with AvailabilityState = Available for all connectors. | Handle incoming availability updates. |
H02.FR.05 | If no specific EVSE was reserved, allows charging on all EVSEs. | All EVSEs may report availability changes. |
H02.FR.06 | If the amount of EVSEs reserved was equal to available EVSEs, sends NotifyEventRequest with AvailabilityState = Available for connectors that were not explicitly reserved. | Handle multiple NotifyEventRequest messages. |
5. H03 — Use a Reserved EVSE
CS-Driven| Use Case ID | H03 |
| Objective | Handle the scenario when an EV Driver uses a reserved EVSE |
| Actors | Charging Station, CSMS, EV Driver |
| CSMS Role | Handle AuthorizeRequest messages and return groupIdToken information |
S1 — IdToken Matches Reservation
The EV Driver presents the exact IdToken that was used in the reservation. The Charging Station handles this locally.
EV Driver Charging Station CSMS
| | |
|-- Present TOKEN_A -->| |
| | (matches reservation) |
| | connector -> Available |
| | |
| [opt: AuthorizeRequest] --------->|
| | |
| |<--- AuthorizeResponse ---|
| | (status=Accepted) |
| | |
| | Start transaction |
| |--- TransactionEventReq ->|
| | (reservationId=12345) |CSMS Role
- Handle
AuthorizeRequest(optional, may or may not arrive): Validate theidToken. ReturnAuthorizeResponsewithidTokenInfo.status = "Accepted". If the reservation has agroupIdToken, include it in the response. - Handle
TransactionEventRequest: The Charging Station includes thereservationIdin theTransactionEventRequestwhen the transaction starts. Match thereservationIdto the active reservation in the DB. Mark the reservation as consumed/used.
Alternative: TxStartPoint = "EVConnected", Cable plugged in first
- EV Driver connects the cable.
- Charging Station starts a transaction (connector remains
Reserved). - EV Driver presents the matching
IdToken. - Charging Station matches it with the reservation and connector becomes
Occupied. - Transaction proceeds as E02 (Start Transaction - Cable Plugin First).
S2 — GroupIdToken Matches Reservation
The EV Driver presents an IdToken that
does not directly match the reservation's idToken,
but the reservation has a groupIdToken.
The Charging Station needs to resolve the group membership.
EV Driver Charging Station CSMS
| | |
|-- Present TOKEN_A -->| |
| | (does NOT match |
| | reservation idToken) |
| | |
| [alt: Lookup groupIdToken of TOKEN_A] |
| [in Auth Cache or Local Auth List] |
| | |
| [If NOT found locally:] |
| |--- AuthorizeRequest ---->|
| | (idToken=TOKEN_A) |
| | |
| |<-- AuthorizeResponse ----|
| | (idTokenInfo.status |
| | =Accepted, |
| | groupIdToken |
| | =TOKEN_B) |
| | |
| | groupIdTokens match! |
| | reservation consumed |
| | connector -> Occupied |
| | Start transaction |CSMS Role — Handling AuthorizeRequest for Group Resolution
This is the critical CSMS responsibility in flow H03. When the Charging Station
sends an AuthorizeRequest:
- Validate the incoming
idToken. - Look up the
groupIdTokenassociated with thisidTokenin the CSMS user/token database. - Return
AuthorizeResponsewithidTokenInfo.status: "Accepted"and theidTokenInfo.groupIdToken.
{
"idTokenInfo": {
"status": "Accepted",
"groupIdToken": {
"idToken": "GROUP001",
"type": "Central"
}
}
}The Charging Station then compares the returned groupIdToken with the reservation's groupIdToken.
If they match, the reservation is consumed.
S3 — Unspecified EVSE Reservation with Available Connector
The reservation was made for an unspecified EVSE and multiple EVSEs are available. The connector
status is Available (not Reserved).
Behavior is identical to S1 — the Charging Station matches the IdToken with the reservation and proceeds
with the transaction. The CSMS handles it the same way.
Alternative: TxStartPoint = "EVConnected", Cable plugged in first
- EV Driver connects the cable.
- Charging Station reports connector as
Occupied. - Charging Station starts a transaction.
- EV Driver presents the matching
IdToken. - Charging Station matches it with the reservation.
- Optional
AuthorizeRequestto CSMS. - Transaction proceeds as E02.
CSMS AuthorizeResponse with GroupIdToken
When implementing the AuthorizeRequest handler, the CSMS must include groupIdToken in the response whenever
the authorized token belongs to a group. This is essential for the Charging Station to match tokens
against reservations made with groupIdToken.
function handleAuthorizeRequest(request):
idToken = request.idToken
// 1. Validate the token
tokenInfo = lookupToken(idToken)
if tokenInfo is invalid:
return AuthorizeResponse(status = "Invalid")
// 2. Look up group membership
groupIdToken = lookupGroupIdToken(idToken)
// 3. Build response with groupIdToken if available
response = AuthorizeResponse(
idTokenInfo.status = "Accepted",
idTokenInfo.groupIdToken = groupIdToken // CRITICAL for reservation matching
)
return responseUnmatched token behavior: If an idToken is presented that does not match the reservation (and groupIdTokens do not match either),
the token is not authorized to charge.
- If
TxStartPoint = AuthorizedorPowerPathClosed: transaction would NOT be started. - If
TxStartPoint = EVConnectedorParkingBayOccupancy: a transaction would be started by cable plug-in/parking, but charging would NOT start. The transaction ends at cable plug-out.
Requirements Reference (H03)
| Req ID | What the CS Does | CSMS Implication |
|---|---|---|
H03.FR.01 | Allows charging when IdToken matches reservation for a specific evseId. | Normal authorization flow. |
H03.FR.02 | Allows charging when IdToken matches reservation for a specific connectorType. | Normal authorization flow. |
H03.FR.03 | Allows charging when IdToken matches reservation without specific evseId or connectorType. | Normal authorization flow. |
H03.FR.04 | With groupIdToken: allows charging when IdToken OR groupIdToken matches. | CSMS must return groupIdToken in AuthorizeResponse. |
H03.FR.05 | With groupIdToken + connectorType: allows IdToken or groupIdToken match. | CSMS must return groupIdToken in AuthorizeResponse. |
H03.FR.06 | With groupIdToken, no specific evseId: allows IdToken or groupIdToken match on any EVSE. | CSMS must return groupIdToken in AuthorizeResponse. |
H03.FR.07 | CS may look up groupIdToken in Local Auth List/Cache. | May not send AuthorizeRequest if found locally. |
H03.FR.08 | If IdToken not found locally, CS sends AuthorizeRequest to CSMS. | CSMS must handle this and return groupIdToken. |
H03.FR.09 | When matching idToken/groupIdToken is presented, reservation is consumed. | CSMS should expect TransactionEventRequest with reservationId. |
H03.FR.10 | After consumption, connector status becomes Available (if no cable) or Occupied (if cable plugged). | Expect NotifyEventRequest with status changes. |
H03.FR.11 | If token matches but no transaction starts within EVConnectionTimeout, CS sends ReservationStatusUpdateRequest with status=NoTransaction. | CSMS must handle this status update. |
6. H04 — Reservation Ended, Not Used
Incoming to CSMS| Use Case ID | H04 |
| Objective | Handle notification from a Charging Station that a reservation has expired without being used |
| Actors | Charging Station, CSMS |
Charging Station CSMS
| |
| (expiryDateTime reached) |
| Reservation removed |
| |
| [alt: Specific EVSE was reserved] |
|--- NotifyEventRequest ---------------------->|
| (component=Connector, |
| variable=AvailabilityState, |
| actualValue=Available) |
| |
|<-- NotifyEventResponse ----------------------|
| |
|--- NotifyEventRequest ---------------------->|
| (component=EVSE, |
| variable=AvailabilityState, |
| actualValue=Available) |
| |
|<-- NotifyEventResponse ----------------------|
| |
|--- ReservationStatusUpdateRequest ---------->|
| (reservationId, status=Expired) |
| |
|<-- ReservationStatusUpdateResponse ----------|
| (empty body) |Handling ReservationStatusUpdateRequest
This is the primary incoming message the CSMS must handle for reservation lifecycle management.
{
"reservationId": 12345,
"reservationUpdateStatus": "Expired"
}| Field | Type | Required | Description |
|---|---|---|---|
reservationId | integer (≥ 0) | Yes | The reservation ID. |
reservationUpdateStatus | enum string | Yes | The status update. |
Possible reservationUpdateStatus Values
| Value | Meaning | When Sent | CSMS Action |
|---|---|---|---|
Expired | The reservation's expiryDateTime was reached and the EV Driver did not use it. | When the expiry time passes without the reservation being consumed. | Mark reservation as expired in DB. Free up internal tracking. Optionally notify EV Driver. |
Removed | The reservation was removed because the targeted EVSE became Faulted or Unavailable. | When EVSE status changes to Faulted (H01.FR.16) or Unavailable (H01.FR.17). | Mark reservation as removed in DB. Optionally offer EV Driver a new reservation on a different station/EVSE. |
NoTransaction | The matching token was presented but no transaction was started within EVConnectionTimeout. | When idToken/groupIdToken matched but cable was never plugged in within timeout. | Mark reservation as no_transaction in DB. Investigate potential issues. Optionally notify EV Driver. |
{}The response body is empty (no required fields). Only the optional customData field may be included.
function handleReservationStatusUpdateRequest(request):
reservationId = request.reservationId
status = request.reservationUpdateStatus
// 1. Look up the reservation
reservation = db.findReservation(reservationId)
if reservation is null:
log.warn("Received status update for unknown reservation: " + reservationId)
// Still respond with empty response
return ReservationStatusUpdateResponse({})
// 2. Update reservation state
switch (status):
case "Expired":
reservation.status = "expired"
reservation.endReason = "timeout"
notifyDriver(reservation, "Your reservation has expired.")
case "Removed":
reservation.status = "removed"
reservation.endReason = "evse_unavailable"
notifyDriver(reservation, "Your reservation was cancelled due to EVSE issues.")
// Consider automatically creating a new reservation elsewhere
case "NoTransaction":
reservation.status = "no_transaction"
reservation.endReason = "no_cable_connected"
notifyDriver(reservation, "You were identified but did not start charging.")
db.saveReservation(reservation)
// 3. Return empty response
return ReservationStatusUpdateResponse({})Requirements Reference (H04)
| Req ID | What the CS Does | CSMS Implication |
|---|---|---|
H04.FR.01 | Sends ReservationStatusUpdateRequest with Expired when expiryDateTime is reached. | Must handle and update reservation state. |
H04.FR.02 | If a specific EVSE was reserved, allows charging again on it. | EVSE becomes available. |
H04.FR.03 | Sends NotifyEventRequest with AvailabilityState = Available for all connectors of the previously reserved EVSE. | Handle availability updates. |
7. JSON Schemas
ReferenceReserveNowRequest
Schema ID: urn:OCPP:Cp:2:2025:1:ReserveNowRequest · Direction: CSMS → Charging Station
{
"id": "<integer, >= 0, REQUIRED>",
"expiryDateTime": "<string, date-time ISO 8601, REQUIRED>",
"idToken": {
"idToken": "<string, max 255, REQUIRED>",
"type": "<string, max 20, REQUIRED>",
"additionalInfo": [
{
"additionalIdToken": "<string, max 255, REQUIRED>",
"type": "<string, max 50, REQUIRED>"
}
]
},
"evseId": "<integer, >= 0, OPTIONAL>",
"connectorType": "<string, max 20, OPTIONAL>",
"groupIdToken": {
"idToken": "<string, max 255>",
"type": "<string, max 20>"
},
"customData": {
"vendorId": "<string, max 255, REQUIRED if customData present>"
}
}| Field | Type | Constraints | Description |
|---|---|---|---|
id | integer | ≥ 0 | Reservation identifier. If it matches an existing reservation on the CS, the old reservation is replaced. |
expiryDateTime | string | ISO 8601 date-time | Expiration timestamp of the reservation. |
idToken | IdTokenType | object | The token this reservation is for. |
idToken.idToken | string | max 255 chars | Case-insensitive identifier (e.g. RFID UID, UUID). |
idToken.type | string | max 20 chars | Token type (e.g. Central, ISO14443, ISO15693, eMAID, KeyCode, Local, MacAddress, NoAuthorization). |
idToken.additionalInfo | array | min 1 item if present | Additional identification info. |
evseId | integer | ≥ 0 | ID of the EVSE to reserve. Omit for unspecified EVSE. |
connectorType | string | max 20 chars | Connector type to reserve. Values from ConnectorEnumStringType. |
groupIdToken | IdTokenType | object | Group token — any token in this group may use the reservation. |
ReserveNowResponse
Schema ID: urn:OCPP:Cp:2:2025:1:ReserveNowResponse · Direction: Charging Station → CSMS
{
"status": "<ReserveNowStatusEnumType, REQUIRED>",
"statusInfo": {
"reasonCode": "<string, max 20, REQUIRED>",
"additionalInfo": "<string, max 1024, OPTIONAL>"
},
"customData": {
"vendorId": "<string, max 255>"
}
}| Value | Description |
|---|---|
Accepted | Reservation has been made. |
Faulted | Reservation could not be made, all targeted EVSEs are faulted. |
Occupied | Reservation could not be made, all targeted EVSEs are occupied or already reserved. |
Rejected | Reservation could not be made (station configured to reject, or policy reason). |
Unavailable | Reservation could not be made, all targeted EVSEs are unavailable. |
CancelReservationRequest
Schema ID: urn:OCPP:Cp:2:2025:1:CancelReservationRequest · Direction: CSMS → Charging Station
{
"reservationId": "<integer, >= 0, REQUIRED>",
"customData": {
"vendorId": "<string, max 255>"
}
}| Field | Type | Constraints | Description |
|---|---|---|---|
reservationId | integer | ≥ 0 | ID of the reservation to cancel. Must match the id used in the original ReserveNowRequest. |
CancelReservationResponse
Schema ID: urn:OCPP:Cp:2:2025:1:CancelReservationResponse · Direction: Charging Station → CSMS
{
"status": "<CancelReservationStatusEnumType, REQUIRED>",
"statusInfo": {
"reasonCode": "<string, max 20, REQUIRED>",
"additionalInfo": "<string, max 1024, OPTIONAL>"
},
"customData": {
"vendorId": "<string, max 255>"
}
}| Value | Description |
|---|---|
Accepted | Reservation has been cancelled. |
Rejected | No reservation with this reservationId was found. |
ReservationStatusUpdateRequest
Schema ID: urn:OCPP:Cp:2:2025:1:ReservationStatusUpdateRequest · Direction: Charging Station → CSMS
{
"reservationId": "<integer, >= 0, REQUIRED>",
"reservationUpdateStatus": "<ReservationUpdateStatusEnumType, REQUIRED>",
"customData": {
"vendorId": "<string, max 255>"
}
}| Value | Description |
|---|---|
Expired | Reservation has expired (expiryDateTime reached, not used). |
Removed | Reservation was removed because the targeted EVSE became Faulted or Unavailable. |
NoTransaction | The matching token was presented but no transaction started within EVConnectionTimeout. |
ReservationStatusUpdateResponse
Schema ID: urn:OCPP:Cp:2:2025:1:ReservationStatusUpdateResponse · Direction: CSMS → Charging Station
{
"customData": {
"vendorId": "<string, max 255>"
}
}Note: The response body can be empty {}. There are no required fields.
8. Data Types Reference
ReferenceIdTokenType
{
"idToken": "string (max 255, REQUIRED)",
"type": "string (max 20, REQUIRED)",
"additionalInfo": [
{
"additionalIdToken": "string (max 255, REQUIRED)",
"type": "string (max 50, REQUIRED)"
}
]
}Common type values:
CentraleMAIDISO14443ISO15693KeyCodeLocalMacAddressNoAuthorizationStatusInfoType
{
"reasonCode": "string (max 20, REQUIRED, case-insensitive)",
"additionalInfo": "string (max 1024, OPTIONAL)"
}CustomDataType
{
"vendorId": "string (max 255, REQUIRED)"
}Can be extended with arbitrary JSON properties for vendor-specific data.
ConnectorEnumStringType (common values)
| Value | Description |
|---|---|
cCCS1 | Combined Charging System 1 (SAE J1772) |
cCCS2 | Combined Charging System 2 (IEC 62196) |
cCHAdeMO | CHAdeMO connector |
cType1 | Type 1 (SAE J1772) |
cType2 | Type 2 (IEC 62196) |
cGBT | GB/T connector |
cTesla | Tesla connector |
sType2 | Type 2 socket |
sType3 | Type 3 socket |
Full list defined in OCPP 2.1 Appendix as ConnectorEnumStringType.
9. Configuration Variables
ReferenceThese Charging Station configuration variables affect reservation behavior. The CSMS should be aware of their settings.
| Variable | Type | Description | Impact on CSMS |
|---|---|---|---|
ReservationNonEvseSpecific | boolean | When true, the CS accepts
reservations without a specific evseId. When false or not set, such
reservations are rejected. | CSMS should check this before sending unspecified EVSE reservations. If false, always include evseId. |
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. |
10. CSMS Implementation Checklist
ChecklistOutgoing Message Handlers (CSMS Sends)
ReserveNowRequest sender
- Generate unique reservation IDs (integer ≥ 0)
- Populate required fields:
id,expiryDateTime,idToken - Support optional
evseIdfor specific EVSE reservations - Support optional
connectorTypefor connector-type reservations - Support optional
groupIdTokenfor group-based reservations - Use same
idto replace/update an existing reservation - Validate schema before sending
CancelReservationRequest sender
- Look up the correct
reservationId - Send to the correct Charging Station
- Validate schema before sending
ReservationStatusUpdateResponse sender
- Return empty response body
{}
NotifyEventResponse sender
- Return empty response body for each
NotifyEventRequestreceived
Incoming Message Handlers (CSMS Receives)
ReserveNowResponse handler
- Handle
Accepted— store reservation in DB, mark active - Handle
Rejected— notify user, check station config - Handle
Occupied— notify user, optionally retry later - Handle
Faulted— notify user, do not retry - Handle
Unavailable— notify user, do not retry - Log
statusInfowhen present
CancelReservationResponse handler
- Handle
Accepted— remove reservation from DB - Handle
Rejected— log mismatch, verify DB state
ReservationStatusUpdateRequest handler
- Handle
Expired— mark reservation expired in DB - Handle
Removed— mark reservation removed in DB (EVSE faulted/unavailable) - Handle
NoTransaction— mark reservation as no-transaction - Always respond with empty
ReservationStatusUpdateResponse
NotifyEventRequest handler (reservation-related)
- Handle
AvailabilityState = Reserved— update EVSE/connector state - Handle
AvailabilityState = Available— update EVSE/connector state (after cancellation or expiry) - Respond with
NotifyEventResponse
AuthorizeRequest handler (reservation-aware)
- Return
groupIdTokeninAuthorizeResponsewhen the token belongs to a group - This is critical for Charging Stations to match tokens against
groupIdTokenreservations
TransactionEventRequest handler (reservation-aware)
- Check for
reservationIdfield in incoming transaction events - When present, mark the corresponding reservation as consumed/used
Database Schema Suggestions
Reservations table fields
id(integer, primary key — matches OCPP reservation id)charging_station_id(FK)evse_id(nullable integer)connector_type(nullable string)id_token(string)id_token_type(string)group_id_token(nullable string)group_id_token_type(nullable string)expiry_date_time(timestamp)status(enum:active,expired,removed,cancelled,consumed,no_transaction)created_at(timestamp)updated_at(timestamp)
Reservation Lifecycle State Machine
ReserveNowResponse
(status=Accepted)
|
v
[Created] -----> [Active] -----> [Expired] (H04: expiryDateTime reached)
|
+----------> [Cancelled] (H02: CSMS sends CancelReservationRequest)
|
+----------> [Consumed] (H03: matching token presented, transaction started)
|
+----------> [Removed] (H01.FR.16/17: EVSE faulted/unavailable)
|
+----------> [NoTransaction] (H03.FR.11: token matched, no transaction started)