> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coreflux.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Victron VRM API

> Client-mode REST API connector for the Victron Energy VRM API v2: list and search installations, read the device list, power, energy, battery and forecast stats, overall totals, alarm log, alarm rules, diagnostics, Dynamic ESS settings and GPS tracks, and clear alarms, manage alarm rules, tags and installation settings

Technical Preview

> [!WARNING]
>
> **Use an access token.** VRM sends the token in the `X-Authorization` header, not in `Authorization`. Victron deprecated `Bearer` login tokens from June 1, 2026. Create a personal access token in the VRM Portal and send it as `Token <access_token>`.

## Overview

Victron GX devices (Cerbo GX, Ekrano GX, Venus GX and other Venus OS devices) upload data from inverters/chargers, MPPT solar chargers, battery monitors, meters and EV chargers to the **VRM Portal**. The **VRM API v2** (`https://vrmapi.victronenergy.com/v2`) gives programmatic access to the same data. Victron publishes it as an OpenAPI 3.1 document on [vrm-api-docs.victronenergy.com](https://vrm-api-docs.victronenergy.com).

The **VictronVrmApi** connector maps 20 MQTT topics onto that API: 13 read events (12 `GET` plus one read-only `POST` lookup) and 7 write events. Typical uses are putting PV yield, battery state of charge and consumption from remote Victron sites (off-grid cabins, telecom shelters, boats, ESS systems) on the broker next to plant data, and turning VRM alarms into broker alarms. Each event publishes the VRM reply on `<topic>/response`.

| Event | Topic | Request | Use |
| - | - | - | - |
| `GetMe` | `energy/victron/user/get` | `GET /v2/users/me` | Who the token belongs to: user.id (idUser), name, email, accessLevel |
| `ListInstallations` | `energy/victron/installation/list` | `GET /v2/users/{user_id}/installations?{query}` | Installations the user can read (records\[].idSite, name, identifier, timezone); query extended=1 and/or idSite=, or "" |
| `SearchInstallations` | `energy/victron/installation/search` | `GET /v2/users/{user_id}/search?{query}` | Full-text search over the user's installations (name, identifier, products); query query=\<text> (required) |
| `GetSiteId` | `energy/victron/site-id/get` | `POST /v2/users/{user_id}/get-site-id` | Read-only lookup (POST): VRM portal id (identifier) -> idSite; body \{"installation\_identifier": "c0619ab27f32"} |
| `GetSystemOverview` | `energy/victron/system-overview/get` | `GET /v2/installations/{id}/system-overview` | Devices connected to the site: GX gateway, Multi/Quattro, MPPT, battery monitor, meters, firmware, last connection |
| `GetStats` | `energy/victron/stats/get` | `GET /v2/installations/{id}/stats?{query}` | Time series (default live\_feed, hours, last 24 h); query type=kwh/venus/consumption/solar\_yield/forecast/custom\&interval=\&start=\&end=\&attributeCodes\[]= |
| `GetOverallStats` | `energy/victron/overall-stats/get` | `GET /v2/installations/{id}/overallstats?{query}` | Totals and percentages for the last year, month, week and day; query type=kwh/custom\&attributeCodes\[]= or "" |
| `ListAlarmRules` | `energy/victron/alarm/list` | `GET /v2/installations/{id}/alarms` | Configured alarm rules (thresholds, recipients, attributes available for new rules); needs full / admin rights on the site |
| `GetAlarmLog` | `energy/victron/alarm-log/get` | `GET /v2/installations/{id}/alarm-log?{query}` | Alarm / fault log: active first, then cleared (started, cleared, description, device); query start=\&end=\&page=\&count= |
| `GetDiagnostics` | `energy/victron/diagnostics/get` | `GET /v2/installations/{id}/diagnostics?{query}` | Logged data per attribute (Device, code, description, formattedValue, rawValue, dbusPath, timestamp); query count=\&page=; needs full rights |
| `GetDynamicEssSettings` | `energy/victron/dynamic-ess-settings/get` | `GET /v2/installations/{id}/dynamic-ess-settings` | Dynamic ESS configuration: battery capacity / costs, charge and discharge power, grid limits, price formulas, isOn |
| `ListTags` | `energy/victron/tag/list` | `GET /v2/installations/{id}/tags?{query}` | Tags of the site; query filter= or ""; needs full rights |
| `GetGpsTrack` | `energy/victron/gps-track/get` | `GET /v2/installations/{id}/gps-download?{query}` | GPS track as KML (vehicles, boats); query start=\&end= (required, Unix seconds) |
| `ClearAlarm` | `energy/victron/alarm/clear` | `POST /v2/installations/{id}/clear-alarm` | WRITE: clear an active alarm and mark it cleared by the user in the event log; body \{"alarmId": \<idAlarm from alarm-log>} |
| `AddAlarmRule` | `energy/victron/alarm/add` | `POST /v2/installations/{id}/alarms` | WRITE: add an alarm rule; float body \{idDataAttribute, instance, AlarmEnabled, NotifyAfterSeconds, highAlarm, ...}, enum body camelCase \{alarmEnabled, notifyAfterSeconds, enumValues} |
| `EditAlarmRule` | `energy/victron/alarm/update` | `PUT /v2/installations/{id}/alarms` | WRITE: edit an alarm rule (same body as alarm/add, keyed by idDataAttribute + instance) |
| `DeleteAlarmRule` | `energy/victron/alarm/delete` | `DELETE /v2/installations/{id}/alarms` | WRITE: delete an alarm rule; DELETE with JSON body \{idDataAttribute, instance} |
| `AddTag` | `energy/victron/tag/add` | `PUT /v2/installations/{id}/tags` | WRITE: add a tag; body \{"tag": "porto-plant", "source": "user"} |
| `RemoveTag` | `energy/victron/tag/remove` | `DELETE /v2/installations/{id}/tags` | WRITE: remove a tag; DELETE with JSON body \{"tag": "porto-plant", "source": "user"} |
| `UpdateInstallationSettings` | `energy/victron/settings/update` | `POST /v2/installations/{id}/settings` | WRITE: update site settings (description = name, notes, phonenumber, noDataAlarmTimeout / noDataAlarmActive, alarmMonitoring, geofence, realtimeUpdates, inverterChargerControl, ...); send only the fields to change |

> [!WARNING]
>
> **Write events change VRM configuration.** `ClearAlarm`, `AddAlarmRule`, `EditAlarmRule`, `DeleteAlarmRule`, `AddTag`, `RemoveTag` and `UpdateInstallationSettings` change portal settings, not the hardware. `UpdateInstallationSettings` can turn `inverterChargerControl` on, which lets VRM users switch the inverter/charger remotely. Restrict who can publish to these topics with a rule. This connector does not include the Dynamic ESS write (it changes how the battery charges and discharges). It also leaves out user, invite and access-token management.

> [!TIP]
>
> For local, low-latency data without the cloud, read the GX device directly: Venus OS runs a local MQTT broker (bridge it with an MQTT bridge connector) and exposes a Modbus TCP register list (use a native Modbus connector). This connector is for VRM cloud data across many sites.

## Prerequisites

* A **VRM Portal** account ([vrm.victronenergy.com](https://vrm.victronenergy.com)) with access to at least one installation. A GX device must upload data to VRM.
* A **personal access token**. In VRM, open **Preferences > Integrations > Access tokens**, create a token, and copy it. VRM shows it only once.
* Your **user id** (`idUser`) for the user-level events. `user/get` returns it as `user.id`.
* The **installation id** (`idSite`) of each site. `installation/list` returns it as `records[].idSite`. It is a number, such as `219742`. It is **not** the VRM portal ID (`identifier`, for example `c0619ab27f32`). `site-id/get` converts a portal ID to `idSite`.
* **Full access** (admin rights) to the site for the alarm rules, diagnostics, tags and write events. Users with read-only access get `403`.
* Outbound HTTPS from the broker to `vrmapi.victronenergy.com`.

## Authentication

Every event sends `X-Authorization: {value.json.authorization}`. Store the full header value as a Hub secret, for example `VRM_AUTHORIZATION` = `Token <access_token>`, and read it with `GET SECRET` in the action that publishes to the connector.

| Format | Source | Notes |
| - | - | - |
| `Token <access_token>` | VRM Preferences > Integrations > Access tokens, or `POST /v2/users/{idUser}/accesstokens` | Recommended. Lasts until you revoke it or it reaches its expiry date |
| `Bearer <jwt>` | `POST /v2/auth/login` (user name and password) | Deprecated from June 1, 2026. Expires after 24 hours |

| Response | Meaning |
| - | - |
| `401` `{"errors":"Login required","error_code":"invalid_credentials"}` | No `X-Authorization` header (a plain `Authorization` header is ignored) |
| `401` `{"errors":"Invalid accesstoken received","error_code":"invalid_token"}` | The `Token` value is unknown or revoked, or a JWT was sent with the `Token` prefix |
| `401` `{"errors":"Token is invalid","error_code":"invalid_token"}` | The `Bearer` JWT is invalid or expired |
| `403` `{"error_code":"forbidden"}` | The token's user has no access, or not enough rights, on that site |
| `429` with `Retry-After` | Rate limit reached; wait that many seconds |

## Configuration

| Setting | Value |
| - | - |
| `BASE_ADDRESS` | `https://vrmapi.victronenergy.com` (endpoints carry `/v2`) |
| `USE_SSL` | `"true"` |
| `DEFAULT_CONTENT_TYPE` | `application/json` |
| Payload fields | `authorization`, `user_id` (`idUser`), `id` (`idSite`), `query` (pre-encoded query string, `""` for none), `body` (JSON object for the `POST`, `PUT` and `DELETE` events) |

Query parameters:

| Event | Parameters | Notes |
| - | - | - |
| `GetStats` | `type`, `interval`, `start`, `end`, `attributeCodes[]`, `show_instance` | `type`: `live_feed` (default), `venus`, `consumption`, `solar_yield`, `kwh`, `generator`, `generator-runtime`, `forecast`, `custom` (needs at least one `attributeCodes[]`, such as `bs` for battery SoC). `interval`: `15mins`, `hours` (default), `2hours`, `days`, `weeks`, `months`, `years`. `start` / `end` are Unix seconds (default: the last 24 hours) |
| `GetOverallStats` | `type`, `attributeCodes[]` | Same `type` values without `forecast`. Returns `year`, `month`, `week` and `today` totals |
| `GetAlarmLog` | `start`, `end`, `page`, `count` | Unix seconds. `count` defaults to 3,000. Active alarms come first |
| `GetDiagnostics` | `count`, `page` | Default 100 records |
| `ListInstallations` | `extended`, `idSite` | `extended=1` adds tags, images, current alarms and more |
| `SearchInstallations` | `query` (required) | Free text, such as `query=ESS` |
| `GetGpsTrack` | `start`, `end` (required) | Unix seconds. Returns KML, not JSON |
| `ListTags` | `filter` | Optional |

Maximum `GetStats` window for each `interval`:

| Interval | Maximum window |
| - | - |
| `15mins`, `hours` | 31 days |
| `days` | 180 days |
| `weeks` | 140 days |
| `months` | 24 months |
| `years` | 5 years |

Stats series come back as `{"success": true, "records": {"<code>": [[timestamp_ms, value, ...], ...]}, "totals": {"<code>": value}}`. The timestamps are in milliseconds. Codes include `Pdc` (PV DC power), `bs` (battery SoC), `bv` (battery voltage), `kwh` and grid / consumption codes. Other responses use `{"success": true, "records": ...}`, and errors use `{"success": false, "errors", "error_code"}`.

## Basic Syntax

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
# Coreflux REST_API template — Victron Energy VRM API v2 (VRM Portal cloud for Victron GX / Cerbo / Venus OS systems):
#   identify the token's user, list and search the installations (sites) it can read, read the device list behind a
#   site (system overview), power / energy / battery / forecast time series (stats), year / month / week / day totals
#   (overall stats), the alarm / fault log, configured alarm rules, diagnostics (logged data per attribute with
#   D-Bus path), Dynamic ESS settings, tags and GPS tracks; and (marked WRITE) clear an active alarm, add / edit /
#   delete alarm rules, add / remove tags and update installation settings.
# Hugo catalog #179, Tier 2 (energy). Spec: official VRM API OpenAPI 3.1 (info.version 2) from
#   https://vrm-api-docs.victronenergy.com (docs/docs/openapi.yaml + its $ref files, fetched 2026-10-05; bundled and
#   curated slim in openapi-cache/victron-vrm-api.json). Credentials are placeholders only.
# Docs: https://docs.coreflux.org/latest/lot-language/routes/rest-api-apps/victron-vrm-api
#
# Auth: X-Authorization: {value.json.authorization} on every call. The header is X-Authorization, not Authorization
#   (a plain "Authorization: Bearer ..." answers 401 "Login required"). Two value formats:
#     "Token <access_token>"  personal access token, VRM Portal > Preferences > Integrations > Access tokens (or
#                             POST /v2/users/{idUser}/accesstokens). Recommended. Keep it in Hub secrets (suggested
#                             VRM_AUTHORIZATION = "Token <access_token>") and map it into the payload with GET SECRET.
#     "Bearer <jwt>"          login JWT from POST /v2/auth/login (24 h). Victron deprecates Bearer login tokens from
#                             2026-06-01 onwards; still accepted today (the public demo login returns one).
#   No header: 401 {"success":false,"errors":"Login required","error_code":"invalid_credentials"}; bad access token:
#   401 "Invalid accesstoken received" (invalid_token); no rights on the site: 403 "forbidden".
# Rate limit: rolling window of 200 requests, one slot freed every 0.33 s (about 3 requests per second sustained).
#   429 with JSON carries Retry-After (seconds). VRM data is logged every 1-15 minutes (GX logging interval), so poll
#   stats every 15 minutes or slower.
# Ids: user_id = idUser (from user/get: user.id), id = idSite (from installation/list: records[].idSite). idSite is
#   NOT the VRM portal id ("identifier", e.g. c0619ab27f32); site-id/get maps a portal id to idSite.
# Queries: events with ?{value.json.query} take a pre-encoded query string ("" for none). Unix timestamps in
#   SECONDS for start= / end= (responses use milliseconds in stats series and seconds elsewhere).
#     stats       type=venus|live_feed|consumption|solar_yield|kwh|generator|generator-runtime|custom|forecast,
#                 interval=15mins|hours|2hours|days|weeks|months|years, start=, end=, attributeCodes[]=bs (custom),
#                 show_instance=1. Max window: 31 days (15mins / hours), 180 days (days), 140 days (weeks),
#                 24 months (months), 5 years (years).
#     alarm-log   start=, end=, page=, count= (default 3000); active entries first.
#     installation/list  extended=1 and/or idSite=<idSite>;  installation/search  query=<text> (required)
# Writes (marked WRITE below): ClearAlarm, AddAlarmRule, EditAlarmRule, DeleteAlarmRule, AddTag, RemoveTag,
#   UpdateInstallationSettings. They change VRM portal configuration only (alarm rules, tags, name / notes / alarm and
#   geofence settings); none of them switches an inverter. UpdateInstallationSettings can toggle
#   inverterChargerControl (whether VRM users may remote-control the inverter/charger) and realtimeUpdates, so
#   restrict who can publish to it. Not packaged: Dynamic ESS writes (change battery charge / discharge behaviour),
#   user / invite / access-token / unlink management, reset-forecasts, custom widgets, data-download exports.
# Responses: JSON {"success": true, "records": ...} (dynamic-ess-settings: "data"); errors {"success": false,
#   "errors", "error_code"}. gps-download answers KML (application/vnd.google-earth.kml+xml).
#
# Payload fields: authorization, user_id (idUser), id (idSite), query, body (JSON object for POST / PUT / DELETE)
#     ListInstallations  user_id = "22", query = "extended=1"
#     GetStats           id = "219742", query = "type=kwh&interval=days&start=1790000000&end=1791200000"
#     GetStats           id = "219742", query = "type=custom&attributeCodes[]=bs&interval=hours"
#     GetAlarmLog        id = "151734", query = "count=50"
#     ClearAlarm         id = "219742", body = {"alarmId": 1012027262}
#     AddTag             id = "219742", body = {"tag": "porto-plant", "source": "user"}

DEFINE ROUTE VictronVrmApi WITH TYPE REST_API
    ADD REST_API_CONFIG
        WITH BASE_ADDRESS "https://vrmapi.victronenergy.com"
        WITH ENABLE_CLIENT "true"
        WITH USE_SSL "true"
        WITH REQUEST_TIMEOUT '30'
        WITH DEFAULT_CONTENT_TYPE "application/json"
        # Smoke: GetMe -> ListInstallations -> GetSystemOverview -> GetStats (kwh, days) -> GetOverallStats -> GetAlarmLog.
    ADD EVENT GetMe
        WITH SOURCE_TOPIC "energy/victron/user/get"
        WITH DESTINATION_TOPIC "energy/victron/user/get/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/v2/users/me"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
    ADD EVENT ListInstallations
        WITH SOURCE_TOPIC "energy/victron/installation/list"
        WITH DESTINATION_TOPIC "energy/victron/installation/list/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/v2/users/{value.json.user_id}/installations?{value.json.query}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
    ADD EVENT SearchInstallations
        WITH SOURCE_TOPIC "energy/victron/installation/search"
        WITH DESTINATION_TOPIC "energy/victron/installation/search/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/v2/users/{value.json.user_id}/search?{value.json.query}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
    ADD EVENT GetSiteId
        WITH SOURCE_TOPIC "energy/victron/site-id/get"
        WITH DESTINATION_TOPIC "energy/victron/site-id/get/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/v2/users/{value.json.user_id}/get-site-id"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
            ADD "Content-Type" "application/json"
        WITH BODY "{value.json.body}"
    ADD EVENT GetSystemOverview
        WITH SOURCE_TOPIC "energy/victron/system-overview/get"
        WITH DESTINATION_TOPIC "energy/victron/system-overview/get/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/v2/installations/{value.json.id}/system-overview"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
    ADD EVENT GetStats
        WITH SOURCE_TOPIC "energy/victron/stats/get"
        WITH DESTINATION_TOPIC "energy/victron/stats/get/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/v2/installations/{value.json.id}/stats?{value.json.query}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
    ADD EVENT GetOverallStats
        WITH SOURCE_TOPIC "energy/victron/overall-stats/get"
        WITH DESTINATION_TOPIC "energy/victron/overall-stats/get/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/v2/installations/{value.json.id}/overallstats?{value.json.query}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
    ADD EVENT ListAlarmRules
        WITH SOURCE_TOPIC "energy/victron/alarm/list"
        WITH DESTINATION_TOPIC "energy/victron/alarm/list/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/v2/installations/{value.json.id}/alarms"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
    ADD EVENT GetAlarmLog
        WITH SOURCE_TOPIC "energy/victron/alarm-log/get"
        WITH DESTINATION_TOPIC "energy/victron/alarm-log/get/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/v2/installations/{value.json.id}/alarm-log?{value.json.query}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
    ADD EVENT GetDiagnostics
        WITH SOURCE_TOPIC "energy/victron/diagnostics/get"
        WITH DESTINATION_TOPIC "energy/victron/diagnostics/get/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/v2/installations/{value.json.id}/diagnostics?{value.json.query}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
    ADD EVENT GetDynamicEssSettings
        WITH SOURCE_TOPIC "energy/victron/dynamic-ess-settings/get"
        WITH DESTINATION_TOPIC "energy/victron/dynamic-ess-settings/get/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/v2/installations/{value.json.id}/dynamic-ess-settings"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
    ADD EVENT ListTags
        WITH SOURCE_TOPIC "energy/victron/tag/list"
        WITH DESTINATION_TOPIC "energy/victron/tag/list/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/v2/installations/{value.json.id}/tags?{value.json.query}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
    ADD EVENT GetGpsTrack
        WITH SOURCE_TOPIC "energy/victron/gps-track/get"
        WITH DESTINATION_TOPIC "energy/victron/gps-track/get/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/v2/installations/{value.json.id}/gps-download?{value.json.query}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
    # WRITE: ClearAlarm changes VRM configuration. Restrict who can publish to energy/victron/alarm/clear.
    ADD EVENT ClearAlarm
        WITH SOURCE_TOPIC "energy/victron/alarm/clear"
        WITH DESTINATION_TOPIC "energy/victron/alarm/clear/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/v2/installations/{value.json.id}/clear-alarm"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
            ADD "Content-Type" "application/json"
        WITH BODY "{value.json.body}"
    # WRITE: AddAlarmRule changes VRM configuration. Restrict who can publish to energy/victron/alarm/add.
    ADD EVENT AddAlarmRule
        WITH SOURCE_TOPIC "energy/victron/alarm/add"
        WITH DESTINATION_TOPIC "energy/victron/alarm/add/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/v2/installations/{value.json.id}/alarms"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
            ADD "Content-Type" "application/json"
        WITH BODY "{value.json.body}"
    # WRITE: EditAlarmRule changes VRM configuration. Restrict who can publish to energy/victron/alarm/update.
    ADD EVENT EditAlarmRule
        WITH SOURCE_TOPIC "energy/victron/alarm/update"
        WITH DESTINATION_TOPIC "energy/victron/alarm/update/response"
        WITH METHOD "PUT"
        WITH ENDPOINT "/v2/installations/{value.json.id}/alarms"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
            ADD "Content-Type" "application/json"
        WITH BODY "{value.json.body}"
    # WRITE: DeleteAlarmRule changes VRM configuration. Restrict who can publish to energy/victron/alarm/delete.
    ADD EVENT DeleteAlarmRule
        WITH SOURCE_TOPIC "energy/victron/alarm/delete"
        WITH DESTINATION_TOPIC "energy/victron/alarm/delete/response"
        WITH METHOD "DELETE"
        WITH ENDPOINT "/v2/installations/{value.json.id}/alarms"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
            ADD "Content-Type" "application/json"
        WITH BODY "{value.json.body}"
    # WRITE: AddTag changes VRM configuration. Restrict who can publish to energy/victron/tag/add.
    ADD EVENT AddTag
        WITH SOURCE_TOPIC "energy/victron/tag/add"
        WITH DESTINATION_TOPIC "energy/victron/tag/add/response"
        WITH METHOD "PUT"
        WITH ENDPOINT "/v2/installations/{value.json.id}/tags"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
            ADD "Content-Type" "application/json"
        WITH BODY "{value.json.body}"
    # WRITE: RemoveTag changes VRM configuration. Restrict who can publish to energy/victron/tag/remove.
    ADD EVENT RemoveTag
        WITH SOURCE_TOPIC "energy/victron/tag/remove"
        WITH DESTINATION_TOPIC "energy/victron/tag/remove/response"
        WITH METHOD "DELETE"
        WITH ENDPOINT "/v2/installations/{value.json.id}/tags"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
            ADD "Content-Type" "application/json"
        WITH BODY "{value.json.body}"
    # WRITE: UpdateInstallationSettings changes VRM configuration. Restrict who can publish to energy/victron/settings/update.
    ADD EVENT UpdateInstallationSettings
        WITH SOURCE_TOPIC "energy/victron/settings/update"
        WITH DESTINATION_TOPIC "energy/victron/settings/update/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/v2/installations/{value.json.id}/settings"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "X-Authorization" "{value.json.authorization}"
            ADD "User-Agent" "Coreflux-Broker REST_API route (https://www.coreflux.org)"
            ADD "Content-Type" "application/json"
        WITH BODY "{value.json.body}"
```

## Examples

Publish directly to a connector topic:

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{"authorization": "Token <access_token>", "id": "219742", "query": "type=kwh&interval=days&start=1790000000&end=1791200000"}
```

to `energy/victron/stats/get`, then read `energy/victron/stats/get/response` for daily energy (`Pc`, `Pb`, `Pg`, `Bc`, `Bg`, `kwh`) for that window.

Clear an active alarm (take `idAlarm` from `alarm-log/get`):

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{"authorization": "Token <access_token>", "id": "219742", "body": {"alarmId": 1012027262}}
```

to `energy/victron/alarm/clear`.

Actions that poll the connector for one site:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
# Example actions for the VictronVrmApi route (docs page). Not part of the route template.
# Secret: VRM_AUTHORIZATION = "Token <access_token>" (personal access token from VRM Portal > Preferences >
#   Integrations > Access tokens). The value is sent as the X-Authorization header.
# Installation id 219742 is the "ESS System" of the public VRM demo account. Replace it with your own idSite
#   (from installation/list: records[].idSite).
# Inline JSON object literals are not supported when publishing to a topic, so the request payload is a COLLAPSED
#   model sent with PUBLISH MODEL.
# Budget: these four actions make about 4 + 1 + 0.25 + 0.04 = 5.3 calls per hour, far below the VRM rate limit
#   (rolling window of 200 requests, about 3 per second sustained).

DEFINE MODEL VrmRequest COLLAPSED
    ADD STRING "authorization"
    ADD STRING "id"
    ADD STRING "query"

DEFINE ACTION VrmLiveFeedEvery15Minutes
ON EVERY 15 MINUTES DO
    PUBLISH MODEL VrmRequest TO "energy/victron/stats/get" WITH
        authorization = (GET SECRET "VRM_AUTHORIZATION")
        id = "219742"
        query = "type=live_feed&interval=15mins"

DEFINE ACTION VrmAlarmLogHourly
ON EVERY 1 HOUR DO
    PUBLISH MODEL VrmRequest TO "energy/victron/alarm-log/get" WITH
        authorization = (GET SECRET "VRM_AUTHORIZATION")
        id = "219742"
        query = "count=20"

DEFINE ACTION VrmSystemOverviewEvery4Hours
ON EVERY 4 HOURS DO
    PUBLISH MODEL VrmRequest TO "energy/victron/system-overview/get" WITH
        authorization = (GET SECRET "VRM_AUTHORIZATION")
        id = "219742"
        query = ""

DEFINE ACTION VrmDailyKwhTotals
ON EVERY 1 DAY DO
    PUBLISH MODEL VrmRequest TO "energy/victron/overall-stats/get" WITH
        authorization = (GET SECRET "VRM_AUTHORIZATION")
        id = "219742"
        query = "type=kwh"
```

Restrict who can publish to `energy/victron/#` with a rule, because these payloads carry the access token.

## Rate limits and polling

VRM rate-limits most endpoints with a rolling window of 200 requests. One request leaves the window every 0.33 seconds, so about 3 requests per second never hit the limit. A `429` with a JSON body has a `Retry-After` header with the seconds to wait. The GX device logs to VRM every 1 to 15 minutes (its logging interval), so polling stats faster than every 15 minutes rarely returns new data. Use one `GetStats` call with `type=custom` and several `attributeCodes[]` instead of many separate calls.

## Notes

* **Demo account:** VRM has a public demo account (user 22) with several sample installations, such as **ESS System** (`219742`), **35ft Yacht** (`151734`) and **Off-grid** (`209689`). The demo is read-only. It answers `403` for alarm rules, diagnostics, tags, the site id lookup and every write.
* **Alarms:** `alarm/list` returns the alarm **rules** configured on a site. `alarm-log/get` returns the alarms that fired, with `started` and `cleared` timestamps. When a site has no log entries, it returns `200` with `{"success": false, "error_code": "no_results_found"}`.
* **Alarm rule bodies:** float alarms use PascalCase `AlarmEnabled` and `NotifyAfterSeconds`; enum alarms use camelCase `alarmEnabled` and `notifyAfterSeconds` with `enumValues`. VRM returns a warning if the case is wrong.
* **DELETE with a body:** `DeleteAlarmRule` and `RemoveTag` send a JSON body with `DELETE`, as the VRM spec requires.
* **Support:** Victron does not offer direct support for the VRM API. Use the Modifications section of the Victron Community.
* Reports and CSV / XLSX exports moved to a separate VRM Reports API and are not covered here.

## Testing

Static checks compare all 20 events with the official VRM OpenAPI 3.1 document, and a local contract mock covers all of them. Against the real API, 9 read events returned `200` with the public demo account: user, installation list and search, system overview, stats (live feed, kWh, custom SoC, forecast), overall stats, alarm log, Dynamic ESS settings and GPS track. The 4 read events that need full rights (alarm rules, diagnostics, tags, site id lookup) and 5 write probes with no-op payloads returned `403 forbidden` on the demo, as expected. The `Token` access-token format was checked only by its `401 invalid_token` response, because the demo gives a `Bearer` JWT. A run with your own access token is still needed (see the factory `TEST.md`).

## Not covered

Dynamic ESS writes, reset forecasts, custom widgets, data and installation-overview downloads, user, invite, group and access-token management, admin endpoints, the deprecated `widgets/*` endpoints, and the login call itself.

## Related

* [REST API Connectors](/latest/lot-language/routes/rest-api-routes)
* [REST API app templates](/latest/lot-language/routes/rest-api-apps/index)
* [SolarEdge Monitoring API](/latest/lot-language/routes/rest-api-apps/solaredge-monitoring-api)
* [Enphase Enlighten API v4](/latest/lot-language/routes/rest-api-apps/enphase-enlighten-api-v4)
* [Fronius Solar API (local)](/latest/lot-language/routes/rest-api-apps/fronius-solar-api)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.