OCPP 2.0 Command Purposes and Request/Response Examples
This page covers 18 commands with their direction, purpose and complete JSON frames for debugging. Examples follow the OCPP 2.0 request and response structures.
Version note: these examples use OCPP 2.0 (2018), not OCPP 2.0.1. For example, transaction events use transactionData.id and availability requests use evseId. Match these structures to the protocol version supported by your server.
Message Format and Usage
- Request CALL:
[2, "unique-message-id", "Action", {request payload}]. - Successful response CALLRESULT:
[3, "same-message-id", {response payload}]. The response does not repeat the action name. - Protocol error CALLERROR:
[4, "same-message-id", "ErrorCode", "Error description", {}]. - Use a new message ID for each request. The response must use the corresponding request ID. Replace the example timestamps, device IDs, tokens and transaction IDs when debugging.
- An empty object
{}is a valid payload and must not be omitted.Acceptedusually acknowledges a request; verify subsequent notifications to confirm the actual transaction or device state.
Command Index
- BootNotification
- Heartbeat
- Authorize
- StatusNotification
- TransactionEvent
- MeterValues
- RequestStartTransaction
- RequestStopTransaction
- ChangeAvailability
- UnlockConnector
- Reset
- FirmwareStatusNotification
- LogStatusNotification
- ClearedChargingLimit
- NotifyChargingLimit
- NotifyEVChargingSchedule
- DataTransfer
- TriggerMessage
BootNotification
Direction: Charging station → server.
Purpose: Report the startup reason and chargingStation information. After Accepted, send heartbeats at the interval specified in seconds.
Request:
[
2,
"ocpp20-001",
"BootNotification",
{
"reason": "PowerUp",
"chargingStation": {
"vendorName": "devTest",
"model": "QA",
"firmwareVersion": "1.0"
}
}
]
Response (returned by the receiver of the request):
[
3,
"ocpp20-001",
{
"status": "Accepted",
"currentTime": "2026-11-08T08:00:00Z",
"interval": 60
}
]
Heartbeat
Direction: Charging station → server.
Purpose: Keep the connection alive and obtain the server time. The request payload is an empty object; currentTime in the response can be used for clock synchronization.
Request:
[
2,
"ocpp20-002",
"Heartbeat",
{}
]
Response (returned by the receiver of the request):
[
3,
"ocpp20-002",
{
"currentTime": "2026-11-08T08:00:00Z"
}
]
Authorize
Direction: Charging station → server.
Purpose: Request authorization using an idToken with an explicit type. Inspect idTokenInfo.status and proceed only when the returned status permits the authorization flow.
Request:
[
2,
"ocpp20-003",
"Authorize",
{
"idToken": {
"idToken": "QA-TAG",
"type": "Central"
},
"evseId": [
1
]
}
]
Response (returned by the receiver of the request):
[
3,
"ocpp20-003",
{
"idTokenInfo": {
"status": "Accepted"
}
}
]
StatusNotification
Direction: Charging station → server.
Purpose: Report the EVSE and connector status. This version uses connectorStatus instead of the OCPP 1.6 status/errorCode fields.
Request:
[
2,
"ocpp20-004",
"StatusNotification",
{
"timestamp": "2026-11-08T08:00:00Z",
"connectorStatus": "Available",
"evseId": 1,
"connectorId": 1
}
]
Response (returned by the receiver of the request):
[
3,
"ocpp20-004",
{}
]
TransactionEvent
Direction: Charging station → server.
Purpose: Report the transaction lifecycle. Started, Updated and Ended indicate start, update and termination. Keep transactionData.id unchanged for a transaction and increment seqNo starting at 0. This example shows a start event.
Request:
[
2,
"ocpp20-005",
"TransactionEvent",
{
"eventType": "Started",
"timestamp": "2026-11-08T08:00:00Z",
"triggerReason": "Authorized",
"seqNo": 0,
"transactionData": {
"id": "TX-001"
},
"evse": {
"id": 1,
"connectorId": 1
},
"idToken": {
"idToken": "QA-TAG",
"type": "Central"
},
"meterValue": [
{
"timestamp": "2026-11-08T08:00:00Z",
"sampledValue": [
{
"value": 1000,
"measurand": "Energy.Active.Import.Register",
"unitOfMeasure": {
"unit": "Wh"
}
}
]
}
]
}
]
Response (returned by the receiver of the request):
[
3,
"ocpp20-005",
{
"idTokenInfo": {
"status": "Accepted"
}
}
]
Example request to end the same transaction (keep the transaction ID, increment seqNo and correlate the response with this message ID):
[
2,
"ocpp20-ended",
"TransactionEvent",
{
"eventType": "Ended",
"timestamp": "2026-11-08T08:10:00Z",
"triggerReason": "StopAuthorized",
"seqNo": 1,
"transactionData": {
"id": "TX-001",
"stoppedReason": "Local"
}
}
]
[
3,
"ocpp20-ended",
{
"idTokenInfo": {
"status": "Accepted"
}
}
]
MeterValues
Direction: Charging station → server.
Purpose: Report meter samples for an EVSE. value is numeric and unitOfMeasure describes the unit. Transaction-related samples can also be included in TransactionEvent.
Request:
[
2,
"ocpp20-006",
"MeterValues",
{
"evseId": 1,
"meterValue": [
{
"timestamp": "2026-11-08T08:00:00Z",
"sampledValue": [
{
"value": 1000,
"measurand": "Energy.Active.Import.Register",
"unitOfMeasure": {
"unit": "Wh"
}
}
]
}
]
}
]
Response (returned by the receiver of the request):
[
3,
"ocpp20-006",
{}
]
RequestStartTransaction
Direction: Server → charging station.
Purpose: Request a transaction start from the server. remoteStartId correlates the remote start request. After Accepted, verify the Started TransactionEvent and its remoteStartId.
Request:
[
2,
"ocpp20-007",
"RequestStartTransaction",
{
"evseId": 1,
"remoteStartId": 7,
"idToken": {
"idToken": "QA-TAG",
"type": "Central"
}
}
]
Response (returned by the receiver of the request):
[
3,
"ocpp20-007",
{
"status": "Accepted"
}
]
RequestStopTransaction
Direction: Server → charging station.
Purpose: Request termination of a transaction identified by a string transactionId. After Accepted, verify the Ended TransactionEvent.
Request:
[
2,
"ocpp20-008",
"RequestStopTransaction",
{
"transactionId": "TX-001"
}
]
Response (returned by the receiver of the request):
[
3,
"ocpp20-008",
{
"status": "Accepted"
}
]
ChangeAvailability
Direction: Server → charging station.
Purpose: Set the operational availability of an EVSE. This example makes EVSE 1 Inoperative; subsequent status messages report the resulting state.
Request:
[
2,
"ocpp20-009",
"ChangeAvailability",
{
"evseId": 1,
"operationalStatus": "Inoperative"
}
]
Response (returned by the receiver of the request):
[
3,
"ocpp20-009",
{
"status": "Accepted"
}
]
UnlockConnector
Direction: Server → charging station.
Purpose: Request unlocking of a connector on an EVSE. Use evseId and connectorId together to identify the target.
Request:
[
2,
"ocpp20-010",
"UnlockConnector",
{
"evseId": 1,
"connectorId": 1
}
]
Response (returned by the receiver of the request):
[
3,
"ocpp20-010",
{
"status": "Unlocked"
}
]
Reset
Direction: Server → charging station.
Purpose: Request a station restart. Immediate requests an immediate reset. Accepted acknowledges receipt; observe disconnection and subsequent registration to verify recovery.
Request:
[
2,
"ocpp20-011",
"Reset",
{
"type": "Immediate"
}
]
Response (returned by the receiver of the request):
[
3,
"ocpp20-011",
{
"status": "Accepted"
}
]
FirmwareStatusNotification
Direction: Charging station → server.
Purpose: Report firmware update progress. Installed indicates that firmware has been installed; requestId correlates the update task.
Request:
[
2,
"ocpp20-012",
"FirmwareStatusNotification",
{
"status": "Installed",
"requestId": 1
}
]
Response (returned by the receiver of the request):
[
3,
"ocpp20-012",
{}
]
LogStatusNotification
Direction: Charging station → server.
Purpose: Report log upload progress. Uploaded indicates completion; Uploading can be sent while uploading. requestId correlates the log task.
Request:
[
2,
"ocpp20-013",
"LogStatusNotification",
{
"status": "Uploaded",
"requestId": 1
}
]
Response (returned by the receiver of the request):
[
3,
"ocpp20-013",
{}
]
ClearedChargingLimit
Direction: Charging station → server.
Purpose: Notify the server that a charging limit from a particular source has been cleared. evseId identifies its scope and chargingLimitSource identifies the original source.
Request:
[
2,
"ocpp20-014",
"ClearedChargingLimit",
{
"chargingLimitSource": "Other",
"evseId": 1
}
]
Response (returned by the receiver of the request):
[
3,
"ocpp20-014",
{}
]
NotifyChargingLimit
Direction: Charging station → server.
Purpose: Report an active external charging limit. This example uses system operator source SO and limits current to 10 A starting at second 0.
Request:
[
2,
"ocpp20-015",
"NotifyChargingLimit",
{
"evseId": 1,
"chargingLimit": {
"chargingLimitSource": "SO",
"isGridCritical": false
},
"chargingSchedule": [
{
"chargingRateUnit": "A",
"chargingSchedulePeriod": [
{
"startPeriod": 0,
"limit": 10
}
]
}
]
}
]
Response (returned by the receiver of the request):
[
3,
"ocpp20-015",
{}
]
NotifyEVChargingSchedule
Direction: Charging station → server.
Purpose: Report the vehicle charging schedule. timeBase is the reference time and startPeriod is the offset in seconds. This example specifies a 10 A current limit.
Request:
[
2,
"ocpp20-016",
"NotifyEVChargingSchedule",
{
"evseId": 1,
"timeBase": "2026-11-08T08:00:00Z",
"chargingSchedule": {
"chargingRateUnit": "A",
"chargingSchedulePeriod": [
{
"startPeriod": 0,
"limit": 10
}
]
}
}
]
Response (returned by the receiver of the request):
[
3,
"ocpp20-016",
{
"status": "Accepted"
}
]
DataTransfer
Direction: Bidirectional (example: charging station → server).
Purpose: Exchange vendor-specific data. vendorId identifies the vendor and messageId identifies the operation. Accepted means that the extension request was accepted.
Request:
[
2,
"ocpp20-017",
"DataTransfer",
{
"vendorId": "devTest",
"messageId": "GetChargeInstruction",
"data": ""
}
]
Response (returned by the receiver of the request):
[
3,
"ocpp20-017",
{
"status": "Accepted"
}
]
TriggerMessage
Direction: Server → charging station.
Purpose: Ask the station to send a specific message. This example triggers Heartbeat. After Accepted, expect a separate Heartbeat CALL from the station.
Request:
[
2,
"ocpp20-018",
"TriggerMessage",
{
"requestedMessage": "Heartbeat"
}
]
Response (returned by the receiver of the request):
[
3,
"ocpp20-018",
{
"status": "Accepted"
}
]