OCPP 2.1 Edition 2 Section D

Local Authorization List Management - CSMS Developer Guide

Based on OCPP 2.1 Edition 2 Specification (Part 2), Section D (Local Authorization List Management). This guide covers all flows for managing the Local Authorization List on Charging Stations, including sending full and differential updates, querying list versions, synchronization strategies, and error handling from the CSMS perspective using OCPP-J (JSON over WebSocket).

8 Sections
2 Use Cases
D01 – D02

1. Overview

Introduction

The Local Authorization List is a list of identifier tokens (idTokens) that the CSMS pushes to Charging Stations. It enables offline authorization (Charging Stations can authorize users without CSMS connectivity) and reduced latency (when online, local list lookups are faster than round-trip CSMS authorization).

Key Point: The CSMS is the initiator of both operations in this functional block. The Charging Station never sends unsolicited list updates.

Operations Summary

Operation Direction Initiated By Purpose
GetLocalListVersion CSMS → CS → CSMS CSMS Query current list version on Charging Station
SendLocalList CSMS → CS → CSMS CSMS Push a full or differential list update to Charging Station

Prerequisites

The Charging Station must have LocalAuthListEnabled configuration variable set to true for the list to be active. The CSMS can read/write this variable via the GetVariables / SetVariables messages (Provisioning functional block).

2. Data Types & Schemas

Reference

SendLocalListRequest Schema

Schema ID: urn:OCPP:Cp:2:2025:1:SendLocalListRequest

Direction: CSMS → Charging Station

SendLocalListRequest Schema
{
  "versionNumber": "integer (> 0)",       // REQUIRED - version to assign after update
  "updateType": "Full | Differential",    // REQUIRED - type of update
  "localAuthorizationList": [             // OPTIONAL - array of AuthorizationData
    {
      "idToken": {                        // REQUIRED - IdTokenType
        "idToken": "string (max 255)",    // REQUIRED - case insensitive identifier
        "type": "string (max 20)",        // REQUIRED - e.g. "ISO14443", "eMAID"
        "additionalInfo": [               // OPTIONAL
          {
            "additionalIdToken": "string (max 255)",  // REQUIRED
            "type": "string (max 50)"                 // REQUIRED
          }
        ]
      },
      "idTokenInfo": {                              // OPTIONAL - presence controls operation
        "status": "AuthorizationStatusEnumType",    // REQUIRED
        "cacheExpiryDateTime": "date-time",         // OPTIONAL
        "chargingPriority": "integer (-9..9)",      // OPTIONAL - default 0
        "groupIdToken": { ... },                    // OPTIONAL - IdTokenType
        "language1": "string (max 8)",              // OPTIONAL - RFC 5646
        "language2": "string (max 8)",              // OPTIONAL - must differ from language1
        "evseId": [1, 2],                           // OPTIONAL - restrict to specific EVSEs
        "personalMessage": {                        // OPTIONAL - MessageContentType
          "format": "ASCII|HTML|URI|UTF8|QRCODE",  // REQUIRED
          "content": "string (max 1024)",           // REQUIRED
          "language": "string (max 8)"              // OPTIONAL
        }
      }
    }
  ]
}

SendLocalListResponse Schema

Direction: Charging Station → CSMS

SendLocalListResponse Schema
{
  "status": "Accepted | Failed | VersionMismatch",  // REQUIRED
  "statusInfo": {                                     // OPTIONAL
    "reasonCode": "string (max 20)",                  // REQUIRED
    "additionalInfo": "string (max 1024)"             // OPTIONAL
  }
}

GetLocalListVersionRequest Schema

Schema ID: urn:OCPP:Cp:2:2025:1:GetLocalListVersionRequest

Direction: CSMS → Charging Station

GetLocalListVersionRequest Schema
{
  // No required fields - simple query request
  "customData": { ... }  // OPTIONAL - vendor-specific custom data
}

Note: This is a simple request with no required fields. An empty JSON {} is a valid request.

GetLocalListVersionResponse Schema

Direction: Charging Station → CSMS

GetLocalListVersionResponse Schema
{
  "versionNumber": "integer"  // REQUIRED - current list version on CS
                               // 0 = no list installed
                               // > 0 = version of installed list
}

3. D01 — Send Local Authorization List

Use Case

Use Case ID: D01

Direction: CSMS sends SendLocalListRequest → Charging Station responds with SendLocalListResponse

CSMS Role: Initiator (sender of the request)

Sequence Diagram

D01 — Send Local Authorization List
┌──────┐                                    ┌───────────────────┐
│ CSMS │                                    │ Charging Station  │
└──┬───┘                                    └────────┬──────────┘
   │                                                 │
   │  SendLocalListRequest(versionNumber,            │
   │    updateType, localAuthorizationList)           │
   │ ───────────────────────────────────────────────> │
   │                                                 │
   │         SendLocalListResponse(status)            │
   │ <─────────────────────────────────────────────── │
   │                                                 │

SendLocalListRequest — Top-Level Fields

Field Type Required Description
versionNumber integer Yes The version number to assign to the list after this update is applied. Must be > 0 (value 0 is reserved to mean "no list installed"). For differential updates, must be strictly greater than the current version on the CS.
updateType UpdateEnumType Yes The type of update: "Full" or "Differential".
localAuthorizationList AuthorizationData[] No Array of authorization entries (min 1 item if provided). Can be omitted for a Full update (to clear the list) or for a Differential update (no-op, only version bumps).

UpdateEnumType Values

Value Description
"Full" Replace the entire Local Authorization List on the Charging Station with the provided list. If localAuthorizationList is omitted/empty, this clears the entire list.
"Differential" Apply incremental changes (add, update, delete) to the existing list.

AuthorizationData Object

Each entry in the localAuthorizationList array:

Field Type Required Description
idToken IdTokenType Yes The identifier token.
idTokenInfo IdTokenInfoType No Authorization status/metadata for this token. Presence or absence controls the operation in differential updates.

Differential Update Behavior Based on idTokenInfo Presence

idTokenInfo present? Effect in Differential Update
Yes Add or Update the entry in the Charging Station's list. If the idToken already exists, its info is replaced. If it doesn't exist, it is added.
No Delete the entry matching this idToken from the Charging Station's list.

IdTokenType Object

Field Type Required Max Length Description
idToken string Yes 255 The identifier value (case insensitive). Can be an RFID UID, UUID, etc.
type string Yes 20 Token type (e.g. "Central", "eMAID", "ISO14443", "ISO15693", "KeyCode", "Local", "MacAddress", "NoAuthorization").
additionalInfo AdditionalInfoType[] No Array of additional identifier info (min 1 item if provided).

AdditionalInfoType Object

Field Type Required Max Length Description
additionalIdToken string Yes 255 The additional identifier token value.
type string Yes 50 Custom type string agreed upon by all parties. Unknown types MAY be ignored.

IdTokenInfoType Object

Field Type Required Description
status AuthorizationStatusEnumType Yes Current authorization status of this token.
cacheExpiryDateTime string (date-time) No Expiration timestamp. After this time the token is considered invalid. Used for caching only — do not stop active charging sessions based on expiry.
chargingPriority integer No Business priority. Range: -9 to 9. Default: 0. Higher = higher priority.
groupIdToken IdTokenType No Group/parent token for group authorization scenarios.
language1 string (max 8) No Preferred UI language (RFC 5646 language code, e.g. "en", "nl").
language2 string (max 8) No Second preferred UI language. Must differ from language1.
evseId integer[] No If present, restricts this token to specific EVSE IDs only (not the entire station). Array of integers >= 0, min 1 item.
personalMessage MessageContentType No Personal message to display to the user.

AuthorizationStatusEnumType Values

Value Description
"Accepted" Token is authorized.
"Blocked" Token is blocked (e.g. reported lost/stolen).
"ConcurrentTx" Token is already in use in another transaction.
"Expired" Token authorization has expired.
"Invalid" Token is unknown/invalid.
"NoCredit" Token has insufficient credit.
"NotAllowedTypeEVSE" Token not allowed on this EVSE type.
"NotAtThisLocation" Token not authorized at this location.
"NotAtThisTime" Token not authorized at this time.
"Unknown" Token status is unknown.

MessageContentType Object

Field Type Required Max Length Description
format MessageFormatEnumType Yes Message format: "ASCII", "HTML", "URI", "UTF8", "QRCODE".
content string Yes 1024 The message text.
language string No 8 Language code (RFC 5646).

Request Examples

Full List Replacement

SendLocalListRequest — Full Replacement
{
  "versionNumber": 5,
  "updateType": "Full",
  "localAuthorizationList": [
    {
      "idToken": {
        "idToken": "AA12BB34",
        "type": "ISO14443"
      },
      "idTokenInfo": {
        "status": "Accepted",
        "cacheExpiryDateTime": "2026-12-31T23:59:59Z"
      }
    },
    {
      "idToken": {
        "idToken": "CC56DD78",
        "type": "ISO14443"
      },
      "idTokenInfo": {
        "status": "Accepted",
        "cacheExpiryDateTime": "2026-06-30T23:59:59Z",
        "chargingPriority": 3,
        "language1": "en",
        "personalMessage": {
          "format": "UTF8",
          "content": "Welcome, Premium Member!"
        }
      }
    },
    {
      "idToken": {
        "idToken": "EE90FF12",
        "type": "ISO14443"
      },
      "idTokenInfo": {
        "status": "Blocked"
      }
    }
  ]
}

Differential Update — Add/Update Entries

SendLocalListRequest — Differential Add/Update
{
  "versionNumber": 6,
  "updateType": "Differential",
  "localAuthorizationList": [
    {
      "idToken": {
        "idToken": "NEWTOKEN01",
        "type": "ISO14443"
      },
      "idTokenInfo": {
        "status": "Accepted",
        "cacheExpiryDateTime": "2026-12-31T23:59:59Z"
      }
    },
    {
      "idToken": {
        "idToken": "AA12BB34",
        "type": "ISO14443"
      },
      "idTokenInfo": {
        "status": "Blocked"
      }
    }
  ]
}

Differential Update — Delete Entries

To delete an entry, include the idToken without idTokenInfo:

SendLocalListRequest — Differential Delete
{
  "versionNumber": 7,
  "updateType": "Differential",
  "localAuthorizationList": [
    {
      "idToken": {
        "idToken": "EE90FF12",
        "type": "ISO14443"
      }
    }
  ]
}

Clear Entire List

Send a Full update with no localAuthorizationList field to remove all entries. The version is updated to the specified number.

SendLocalListRequest — Clear Entire List
{
  "versionNumber": 8,
  "updateType": "Full"
}

Differential Update — Mixed Add/Update and Delete

SendLocalListRequest — Mixed Differential
{
  "versionNumber": 9,
  "updateType": "Differential",
  "localAuthorizationList": [
    {
      "idToken": {
        "idToken": "NEWTOKEN02",
        "type": "eMAID"
      },
      "idTokenInfo": {
        "status": "Accepted",
        "evseId": [1, 2]
      }
    },
    {
      "idToken": {
        "idToken": "OLDTOKEN99",
        "type": "ISO14443"
      }
    }
  ]
}

SendLocalListResponse — Status Values

Value Meaning CSMS Action
"Accepted" The Charging Station successfully applied the update and set the version number. Success. Update your internal tracking of this Charging Station's list version.
"Failed" The Charging Station could not apply the update (generic failure). Retry. If the updateType was "Differential", fall back to sending the full list.
"VersionMismatch" The versionNumber in a Differential request was <= the Charging Station's current version. The CSMS's view of the CS version is stale. Query with GetLocalListVersion, then resend with correct version or send a Full update.

Response Examples

Response — Accepted
{
  "status": "Accepted"
}
Response — Version Mismatch
{
  "status": "VersionMismatch",
  "statusInfo": {
    "reasonCode": "VersionConflict",
    "additionalInfo": "Current list version is 10, received version 8"
  }
}

StatusInfoType Object

Field Type Required Max Length Description
reasonCode string Yes 20 Predefined reason code (case-insensitive).
additionalInfo string No 1024 Human-readable additional details.

CSMS Response Handling Logic

D01 — Response Decision Tree
Receive SendLocalListResponse:

├── status == "Accepted"
│   └── Update internal record: CS version = versionNumber from request
│       Done.
│
├── status == "Failed"
│   ├── Was updateType "Differential"?
│   │   ├── Yes → Retry with updateType "Full" (send complete list)
│   │   │         If list is too large for one message:
│   │   │           1. Send initial subset with updateType "Full"
│   │   │           2. Send remaining entries with updateType "Differential"
│   │   │              (incrementing version each time)
│   │   └── No (was already "Full") → Log error, alert operator, retry later
│   └── Done.
│
└── status == "VersionMismatch"
    ├── Was updateType "Differential"?
    │   ├── Yes → Send GetLocalListVersionRequest to get current version
    │   │         Then either:
    │   │           a) Resend differential with corrected versionNumber (> CS version)
    │   │           b) Send full list to force sync
    │   └── No → Should not normally occur for Full. Log and investigate.
    └── Done.

Requirement Traceability (CSMS Responsibilities)

Req ID CSMS Responsibility
D01.FR.01 CSMS must include updateType and versionNumber in every SendLocalListRequest.
D01.FR.02 CSMS must check the status field in the response to determine success/failure.
D01.FR.03 If response is Failed or VersionMismatch and updateType was Differential, CSMS should resend as a full list. If the full list is too large, send an initial Full batch then Differential batches.
D01.FR.04 To clear the list: send updateType: "Full" with no localAuthorizationList field.
D01.FR.05 A Differential update with no localAuthorizationList is a no-op (only the version number is updated on the CS).
D01.FR.06 CSMS must ensure all idToken values in the list are unique. No duplicates in a single request.
D01.FR.11 CSMS must respect the Charging Station's ItemsPerMessageSendLocalList and BytesPerMessageSendLocalList configuration variables to limit message size.
D01.FR.15 For initial sync or full replacement: use updateType: "Full" with a non-empty list.
D01.FR.16 For adding/updating entries in differential mode: include idTokenInfo in the AuthorizationData.
D01.FR.17 For deleting entries in differential mode: omit idTokenInfo from the AuthorizationData (include only idToken).
D01.FR.18 CSMS must always use versionNumber > 0.
D01.FR.19 For differential updates, CSMS must use a versionNumber strictly greater than the CS's current version, or the CS will reject with VersionMismatch.

4. D02 — Get Local List Version

Use Case

Use Case ID: D02

Direction: CSMS sends GetLocalListVersionRequest → Charging Station responds with GetLocalListVersionResponse

CSMS Role: Initiator (sender of the request)

Sequence Diagram

D02 — Get Local List Version
┌──────┐                                        ┌───────────────────┐
│ CSMS │                                        │ Charging Station  │
└──┬───┘                                        └────────┬──────────┘
   │                                                     │
   │       GetLocalListVersionRequest()                   │
   │ ───────────────────────────────────────────────────> │
   │                                                     │
   │     GetLocalListVersionResponse(versionNumber)       │
   │ <─────────────────────────────────────────────────── │
   │                                                     │

GetLocalListVersionRequest

This is a simple request with no required fields. The CSMS sends it to query the current version of the Local Authorization List on a Charging Station.

Example Request
{}
With Custom Data
{
  "customData": {
    "vendorId": "com.example.vendor"
  }
}

GetLocalListVersionResponse

Field Type Required Description
versionNumber integer Yes Current version of the Local Authorization List on the Charging Station.

Version Number Semantics

Value Meaning
0 No Local Authorization List exists. Either LocalAuthListEnabled is false, or no list has ever been sent to this Charging Station.
> 0 The version of the currently installed list. This matches the versionNumber from the last successfully applied SendLocalListRequest. An emptied list (cleared via a Full update with no entries) still has a version > 0.

Response Examples

Response — List Exists
{
  "versionNumber": 5
}
Response — No List
{
  "versionNumber": 0
}

CSMS Response Handling Logic

D02 — Response Decision Tree
Receive GetLocalListVersionResponse:

├── versionNumber == 0
│   └── No list exists on the Charging Station.
│       Action: Send a Full list via SendLocalListRequest (versionNumber: 1).
│
├── versionNumber == CSMS's expected version
│   └── Lists are in sync. No action needed.
│
├── versionNumber < CSMS's expected version
│   └── Charging Station is behind (e.g. it was reset, or a previous update failed).
│       Action: Send a Full list to re-sync.
│
└── versionNumber > CSMS's expected version
    └── CSMS tracking is stale (should not normally happen since CSMS is sole sender).
        Action: Update internal tracking to match CS version.
        Consider sending a Full list to ensure correctness.

Requirement Traceability (CSMS Responsibilities)

Req ID CSMS Responsibility
D02.FR.01 CSMS should expect a valid version number when LocalAuthListEnabled is true.
D02.FR.02 CSMS should interpret versionNumber == 0 as "no list has been sent yet" (when enabled but never initialized).
D02.FR.03 CSMS should interpret versionNumber == 0 as "list not enabled" (when LocalAuthListEnabled is false).

5. CSMS Implementation Strategy: Synchronization Workflow

Strategy

Recommended Sync Algorithm

The CSMS should maintain an internal record of each Charging Station's list version. Here is the recommended synchronization flow:

Synchronization Algorithm
On Charging Station (re)connect or periodic sync:

1. Send GetLocalListVersionRequest
2. Receive GetLocalListVersionResponse(versionNumber)

3. IF versionNumber == 0:
     → CS has no list. Send Full list with versionNumber = CSMS_current_version

4. ELSE IF versionNumber == CSMS_current_version:
     → In sync. Nothing to do.

5. ELSE IF versionNumber < CSMS_current_version:
     → CS is behind.
     → Option A: Send Differential update (if delta is small)
                  Use versionNumber = CSMS_current_version (must be > CS version)
     → Option B: Send Full update (if delta is large or unknown)

6. ELSE (versionNumber > CSMS_current_version):
     → Unexpected. Log warning. Send Full list to force re-sync.

Handling Large Lists (Chunked Sending)

When the full list is too large to fit in a single message (constrained by ItemsPerMessageSendLocalList and BytesPerMessageSendLocalList), use this strategy:

Chunked Sending Strategy
Given: total_entries = all entries to send
       max_per_msg = ItemsPerMessageSendLocalList from CS config
       version = starting version number

1. First message:
   - updateType: "Full"
   - localAuthorizationList: first chunk (up to max_per_msg entries)
   - versionNumber: version
   → This REPLACES the entire list with just this chunk

2. Subsequent messages (for remaining entries):
   - updateType: "Differential"
   - localAuthorizationList: next chunk (up to max_per_msg entries)
   - versionNumber: ++version  (must increment for each differential)
   → Each includes idTokenInfo for all entries (add operation)

3. Repeat step 2 until all entries are sent.

4. After final response, verify: CS version == last versionNumber sent.

Important: The first message with updateType: "Full" replaces the entire list with just that chunk. All subsequent chunks must use "Differential" to add to the list rather than replace it again.

CSMS Internal Data Model (Suggested)

The following data model is recommended for tracking Local Authorization List state on the CSMS side:

Per Charging Station Tracking
Per Charging Station, track:
  - charging_station_id: string
  - local_list_version: integer        // last successfully applied version
  - local_list_enabled: boolean        // mirrors LocalAuthListEnabled config var
  - max_items_per_message: integer     // from ItemsPerMessageSendLocalList
  - max_bytes_per_message: integer     // from BytesPerMessageSendLocalList
  - max_list_entries: integer          // from LocalAuthListEntries (max capacity)
  - last_sync_timestamp: datetime
Per Authorization Entry (Master List)
Per authorization entry (the master list), track:
  - id_token: string
  - id_token_type: string
  - authorization_status: AuthorizationStatusEnumType
  - cache_expiry: datetime (optional)
  - charging_priority: integer (optional)
  - group_id_token: IdTokenType (optional)
  - language1: string (optional)
  - language2: string (optional)
  - evse_ids: integer[] (optional)
  - personal_message: MessageContentType (optional)

6. Configuration Variables Reference

Reference

These Charging Station configuration variables are relevant to Local Authorization List Management. The CSMS should query them via GetVariables (Provisioning functional block) before performing list operations.

Variable Description CSMS Usage
LocalAuthListEnabled Whether the Local Authorization List feature is enabled on the CS. Check before sending list updates. If false, list operations are meaningless. Can be set via SetVariables.
LocalAuthListEntries Reports the current number AND maximum possible number of entries in the CS's list. Use to know the capacity limit. Do not send more entries than the CS can store.
ItemsPerMessageSendLocalList Maximum number of AuthorizationData entries allowed in a single SendLocalListRequest. Use to chunk large lists into multiple messages.
BytesPerMessageSendLocalList Maximum byte size of a single SendLocalListRequest message. Use alongside ItemsPerMessageSendLocalList to ensure messages don't exceed limits.

7. Error Handling & Edge Cases

Reference

Differential Update Fails or Version Mismatch

Scenario CSMS Behavior
status == "Failed" with updateType == "Differential" Resend as a Full update. If too large for one message, use the chunked strategy (section 5.2).
status == "VersionMismatch" with updateType == "Differential" The CSMS's versionNumber was <= the CS's current version. Send GetLocalListVersionRequest to get the actual version, then resend with a corrected versionNumber > CS version, or send a Full update to force sync.
status == "Failed" with updateType == "Full" Genuine failure (storage error, etc). Log the error, alert operator, retry after a delay.

Charging Station Reconnection

When a Charging Station reconnects (after reboot, network loss, etc.):

  1. Send GetLocalListVersionRequest to verify the list state.
  2. Compare with CSMS's expected version for this Charging Station.
  3. If out of sync, resend the appropriate update (Full or Differential).

Version Number Management

Always use versionNumber > 0

The CSMS is the sole authority for version numbers. Value 0 is reserved to mean "no list installed".

Increment monotonically

Increment the version number with each update to maintain a clear update history.

Differential version constraint

For differential updates, the versionNumber sent must be strictly greater than the CS's current version, or the CS will reject with VersionMismatch (D01.FR.19).

Full update flexibility

For full updates, there is no version comparison constraint, but you should still use a higher version to maintain consistency.

Uniqueness Constraint

All idToken values in the Local Authorization List must be unique (D01.FR.06). When building the localAuthorizationList array:

  • Do not include duplicate idToken values in a single request.
  • When sending a Full update, ensure the entire list has no duplicates.
  • When sending a Differential update, each idToken should appear at most once in the request.

Empty/No-op Operations

Operation Result
Full update with no localAuthorizationList field Clears the entire list on the CS. Version is updated to versionNumber.
Differential update with no localAuthorizationList field No-op. List is unchanged. Version is updated to versionNumber.
Full update with an empty localAuthorizationList array Not valid per schema (minItems: 1). Either omit the field entirely or provide at least 1 entry.

OCPP-J Message Framing

All messages are sent over the OCPP-J (JSON over WebSocket) protocol using the standard CALL/CALLRESULT/CALLERROR framing:

CSMS sending SendLocalListRequest (CALL)

CALL — SendLocalList
[2, "msg-uuid-001", "SendLocalList", {
  "versionNumber": 5,
  "updateType": "Full",
  "localAuthorizationList": [
    {
      "idToken": {"idToken": "AA12BB34", "type": "ISO14443"},
      "idTokenInfo": {"status": "Accepted"}
    }
  ]
}]

Charging Station responding (CALLRESULT)

CALLRESULT — SendLocalList
[3, "msg-uuid-001", {
  "status": "Accepted"
}]

CSMS sending GetLocalListVersionRequest (CALL)

CALL — GetLocalListVersion
[2, "msg-uuid-002", "GetLocalListVersion", {}]

Charging Station responding (CALLRESULT)

CALLRESULT — GetLocalListVersion
[3, "msg-uuid-002", {
  "versionNumber": 5
}]

8. Message Direction Summary

Reference

Outgoing from CSMS (CSMS → Charging Station)

Message When to Send Use Cases
SendLocalListRequest Push a full or differential list update to the Charging Station D01
GetLocalListVersionRequest Query the current version of the Local Authorization List on the Charging Station D02

Incoming to CSMS (Charging Station → CSMS)

Message Description Use Cases
SendLocalListResponse Response to CSMS SendLocalListRequest — contains status (Accepted, Failed, VersionMismatch) D01
GetLocalListVersionResponse Response to CSMS GetLocalListVersionRequest — contains current versionNumber D02

Related Messages (Other Functional Blocks)

The following messages from other functional blocks are relevant to Local Authorization List Management:

Message Functional Block Relevance
GetVariables Provisioning Query CS configuration variables (LocalAuthListEnabled, LocalAuthListEntries, etc.)
SetVariables Provisioning Set LocalAuthListEnabled to enable/disable the feature

OCPP 2.1 Local Authorization List Management (D01–D02) - CSMS Developer Guide. Based on OCPP 2.1 Edition 2 Specification (Part 2), Section D.