Reverse-engineered API documentation for the Hoval Connect IoT platform (used by Hoval heating/ventilation systems), plus a Home Assistant custom integration (HACS-compatible).
β οΈ Unofficial. Not affiliated with Hoval. Use at your own risk. API may change without notice.
Successor to Hoval-GatewayV2-CANBUS-MQTT. This cloud-based integration requires no additional hardware β just your Hoval Connect credentials. The previous project used CAN bus + MQTT via a physical gateway connection.
- In HACS, go to Integrations β Custom repositories
- Add
https://github.com/trcyberoptic/hoval-connect-apias an Integration - Install Hoval Connect
- Restart Home Assistant
- Go to Settings β Integrations β Add Integration β search Hoval Connect
- Enter your Hoval Connect email and password
Plants and circuits are discovered automatically from your account.
Fan entity (per HV ventilation circuit):
- Continuous speed slider: 0β100% (temporary override, keeps time program active)
- Turn on/off toggle (standby mode)
- Configurable turn-on mode: resume last program, or activate week1/week2
- Debounced slider input (1.5s) to prevent API rate-limiting
Climate entity (per HK heating circuit):
- Target temperature control
- HVAC modes: Heat / Auto / Off (standby)
- HVAC action reflects actual circuit status
Program select (per HV/HK circuit):
- Switch between week1, week2, eco mode, standby, constant
- Shows user-defined program names from the Hoval app
- Current program pre-selected
Sensor entities (per circuit):
- Outside temperature, exhaust temperature
- Air volume, humidity (actual), humidity (target)
- Operation mode, active week program, active day program, program air volume
Plant-level sensors:
- Weather condition and forecast temperature
- Latest event type, message, and timestamp
- Active event count
Binary sensors (per plant):
- Online/offline (connectivity class)
- Error status (problem class, detects blocking/locking events)
Diagnostics:
- Full diagnostic data export with automatic PII redaction (tokens, credentials, plant IDs)
Options (configurable per integration entry):
- Turn-on mode: resume / week1 / week2
- Temporary override duration: 4 hours / until midnight
- Polling interval (default: 60s)
Under the hood:
- 2-step token management (ID token + Plant Access Token) with TTL caching and auto-refresh
- Skips API calls when plant is offline, invalidates token cache on reconnect
- Parallel API fetches for circuits, live values, programs, events, and weather
- Program cache (5min TTL) reduces API calls
- Dynamic entity discovery β new circuits added without restart
- v1 API
activeProgramvalues normalized to v3 enum for consistent entity state
- HV and HK circuits only. Boiler (BL), warm water (WW), solar (SOL), and other circuit types are not yet implemented.
- No time program editing. Time programs can be read but not modified through the integration.
- No energy/temperature history. Historical statistics endpoints are documented but not yet integrated.
- No holiday mode control.
- Single account only. Each HA instance supports one Hoval Connect account.
- A Hoval Connect account (same credentials as the Hoval Connect mobile app)
- Home Assistant 2024.1.0 or newer
Hoval Connect is a cloud platform that connects Hoval HVAC systems (heating, ventilation, hot water) via an IoT gateway to Azure IoT Hub. The mobile app (Android/iOS) communicates through a REST API hosted on Azure.
Hoval Device ββ IoT Gateway ββ Azure IoT Hub ββ Hoval Core API ββ Mobile App / HA Integration
(REST/JSON)
| Component | URL |
|---|---|
| Core API | https://azure-iot-prod.hoval.com/core |
| Identity Provider | SAP Cloud Identity Services (IAS) |
| OIDC Discovery | https://akwc5scsc.accounts.ondemand.com/.well-known/openid-configuration |
| IoT Hub | iot-hub-neu-prod.azure-devices.net |
| Gateway Desk | gateway.hovaldesk.com |
| Monitoring | Grafana Cloud (logs-prod-012.grafana.net) |
Note: The
client_idbelow is the public OAuth2 client ID for the Hoval Connect mobile app, extracted from the official Android/iOS app. It is the same for all users and is required by the SAP IAS identity provider.
curl -X POST "https://akwc5scsc.accounts.ondemand.com/oauth2/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=password" \
-d "client_id=991b54b2-7e67-47ef-81fe-572e21c59899" \
-d "username=YOUR_EMAIL" \
-d "password=YOUR_PASSWORD" \
-d "scope=openid"Response:
{
"access_token": "opaque-token...",
"id_token": "eyJhbGci...",
"token_type": "Bearer",
"expires_in": 1800
}Important: Use the
id_token(JWT) as your Bearer token, NOT theaccess_token.
Token lifetime: 30 minutes.
JWT Claims:
| Claim | Description |
|---|---|
sub |
User ID (e.g., P000001) |
groups |
Hoval-IoT-Prod-BasicUser |
aud |
Array of audience IDs |
app_tid |
Application tenant ID |
Most plant-specific endpoints require an additional X-Plant-Access-Token header.
curl "https://azure-iot-prod.hoval.com/core/v1/plants/{plantExternalId}/settings" \
-H "Authorization: Bearer {id_token}"Response:
{
"token": "eyJhbGci...",
"featureMap": { "OP": "OWN_PLANT", "PE": "PROGRAMS_EDIT", ... },
"plantSetting": {
"plantExternalId": "123456789012345",
"address": { "street": "...", "city": "...", "countryCode": "CH" },
"plantName": "MyPlant"
},
"isPlantOwner": true
}Plant Access Token lifetime: ~15 minutes (JWT with exp claim).
id_token (30min) β Authorization: Bearer {id_token}
plant_access_token (15min) β X-Plant-Access-Token: {token}
https://azure-iot-prod.hoval.com/core
{plantId}= Plant External ID (15-digit number, e.g.,123456789012345){circuitPath}= Circuit path (e.g.,520.50.0)- π = Requires
Authorization: Bearer {id_token} - π = Also requires
X-Plant-Access-Token
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/bootstrap |
π | Environment info + user settings |
| GET | /api/my-plants?size=12&page=0 |
π | List user's plants |
| GET | /api/user-settings |
π | User profile |
| GET | /api/contracts/active?plantExternalId={plantId} |
π | Active service contracts |
{
"environmentInfo": {
"environment": "prod",
"solarWebUiBaseUrl": "https://helio.sun"
},
"userSetting": {
"userId": "P000001",
"email": "user@example.com",
"firstName": "...",
"lastName": "...",
"platformFeatures": ["REDEEM_PLANT_ACCESS_CODE"],
"language": "DE",
"availableLanguages": ["DE", "EN", "FR", "IT"]
}
}[
{
"plantExternalId": "123456789012345",
"description": "MyPlant",
"isOnline": true,
"isOnboarded": true,
"isContractValid": true
}
][
{
"ContractID": "0000000000",
"ContractType": "000000000000000000",
"ValidFrom": "2025-01-01",
"ValidTo": "2050-12-30",
"GatewaySerialID": "123456789012345",
"isOnboarded": true,
"Latitude": "47.000000",
"Longitude": "8.000000"
}
]| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /v1/plants/{plantId}/settings |
π | Plant access token + features + address |
| GET | /v1/plant-shares?plantExternalId={plantId} |
ππ | Shared access list |
| GET | /business/plants/{plantId}/is-online |
ππ | Online status (boolean) |
Circuits represent the controllable components of a plant (heating, ventilation, hot water, etc.).
| Code | Description |
|---|---|
| HK | Heating circuit (Heizkreis) |
| BL | Boiler |
| WW | Warm water (Warmwasser) |
| FRIWA | Fresh water station (Frischwasser) |
| HV | Home ventilation (LΓΌftung) |
| SOL | Solar |
| SOLB | Solar buffer |
| PS | Pool/Swimming |
| GW | Gateway |
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /v1/plants/{plantId}/circuits |
ππ | All circuits with details |
| GET | /v1/plants/{plantId}/circuits/{circuitPath} |
ππ | Single circuit detail |
| GET | /v3/plants/{plantId}/circuits |
ππ | Circuit overview (v3) |
| GET | /v3/plants/{plantId}/circuits/{circuitPath} |
ππ | Single circuit (v3) |
| GET | /v3/plants/{plantId}/circuits/{circuitPath}/programs |
ππ | Time programs for circuit |
| GET | /business/plants/{plantId}/circuits |
ππ | Circuit paths list |
| GET | /business/plants/{plantId}/heat-generators |
ππ | Heat generator info |
[
{
"type": "GW",
"moduleType": "GW",
"path": "1153.0.0",
"name": null,
"selectable": false,
"configuredCorrectly": true,
"hasError": false,
"operationMode": null
},
{
"type": "HV",
"moduleType": "HV",
"path": "520.50.0",
"name": "LΓΌftung",
"activeProgram": "tteControlled",
"targetAirVolume": 40,
"targetAirHumidity": 50,
"isAirQualityGuided": false,
"selectable": true,
"homeVent": true,
"hasError": false,
"operationMode": "REGULAR",
"plantTime": "2026-02-10T13:24:17+01:00"
}
]Note: PUT control endpoints return HTTP 204 No Content on success (no response body).
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /v1/plants/{plantId}/circuits/{circuitPath}/temporary-change?duration=FOUR|MIDNIGHT&value={airVolume} |
ππ | Temporary air volume override (keeps time program active) |
| POST | /v1/plants/{plantId}/circuits/{circuitPath}/temporary-change/reset |
ππ | Cancel active temporary override, resume time program |
/v1/plants/{plantId}/circuits/{circuitPath}/constant?value={airVolume} |
ππ | temporary-change instead) |
|
| POST | /v1/plants/{plantId}/circuits/{circuitPath}/standby |
ππ | Set standby mode |
| POST | /v1/plants/{plantId}/circuits/{circuitPath}/manual |
ππ | Set manual mode |
| POST | /v1/plants/{plantId}/circuits/{circuitPath}/time-programs |
ππ | Set time programs |
| POST | /v1/plants/{plantId}/circuits/{circuitPath}/reset |
ππ | Reset to auto |
/v3/plants/{plantId}/circuits/{circuitPath}/settings |
ππ |
| Method | Path | Auth | Parameters | Description |
|---|---|---|---|---|
| GET | /v3/api/statistics/live-values/{plantId} |
ππ | circuitPath, circuitType |
Live sensor values |
| GET | /v2/api/statistics/live-values/{plantId} |
ππ | circuitPath, circuitType |
Live values (v2) |
| GET | /v3/api/statistics/temperature/{plantId} |
ππ | circuitPath, circuitType, interval (24h|3d), datapoints |
Temperature history |
| GET | /v2/api/statistics/total-energy/{plantId} |
ππ | circuitPath, interval (7d|1M|1y|7y), granularity (1d|1w|1M|1y) |
Energy consumption |
| GET | /v2/api/statistics/heat-consumption/{plantId} |
ππ | circuitPath, interval |
Heat consumption |
| GET | /v2/api/statistics/solar-yield/{plantId} |
ππ | circuitPath, interval |
Solar yield |
| GET | /api/telemetry-data/snapshots/live/{plantId} |
ππ | dataPoints (array) |
Raw telemetry snapshots |
Parameters:
circuitPath(required): e.g.,520.50.0circuitType(required):HK,BL,WW,FRIWA,HV,SOL,SOLB,PS,GW
Response (HV circuit):
[
{ "key": "outsideTemperature", "value": "5.5" },
{ "key": "airVolume", "value": "40" },
{ "key": "humidityTarget", "value": "50" },
{ "key": "humidityActual", "value": "42" },
{ "key": "exhaustTemp", "value": "22.4" }
]| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /v2/api/weather/forecast/{plantId} |
ππ | 4-day weather forecast for plant location |
[
{
"_time": "2026-02-10T00:00:00Z",
"weatherCode": 3,
"weatherType": "partialCloud",
"outsideTemperatureMin": 4,
"outsideTemperature": 6
}
]| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /v1/plant-events/{plantId} |
π | Plant error events |
| GET | /v1/plant-events/latest/{plantId} |
π | Latest event |
| GET | /v1/plants/{plantId}/notifications |
ππ | Notification settings |
| GET | /business/notifications |
ππ | Business notifications |
[
{
"language": "DE",
"eventTypes": ["offline", "blocking", "warning", "info", "locking"],
"id": "xxxxxxxx-...",
"plantExternalId": "123456789012345",
"userId": "P000001",
"email": "user@example.com"
}
]| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /api/gateway-software/{plantId}/versions/current |
ππ | Current gateway SW version |
| Method | Path | Auth | Description |
|---|---|---|---|
| PUT | /v2/api/holiday/{plantId} |
ππ | Set/update holiday mode |
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /v2/api/energy-manager-pv-smart/available/{plantId} |
ππ | PV smart availability |
| GET | /v2/api/energy-manager-pv-smart/live/{plantId} |
ππ | PV live data |
| GET | /v2/api/energy-manager-pv-smart/chart-data/{plantId} |
ππ | PV chart data |
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /v1/plant-registrations |
π | Register a new plant |
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /v1/news/latest |
π | Latest news (requires Hovalconnect-Frontend-App-Version header) |
The full OpenAPI 3.1 specification is available at:
GET /v3/api-docs
(~450KB JSON, requires Bearer auth)
The plant access token response includes a feature map indicating what operations are available:
| Code | Feature |
|---|---|
| OP | Own Plant |
| PA | Plant Access |
| PE | Programs Edit |
| GSV | Gateway Software View |
| GSU | Gateway Software Update |
| GSD | Gateway Software Downgrade |
| SP | Share Plant |
| DM | Diagnosis Mode |
| PT | Parameter Tree |
| PVV | Plant Visualisation View |
| PVE | Plant Visualisation Edit |
| MUV | Meters Unassigned View |
| MUNE | Meters Unassigned Name Edit |
| EAS | Energy Accounting Share |
| PAE | Plant Address Edit |
| PNE | Plant Name Edit |
| PAV | Plant Address View |
| NVR | Notification View Receivers |
| NMR | Notification Manage Receivers |
- Token lifetime: 30 min (id_token), ~15 min (plant access token)
- No documented rate limits, but be respectful
- The API may lock out accounts after repeated failed auth attempts
- Some endpoints are partner/business-only (403 for regular users)
business/endpoints may require elevated access roles
This documentation was created through API analysis and is not officially supported by Hoval. The API may change at any time. Use responsibly and respect Hoval's terms of service.