OCPP 2.1 Edition 2 Section H

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).

10 Sections
4 Use Cases
H01 – H04

1. Overview

Introduction

The 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 CancelReservationRequest

Receiver for:

ReservationStatusUpdateRequest NotifyEventRequest AuthorizeRequest

2. 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.

Sequence Diagram (CSMS perspective)
EV Driver            CSMS                          Charging Station
    |                  |                                  |
    |--- reserve ----->|                                  |
    |                  |--- ReserveNowRequest ----------->|
    |                  |    (id, expiryDateTime, idToken)  |
    |                  |    (NO evseId)                    |
    |                  |                                  |
    |                  |<-- ReserveNowResponse ------------|
    |                  |    (status = Accepted)            |
    |<-- notification -|                                  |
ReserveNowRequest — Unspecified EVSE
{
  "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

  1. Receive reservation request from EV Driver (via app/API).
  2. Generate a unique id (integer ≥ 0) for the reservation.
  3. Set expiryDateTime to the desired expiry time.
  4. Populate idToken with the EV Driver's token info.
  5. Do NOT include evseId or connectorType.
  6. Optionally include groupIdToken if group-based reservation is desired.
  7. Send ReserveNowRequest to the target Charging Station.
  8. 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.

Sequence Diagram (CSMS perspective)
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 -|                                  |
ReserveNowRequest — Specific EVSE
{
  "id": 12346,
  "expiryDateTime": "2025-12-15T14:30:00Z",
  "evseId": 1,
  "idToken": {
    "idToken": "AABBCCDD",
    "type": "ISO14443"
  },
  "groupIdToken": {
    "idToken": "GROUP001",
    "type": "Central"
  }
}

CSMS Implementation Steps

  1. Same as S1, but include evseId specifying the target EVSE.
  2. Send ReserveNowRequest.
  3. Process ReserveNowResponse.
  4. Expect incoming NotifyEventRequest messages from the Charging Station reporting connector and EVSE availability changes to Reserved.
  5. Respond to each NotifyEventRequest with an empty NotifyEventResponse.
  6. Update internal EVSE state tracking to reflect Reserved status.

Prerequisite: The specified EVSE has status Available.

Post-conditions on success

  • Charging Station accepted the ReserveNowRequest
  • Charging Station sent NotifyEventRequest with component.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.

Sequence Diagram (CSMS perspective)
EV Driver            CSMS                          Charging Station
    |                  |                                  |
    |--- reserve ----->|                                  |
    |                  |--- ReserveNowRequest ----------->|
    |                  |    (id, expiryDateTime, idToken,  |
    |                  |     connectorType, NO evseId)     |
    |                  |                                  |
    |                  |<-- ReserveNowResponse ------------|
    |                  |    (status = Accepted)            |
    |<-- notification -|                                  |
ReserveNowRequest — Connector Type
{
  "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

  1. Same as S1, but include connectorType and do NOT include evseId.
  2. Send ReserveNowRequest.
  3. 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:

ReserveNowResponse
{
  "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
Sequence Diagram (CSMS perspective)
User                 CSMS                          Charging Station
  |                    |                                  |
  |-- cancel request ->|                                  |
  |                    |--- CancelReservationRequest ----->|
  |                    |    (reservationId)                |
  |                    |                                  |
  |                    |<-- CancelReservationResponse -----|
  |                    |    (status = Accepted)            |
  |                    |                                  |
  |                    |<-- NotifyEventRequest ------------|
  |                    |    (component=Connector,          |
  |                    |     variable=AvailabilityState,   |
  |                    |     actualValue=Available)        |
  |                    |                                  |
  |                    |--- NotifyEventResponse ---------->|
CancelReservationRequest
{
  "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

  1. Receive cancellation request from EV Driver or internal logic.
  2. Look up the reservation by its ID to find the associated Charging Station.
  3. Send CancelReservationRequest with the reservationId.
  4. Process the CancelReservationResponse.
  5. If Accepted: mark reservation as cancelled in the database. Expect incoming NotifyEventRequest messages indicating connectors/EVSEs are now Available. Respond to each with a NotifyEventResponse. Update internal EVSE state tracking.
  6. 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

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.

Sequence Diagram — TxStartPoint = "Authorized", IdToken presented first
EV Driver            Charging Station              CSMS
    |                      |                          |
    |-- Present TOKEN_A -->|                          |
    |                      | (matches reservation)    |
    |                      | connector -> Available    |
    |                      |                          |
    |                [opt: AuthorizeRequest] --------->|
    |                      |                          |
    |                      |<--- AuthorizeResponse ---|
    |                      |     (status=Accepted)    |
    |                      |                          |
    |                      | Start transaction        |
    |                      |--- TransactionEventReq ->|
    |                      |    (reservationId=12345)  |

CSMS Role

  1. Handle AuthorizeRequest (optional, may or may not arrive): Validate the idToken. Return AuthorizeResponse with idTokenInfo.status = "Accepted". If the reservation has a groupIdToken, include it in the response.
  2. Handle TransactionEventRequest: The Charging Station includes the reservationId in the TransactionEventRequest when the transaction starts. Match the reservationId to the active reservation in the DB. Mark the reservation as consumed/used.

Alternative: TxStartPoint = "EVConnected", Cable plugged in first

  1. EV Driver connects the cable.
  2. Charging Station starts a transaction (connector remains Reserved).
  3. EV Driver presents the matching IdToken.
  4. Charging Station matches it with the reservation and connector becomes Occupied.
  5. 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.

Sequence Diagram — GroupIdToken Resolution
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:

  1. Validate the incoming idToken.
  2. Look up the groupIdToken associated with this idToken in the CSMS user/token database.
  3. Return AuthorizeResponse with idTokenInfo.status: "Accepted" and the idTokenInfo.groupIdToken.
AuthorizeResponse from CSMS (with 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

  1. EV Driver connects the cable.
  2. Charging Station reports connector as Occupied.
  3. Charging Station starts a transaction.
  4. EV Driver presents the matching IdToken.
  5. Charging Station matches it with the reservation.
  6. Optional AuthorizeRequest to CSMS.
  7. 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.

CSMS AuthorizeRequest Handler (reservation-aware pseudocode)
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 response

Unmatched 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 = Authorized or PowerPathClosed: transaction would NOT be started.
  • If TxStartPoint = EVConnected or ParkingBayOccupancy: 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
Sequence Diagram (CSMS perspective)
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.

ReservationStatusUpdateRequest
{
  "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.
ReservationStatusUpdateResponse (always empty)
{}

The response body is empty (no required fields). Only the optional customData field may be included.

CSMS Handler Pseudocode
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

Reference

ReserveNowRequest

Schema ID: urn:OCPP:Cp:2:2025:1:ReserveNowRequest  ·  Direction: CSMS → Charging Station

ReserveNowRequest Schema
{
  "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

ReserveNowResponse Schema
{
  "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

CancelReservationRequest Schema
{
  "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

CancelReservationResponse Schema
{
  "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

ReservationStatusUpdateRequest Schema
{
  "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

ReservationStatusUpdateResponse Schema
{
  "customData": {
    "vendorId": "<string, max 255>"
  }
}

Note: The response body can be empty {}. There are no required fields.

8. Data Types Reference

Reference

IdTokenType

IdTokenType Schema
{
  "idToken": "string (max 255, REQUIRED)",
  "type": "string (max 20, REQUIRED)",
  "additionalInfo": [
    {
      "additionalIdToken": "string (max 255, REQUIRED)",
      "type": "string (max 50, REQUIRED)"
    }
  ]
}

Common type values:

CentraleMAIDISO14443ISO15693KeyCodeLocalMacAddressNoAuthorization

StatusInfoType

StatusInfoType Schema
{
  "reasonCode": "string (max 20, REQUIRED, case-insensitive)",
  "additionalInfo": "string (max 1024, OPTIONAL)"
}

CustomDataType

CustomDataType Schema
{
  "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

Reference

These 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

Checklist

Outgoing Message Handlers (CSMS Sends)

ReserveNowRequest sender

  • Generate unique reservation IDs (integer ≥ 0)
  • Populate required fields: id, expiryDateTime, idToken
  • Support optional evseId for specific EVSE reservations
  • Support optional connectorType for connector-type reservations
  • Support optional groupIdToken for group-based reservations
  • Use same id to 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 NotifyEventRequest received

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 statusInfo when 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 groupIdToken in AuthorizeResponse when the token belongs to a group
  • This is critical for Charging Stations to match tokens against groupIdToken reservations

TransactionEventRequest handler (reservation-aware)

  • Check for reservationId field 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

Reservation State Transitions
                  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)

OCPP 2.1 Reservation Flows (H01–H04) - CSMS Developer Guide. Based on OCPP 2.1 Edition 2 Specification (Part 2), Section H.