Introduction
API guide
  • AuthenticationSoon
  • Your first API callSoon
  • Interactive API referenceSoon
  • Roles and permissionsSoon
  • Errors, pagination and versioningSoon
  • Live updatesSoon
  • Sending commands to a chargerSoon
  • Rate limitsSoon
Troubleshooting
  • My charger will not connectSoon
  • It connects, then dropsSoon
  • A command timed out or returned 409Soon
  • A card is not being authorizedSoon
  • My transaction looks wrongSoon
  • Meter values are missing or sparseSoon
  • Reading the OCPP message logSoon
  • Known limitationsSoon
Reference
  • GlossarySoon
  • Endpoint indexSoon
  • OCPP message supportSoon
  • Status and error codesSoon
  • ChangelogSoon
Flowion Docs

Read and change charger settings

OCPP functional block B — Provisioning.

Every station carries settings: how often to send meter values, what to measure, how long to wait before giving up on a connection. OCPP 1.6 models these as flat configuration keys; OCPP 2.x replaces them with a structured device model. Both are reachable here, and which one applies depends on what the station negotiated.

Cached reads and live round-trips#

There are two ways to read a setting, and the difference matters.

Cached — fast, no round-trip, possibly stale:

curl "https://api.flowion.io/v1/chargers/$CHARGER/configuration?per_page=100" \
  -H "Authorization: Bearer $TOKEN"

This returns what we last saw, backed by the most recent successful get-configuration or change-configuration. It answers immediately and works while the station is offline.

Live — a real command, blocking until the station answers:

curl -X POST https://api.flowion.io/v1/chargers/$CHARGER/commands/get-configuration \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keys": ["MeterValueSampleInterval", "HeartbeatInterval"]}'

Omitting keys — or passing an empty array — asks for every setting the station has, which is also how the cache gets refreshed. That refresh happens on a timer anyway, so the cached read is rarely badly out of date.

Use the cache for display and inventory. Use the command when you are about to act on the value.

Changing a 1.6 setting#

curl -X POST https://api.flowion.io/v1/chargers/$CHARGER/commands/change-configuration \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"key": "MeterValueSampleInterval", "value": "60"}'

Both fields are strings — OCPP 1.6 has no types here. "60", not 60.

A 200 means the station answered, which is not the same as saying yes. The answer can be Rejected (it will not), NotSupported (it does not have that key), or RebootRequired (accepted, but not in effect until it restarts).

RebootRequired is easy to miss. The change is stored, the response is successful, and nothing takes effect. If a setting change appears to do nothing, check whether the station asked for a reboot and give it a reset.

The 2.x device model#

OCPP 2.x replaces flat keys with components and variables. A component is a part of the station — a connector, a meter, the controller. A variable is a named value on that component, with attributes such as Actual and Target.

Read the cached model:

curl "https://api.flowion.io/v1/chargers/$CHARGER/device-model?q=heartbeat" \
  -H "Authorization: Bearer $TOKEN"

q filters over component name, component instance and variable name, which is how you find anything in a model that can run to hundreds of entries.

Read and write live:

curl -X POST https://api.flowion.io/v1/chargers/$CHARGER/commands/get-variables \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"variables": [{"component": {"name": "OCPPCommCtrlr"},
                      "variable": {"name": "HeartbeatInterval"}}]}'
curl -X POST https://api.flowion.io/v1/chargers/$CHARGER/commands/set-variables \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"variables": [{"component": {"name": "OCPPCommCtrlr"},
                      "variable": {"name": "HeartbeatInterval"},
                      "value": "300"}]}'

Both requests are checked against the station's known device model before being relayed, so a typo'd component or variable fails fast instead of travelling to the station and coming back rejected. Pass "skip_device_model_check": true to bypass that — useful when the cached model is incomplete and you are certain the target exists.

Which one applies?#

The station's negotiated version decides. A 1.6 station has configuration keys and no device model; a 2.x station has a device model. Check ocpp_version on the charger before choosing an endpoint, or you will get a 422 telling you the request is not expressible in that station's OCPP version.

Settings worth getting right#

Concern1.6 keyWhy
Telemetry frequencyMeterValueSampleIntervalToo long and sessions look empty; too short and you pay for traffic
What is measuredMeterValuesSampledDataWithout an energy register you get transactions with no consumption
Session boundariesStopTransactionOnEVSideDisconnectDecides whether unplugging ends the session
Cable releaseUnlockConnectorOnEVSideDisconnectDecides whether a cable frees itself
Status noiseMinimumStatusDurationSuppresses very short-lived status changes

The last one is worth knowing about even if you never set it: a station may legitimately omit status changes that lasted less than this, so a connector can move from Preparing to Charging with nothing in between.

Asking a station to report#

Sometimes you do not want to change anything — you want the station to tell you something now:

curl -X POST https://api.flowion.io/v1/chargers/$CHARGER/commands/trigger-message \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"requested_message": "boot_notification"}'

Available triggers: boot_notification, heartbeat, meter_values, status_notification, transaction_event, and custom on 2.1 with a custom_trigger name.

Two things to know. Adding connector_id asks about one connector — omitting it is not the same as asking about all of them, and 1.6 forbids naming connector 0 here, so that request comes back 422 rather than travelling.

And the accepted answer only means the station intends to send the message. Nothing correlates the triggered message with your request when it arrives, and nothing tracks whether an accepted trigger was ever honoured. Treat it as a nudge, not a request/response.

What the status codes mean#

Every command endpoint shares these:

CodeMeaning
200The station answered — including answering "no"
409The station is not connected
422Not expressible in this station's OCPP version, or not permitted
502The station answered with something unusable
503The command could not be sent
504The station did not answer in time

Endpoints#

Configuration · Commands · Command History