Endpoints¶
| Method | Path | Token | Purpose |
|---|---|---|---|
| GET | /health | no | Liveness; 503 once the shutdown has begun |
| GET | /metrics | yes by default | Prometheus text format, never touches a device |
| GET | /docs, /openapi.json | no | Swagger UI and OpenAPI document; only with documentation enabled (DOCS_PUBLIC, GUI Settings), otherwise 404 |
| GET | /api/v1/readiness | yes | Readiness per device |
| GET | /api/v1/metrics | yes | Metric list from the object registry |
| GET | /api/v1/devices | yes | Configured devices |
| GET | /api/v1/devices/{device_id}/metrics | yes | Several metrics, partial success |
| GET | /api/v1/devices/{device_id}/metrics/{metric_name} | yes | One metric |
| PUT | /api/v1/devices/{device_id}/metrics/{metric_name} | read/write | Write a metric (write access required) |
| POST | /api/v1/devices/{device_id}/actions/{action_name} | read/write | Trigger an action variable (write access required) |
| POST | /api/v1/devices/{device_id}/battery/dispatch | read/write | Start or atomically replace grid charging or load-following discharge |
| GET | /api/v1/devices/{device_id}/battery/dispatch | read/write | Read the current dispatch and restore state |
| DELETE | /api/v1/devices/{device_id}/battery/dispatch | read/write | Stop dispatch and restore the previous inverter settings |
| GET | /api/v1/devices/{device_id}/energy | read/write | Energy Manager state, readings, target window and action availability |
| POST | /api/v1/devices/{device_id}/energy/command | read/write | One business action: charge, discharge, hold, auto |
| GET | /api/v1/vendor/rct/objects, /transports, /devices/{device_id}/slaves | read/write | RCT diagnostics |
/metrics (Prometheus) and /api/v1/metrics (metric list) are different on purpose.
Vendor diagnostics are off
The vendor routes answer 404 because the internal switch ENABLE_VENDOR_DIAGNOSTICS defaults to off and is not an operator setting. Likewise the write, dispatch and Energy Manager routes answer 404 write_disabled while write access is off in the GUI; switching it takes effect at once.
Reading values¶
curl -H "Authorization: Bearer $TOKEN" \
"http://127.0.0.1:8000/api/v1/devices/main/metrics?names=battery_soc,inverter_state"
- Without
namesthe request returns all preselected metrics and is exempt from the batch limit; explicitnamesare limited to 32. - A partial success answers 200 with an
errorslist; a batch without a single value fails with 502device_unavailable. fresh=trueforces a device read instead of using the cache. It requires an explicitnameslist (at most 8 entries); withoutnamesthe request is rejected with 422invalid_request. Periodically delivered metrics are read from the device as well (the internalobservemode); the 409fresh_not_available_for_periodic_metriconly exists in the internalrejectmode, which is not an operator setting.staleandstale_reasonmark a cached value that could not be refreshed.
Writing values¶
curl -X PUT -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"value": 80}' \
http://127.0.0.1:8000/api/v1/devices/main/metrics/<metric_name>
- Needs write access enabled in the GUI, a
read/writetoken and a metric approved on the Inverters page (stored indata/rct.db). - The body is
{"value": <scalar>}; unknown fields are rejected. - The value is always named in the unit the metric reports on read. For a metric the catalog scales (
battery_soc_targetis given in percent, the device holds a ratio) the gateway converts it back before sending, so{"value": 80}and{"value": 80.0}write the same value. - The result reports
readback_valueandconfirmed. If the value was sent but could not be confirmed, the request fails with 502write_outcome_unknown. - Metrics that are actions answer 409
metric_is_action; usePOST /api/v1/devices/{device_id}/actions/{action_name}with the same body. The protocol has no execution feedback, soaction_confirmedis alwaysfalseand the response carries anaction_note.
Readiness¶
GET /api/v1/readiness answers 200 with ready: true when every device is in a ready state, and 503 not_ready (with a devices member) otherwise.
Battery dispatch¶
Battery dispatch is available only when write support is enabled, all four power_mng_* registers are approved on the Inverters page, and the device's required capabilities for the requested mode are verified (or its engineering mode is on) — see Battery dispatch capabilities. A device with an unverified required capability answers 409 dispatch_unverified, naming the missing capabilities. Starting a dispatch when the device's control snapshot could not be read freshly enough answers 503 dispatch_snapshot_stale; retry. A persisted dispatch record that cannot be read back (corrupt or incomplete) answers 503 dispatch_record_corrupt for that device only — other devices keep operating normally.
Grid charging:
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"mode":"charge_from_grid","target_soc_percent":80,"max_power_w":3000,"valid_until":"2026-10-05T23:00:00+02:00"}' \
http://127.0.0.1:8000/api/v1/devices/main/battery/dispatch
Load-following discharge:
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"mode":"discharge_to_load","target_soc_percent":20,"max_power_w":5000,"valid_until":"2026-10-05T23:00:00+02:00"}' \
http://127.0.0.1:8000/api/v1/devices/main/battery/dispatch
max_power_wis an upper bound and is clamped to the configured device limit.discharge_to_loadreduces the setpoint immediately when the grid is exporting; deadband and write interval do not delay the cut.valid_untilis mandatory and must include a timezone offset. The service also caps it at six hours.- A second
POSTreplaces the active operation. Setexpected_operation_idfor compare-and-swap semantics. DELETEfirst requests 0 W and then restores the captured pre-dispatch register values.FAULT_RESTORE_PENDINGmeans restoration could not be confirmed. New dispatches remain blocked until restore succeeds.export_to_gridis reserved but currently returns409 dispatch_mode_unavailable.holdis a validmodeas well: it pins the battery at 0 W under our control, takes notarget_soc_percentand no power budget, and is gated per device like every other mode. It is not verified on hardware — see Energy Manager.
Energy Manager¶
Business-level control in front of battery dispatch, available while the operator has set the inverter to mode External: one action (charge, discharge, hold, auto) plus target_soc_percent where needed. Actions, errors and readings are described in Energy Manager.
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"action":"charge","target_soc_percent":80}' \
http://127.0.0.1:8000/api/v1/devices/main/energy/command
409 energy_manager_off- the inverter is switched off; an operator selects a mode in the admin GUI (the public API cannot).409 energy_manager_not_external- the inverter is in Manual mode, which only the admin GUI may command; an operator must switch it to External.- The status carries
modeandaccepts_commands_from;armedis derived (mode != "off"). The expert endpoint/battery/dispatchabove needs no mode. 409 energy_action_unavailable- the action is not available right now, for example after its register approvals were revoked.