Remote commands

Public API — Remote Commands & Troubleshooting

How to drive charging stations remotely — reset, start/stop sessions, availability, unlock, diagnostics, firmware — and how to find out why a command didn't do what you expected.

All command endpoints require permission charging-station:remote-control (see Authentication).

v1 vs v2

Both versions expose the same commands with the same request bodies:

  • v1/api/v1/commands/*. Most endpoints return 204 No Content.
  • v2/api/v2/commands/*. Every endpoint returns 200 with a JSON body containing ocppMessageId — the correlation ID stamped on the outgoing OCPP message. Store it; it is your handle for tracing the command through OCPP logs (CPMS → OCPP adapter → charging station).

New integrations should use v2. Without ocppMessageId you cannot correlate a command with its OCPP exchange later.

The execution model: accepted ≠ executed

A command request is asynchronous: a 2xx response means the command was validated and dispatched towards the station — not that the station received or executed it. The station's reaction (or silence) arrives later over OCPP and shows up as entity state changes, sessions, webhooks, and OCPP log entries.

Two commands give you more than dispatch:

  • unlock-connector waits for the station's reply and returns the actual unlock status.
  • start-session returns a command id you can poll for the outcome.
sequenceDiagram
    participant C as Your backend
    participant API as Public API
    participant CS as Charging Station

    C->>API: POST /v2/commands/<command>
    API-->>C: 200 { ocppMessageId }
    Note over API,CS: asynchronous from here
    API->>CS: OCPP call (ocppMessageId)
    CS-->>API: Accepted / Rejected — visible in OCPP logs,<br/>entity state, sessions, webhooks

Command catalog

All paths relative to /api/v1/commands or /api/v2/commands. All are POST unless noted.

CommandPathKey request fieldsv1 → / v2 →
Reset station/resetchargingStationId (UUID or OCPP ID), type: SOFT (default) | HARD204 / { ocppMessageId }
Start session/start-sessionconnectorId, tokenUidcommand DTO / { id, status, sessionId, ocppMessageId }
Start session statusGET /start-session/{id}command DTO / { id, status, sessionId, ocppMessageId }
Stop session/stop-sessionchargingSessionId or chargingStationId + ocppTransactionId204 / { ocppMessageId }
Station availability/change-charging-station-availabilityid (UUID or OCPP ID), type: OPERATIVE | INOPERATIVE204 / { ocppMessageId }
Point availability/change-charging-point-availabilityid (charging point UUID), type204 / { ocppMessageId }
Connector availability/change-connector-availabilityid (connector UUID), type204 / { ocppMessageId }
Unlock connector/unlock-connectorconnectorId{ status } / { status, ocppMessageId }
Trigger message/trigger-messagechargingStationId, requestedMessage, optional chargingPointId, connectorId204 / { ocppMessageId }
Get diagnostics/get-diagnosticschargingStationId (UUID), optional location, retries, retryInterval, startTime, stopTime{ url } / { url, message, ocppMessageId }
Update firmware/update-firmwarechargingStationId, firmwareId xor locationUrl, optional retrieveDate, retries, retryInterval204 / { ocppMessageId }

Command notes

Reset

SOFT asks the station to restart gracefully (finish transactions first); HARD reboots. Each reset is recorded in the station's restart log together with the API key that requested it.

curl -s -X POST -H "x-api-key: $API_KEY" -H "Content-Type: application/json" \
  -d '{ "chargingStationId": "EWEL00629", "type": "SOFT" }' \
  "https://<host>/api/v2/commands/reset"

Start / stop session

Covered in depth — with sequence diagrams — in Session Flows. The short version:

  • start-session creates a trackable command. Poll GET /v2/commands/start-session/{id}; status moves through PENDINGACCEPTEDSESSION_CREATED (with sessionId set), or ends in REJECTED / TIMED_OUT.
  • stop-session identifies the session by chargingSessionId, or by chargingStationId + ocppTransactionId. The stop is confirmed asynchronously by the station — verify via session status or a webhook.

Change availability

INOPERATIVE takes the target out of service (station screen typically shows "unavailable"); OPERATIVE returns it to service. Three granularities: whole station, one charging point (EVSE), one connector.

OCPP 1.6 caveat: point-level availability requires the point to have exactly one connector (the 1.6 protocol addresses connectors, not EVSEs); otherwise the request is rejected with 400.

Unlock connector

The only fully synchronous command — the response carries the station's verdict:

statusMeaning
UNLOCKEDConnector released
UNLOCK_FAILEDStation tried and failed (cable still latched by the vehicle?)
ONGOING_AUTHORIZED_TRANSACTIONActive authorized session — stop it first
UNKNOWN_CONNECTORStation doesn't know this connector
NOT_SUPPORTEDStation cannot unlock remotely

Trigger message

Asks the station to proactively send a message — the primary self-service diagnostic tool. requestedMessage values (OCPP-standard):

BootNotification, Heartbeat, MeterValues, StatusNotification, DiagnosticsStatusNotification, FirmwareStatusNotification — plus, on stations supporting the extended set, LogStatusNotification and SignChargePointCertificate.

Optional chargingPointId / connectorId scope the trigger (both must belong to the given station, else 422). Triggering StatusNotification on a connector is the quickest way to check whether a station is alive and what state it reports.

Get diagnostics

Requests the station to upload a diagnostics archive. If you pass location (an FTP URL you control), the station uploads there. Without it, a CPMS-hosted FTP location is used and the response url is where the file will appear — the hosted download link is valid for 1 hour, and only after the upload completes (watch for DiagnosticsStatusNotification, or trigger it). startTime/stopTime bound the log window.

Update firmware

Provide exactly one of firmwareId (a firmware entity registered via /api/v1/firmware) or locationUrl (direct download URL for the station). retrieveDate defaults to now. Download and installation progress arrives via FirmwareStatusNotification — visible in the OCPP logs.

Troubleshooting

First rule: verify effect, not response

A 2xx proves dispatch, nothing more. Confirm the actual outcome through:

  1. Entity state — station/point/connector status: POST /api/v1/charging-stations/rsql-list with { "filter": "status == 'ONLINE'" }, or GET the entity.
  2. SessionsGET /api/v1/sessions/{id} or a SESSION webhook.
  3. OCPP logsPOST /api/v1/charging-stations/{id}/ocpp-logs/rsql-list (permission charging-station:read-logs): the raw request/response exchange with the station. Search around the command timestamp and match the v2 ocppMessageId.

Diagnosis flow

flowchart TD
    A[Command returned 2xx<br/>but nothing happened] --> B{Station ONLINE?}
    B -- no --> C[Station offline — command never reached it.<br/>Check connectivity, then retry]
    B -- yes --> D{OCPP logs show the message?<br/>match ocppMessageId}
    D -- no --> E[Not dispatched — check adapter health,<br/>report with X-Correlation-Id]
    D -- yes --> F{Station reply in logs?}
    F -- Rejected / error --> G[Station refused — see reply payload.<br/>Trigger StatusNotification to inspect state]
    F -- none --> H[Station silent — power/network issue.<br/>Trigger Heartbeat; escalate to field service]

Error responses

StatusTypical causeWhat to do
401Missing/invalid API keyCheck x-api-key header (Authentication)
403Key's role lacks charging-station:remote-controlGrant via IAM endpoints
404 <Entity> not foundUnknown connectorId / session / charging point UUIDYou passed the wrong ID or the wrong kind of ID — most fields take the internal UUID, not the OCPP ID
400Validation error, missing station details, or the OCPP 1.6 multi-connector availability caveatMessage names the field/rule
422Business rule violatedSee table below
500UnexpectedReport with X-Correlation-Id

Common 422 reasons by command:

Command422 cause
reset, trigger-message, get-diagnosticsStation unknown or has never connected (no station details yet — a station that never sent BootNotification cannot be commanded)
stop-sessionSelector rule violated (chargingSessionId or chargingStationId+ocppTransactionId required); session has no OCPP transaction ID (never actually started on the station)
trigger-messagechargingPointId/connectorId not part of the given station
get-diagnosticsNo location given and no hosted FTP configured for the environment
update-firmwareNeither or both of firmwareId/locationUrl given; unknown firmware ID

Frequent symptoms

SymptomLikely cause / fix
start-session stuck in PENDING, then TIMED_OUTStation offline, connector occupied, or station ignored the remote start. Check OCPP logs by ocppMessageId.
start-sessionREJECTEDStation refused (connector faulted/occupied) or token not authorized.
ACCEPTED but sessionId stays nullStation accepted but the driver never plugged in / transaction never started. Some stations only start the transaction after the cable is connected.
stop-session OK but session stays ACTIVEStation hasn't confirmed the stop yet — it must send the stop transaction event. If it persists, station is offline or ignored the request; check logs.
Availability change has no visible effectVerify via connector status afterwards; trigger StatusNotification. Some stations only apply INOPERATIVE after the running transaction ends (OCPP: "Scheduled").
Diagnostics url gives 404 / empty fileUpload not finished (or failed). Wait for DiagnosticsStatusNotification in the logs; hosted links expire after 1 hour — re-request if expired.
Every command 404sYou are using OCPP IDs where UUIDs are expected. Only reset, stop-session (chargingStationId), and station-level availability accept the OCPP station ID as an alternative.

Reporting an issue

Include: the endpoint and request body (minus the API key), the response, the X-Correlation-Id response header, the v2 ocppMessageId, and the timestamp with timezone. These let operators trace the exact request through CPMS and OCPP adapter logs.

Related



Did this page help you?