> ## 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.

# Home Assistant

> Client-mode REST API connector for Home Assistant: read and write entity states, call services on switches, lights and climate, fire events, read history and logbook, render templates, read calendars, check the configuration and trigger webhook automations

Technical Preview

## Overview

One client-mode connector, **HomeAssistant**, for the [Home Assistant REST API](https://developers.home-assistant.io/docs/api/rest). Home Assistant is an open-source automation platform that runs on site and connects thousands of device integrations: building HVAC, lighting, energy meters, smart plugs, Zigbee and Z-Wave sensors. Everything it knows about is an **entity** with a **state** (for example `sensor.office_temperature` = `21.4`), and you act on devices by calling **services** (for example `switch.turn_off`).

Use the connector to bridge Home Assistant and the UNS: mirror plant values into Home Assistant dashboards, switch a compressor or the shop-floor lighting from a broker rule, pull building temperature history into a report, or start a Home Assistant automation from an MQTT alarm.

| Event | Request | Notes |
| - | - | - |
| GetApiStatus | `GET /api/` | `{"message": "API running."}`; keep the trailing `/` |
| GetConfig | `GET /api/config` | Version, location, time zone, units, loaded components |
| ListComponents | `GET /api/components` | Loaded integrations |
| ListEventTypes | `GET /api/events` | Event types and listener counts |
| ListServices | `GET /api/services` | Services per domain with their fields |
| ListStates | `GET /api/states` | Every entity state |
| GetState | `GET /api/states/{entity_id}` | `404` for an unknown entity |
| SetState | `POST /api/states/{entity_id}` | `{"state": ..., "attributes": {...}}`; `201` new, `200` existing |
| DeleteState | `DELETE /api/states/{entity_id}` | `{"message": "Entity removed."}` |
| CallService | `POST /api/services/{domain}/{service}` | Service data as the body; returns the changed states |
| CallServiceWithResponse | `POST /api/services/{domain}/{service}?return_response` | Adds `service_response` (for example `calendar.get_events`, `weather.get_forecasts`) |
| FireEvent | `POST /api/events/{event_type}` | Event data as the body |
| GetHistory | `GET /api/history/period?{query}` | Past day; `query` must include `filter_entity_id` |
| GetHistorySince | `GET /api/history/period/{start_time}?{query}` | From `start_time`; add `end_time` to close the window |
| GetLogbook | `GET /api/logbook/{start_time}?{query}` | Optional `entity` and `end_time` |
| RenderTemplate | `POST /api/template` | `{"template": "..."}`; reply is plain text |
| ListCalendars | `GET /api/calendars` | Calendar entities |
| GetCalendarEvents | `GET /api/calendars/{entity_id}?{query}` | `query` = `start=...&end=...` |
| GetErrorLog | `GET /api/error_log` | Plain text; admin token |
| CheckConfig | `POST /api/config/core/check_config` | `{"result": "valid"}` or the errors |
| TriggerWebhook | `POST /api/webhook/{webhook_id}` | No token; starts automations with a webhook trigger |

Replies arrive on `<topic>/response`. The WebSocket API (live event subscriptions) is not covered by this template.

## Authentication

Every event except `TriggerWebhook` sends `Authorization: {authorization}`, so pass the whole header value: `"Bearer <long-lived access token>"`. Create the token in Home Assistant under your user **Profile > Security > Long-lived access tokens**; it is shown only once and is valid for 10 years unless you delete it. Use a dedicated Home Assistant user for the broker so you can revoke it on its own; non-admin users cannot read the error log or check the configuration.

Keep the header value in a broker secret (suggested `HOME_ASSISTANT_AUTHORIZATION`) and map it in with `GET SECRET`. A missing or wrong token returns `401`.

`TriggerWebhook` needs no token: the webhook id is the secret, so pick a long random one. Webhook triggers only accept requests from the local network unless the trigger sets `local_only: false`, so run the broker on the same network as Home Assistant or change that option.

## Basic Syntax

Set `BASE_ADDRESS` to your Home Assistant URL, with no trailing slash: `http://homeassistant.local:8123` or `http://<ip>:8123` with `USE_SSL "false"`, or an HTTPS reverse proxy or Home Assistant Cloud remote URL with `USE_SSL "true"`. The REST API is part of `default_config`; on a minimal configuration add `api:` to `configuration.yaml`.

```lot theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE HomeAssistant WITH TYPE REST_API
    ADD REST_API_CONFIG
        WITH BASE_ADDRESS "http://YOUR_HA_HOST:8123"
        WITH ENABLE_CLIENT "true"
        WITH USE_SSL "false"
        WITH REQUEST_TIMEOUT '30'
        WITH DEFAULT_CONTENT_TYPE "application/json"
        # Smoke: GetApiStatus / GetState (GET), SetState / CallService / FireEvent / RenderTemplate (POST), DeleteState (DELETE), TriggerWebhook (no auth).
    ADD EVENT GetApiStatus
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/api/status"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/api/status/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/api/"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT GetConfig
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/config/get"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/config/get/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/api/config"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT ListComponents
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/component/list"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/component/list/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/api/components"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT ListEventTypes
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/event-type/list"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/event-type/list/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/api/events"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT ListServices
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/service/list"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/service/list/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/api/services"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT ListStates
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/state/list"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/state/list/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/api/states"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT GetState
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/state/get"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/state/get/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/api/states/{value.json.entity_id}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT SetState
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/state/set"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/state/set/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/api/states/{value.json.entity_id}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Content-Type" "application/json"
            ADD "Authorization" "{value.json.authorization}"
        WITH BODY "{value.json.body}"
    ADD EVENT DeleteState
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/state/delete"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/state/delete/response"
        WITH METHOD "DELETE"
        WITH ENDPOINT "/api/states/{value.json.entity_id}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT CallService
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/service/call"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/service/call/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/api/services/{value.json.domain}/{value.json.service}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Content-Type" "application/json"
            ADD "Authorization" "{value.json.authorization}"
        WITH BODY "{value.json.body}"
    ADD EVENT CallServiceWithResponse
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/service/call-with-response"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/service/call-with-response/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/api/services/{value.json.domain}/{value.json.service}?return_response"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Content-Type" "application/json"
            ADD "Authorization" "{value.json.authorization}"
        WITH BODY "{value.json.body}"
    ADD EVENT FireEvent
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/event/fire"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/event/fire/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/api/events/{value.json.event_type}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Content-Type" "application/json"
            ADD "Authorization" "{value.json.authorization}"
        WITH BODY "{value.json.body}"
    ADD EVENT GetHistory
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/history/get"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/history/get/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/api/history/period?{value.json.query}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT GetHistorySince
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/history/get-since"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/history/get-since/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/api/history/period/{value.json.start_time}?{value.json.query}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT GetLogbook
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/logbook/get"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/logbook/get/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/api/logbook/{value.json.start_time}?{value.json.query}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT RenderTemplate
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/template/render"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/template/render/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/api/template"
        WITH HEADERS
            ADD "Accept" "text/plain"
            ADD "Content-Type" "application/json"
            ADD "Authorization" "{value.json.authorization}"
        WITH BODY "{value.json.body}"
    ADD EVENT ListCalendars
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/calendar/list"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/calendar/list/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/api/calendars"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT GetCalendarEvents
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/calendar-event/list"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/calendar-event/list/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/api/calendars/{value.json.entity_id}?{value.json.query}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT GetErrorLog
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/error-log/get"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/error-log/get/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/api/error_log"
        WITH HEADERS
            ADD "Accept" "text/plain"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT CheckConfig
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/config/check"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/config/check/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/api/config/core/check_config"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
        WITH BODY ""
    ADD EVENT TriggerWebhook
        WITH SOURCE_TOPIC "cloud-iot/home-assistant/webhook/trigger"
        WITH DESTINATION_TOPIC "cloud-iot/home-assistant/webhook/trigger/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/api/webhook/{value.json.webhook_id}"
        WITH HEADERS
            ADD "Content-Type" "application/json"
        WITH BODY "{value.json.body}"
```

## MQTT examples

Request bodies go under `body`, so control fields like `authorization` and `entity_id` are not sent to Home Assistant. Events with a `query` field need it; send the pre-encoded query string.

**Mirror a plant value into Home Assistant**: publish to `cloud-iot/home-assistant/state/set`:

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "authorization": "Bearer <long-lived access token>",
  "entity_id": "sensor.porto_line1_temperature",
  "body": {"state": "21.4", "attributes": {"unit_of_measurement": "°C", "device_class": "temperature", "friendly_name": "Line 1 temperature"}}
}
```

Home Assistant answers `201` the first time and `200` afterwards. The state only exists in Home Assistant's state machine (it is not a device and does not survive a restart), which is fine for dashboards and automations fed from the broker.

**Switch a device**: publish to `cloud-iot/home-assistant/service/call`:

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "authorization": "Bearer <long-lived access token>",
  "domain": "switch",
  "service": "turn_off",
  "body": {"entity_id": "switch.compressor_2"}
}
```

The reply lists the states that changed. An unknown domain or service returns `400`. Any service works the same way: `light/turn_on` with `{"entity_id": "light.hall_b", "brightness_pct": 60}`, `climate/set_temperature` with `{"entity_id": "climate.office", "temperature": 21}`, `script/turn_on`, `automation/trigger`, `notify/<target>`.

**Read the next maintenance windows**: publish to `cloud-iot/home-assistant/service/call-with-response`:

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "authorization": "Bearer <long-lived access token>",
  "domain": "calendar",
  "service": "get_events",
  "body": {"entity_id": "calendar.maintenance", "duration": {"days": 7}}
}
```

The reply carries `service_response` with the events. Use this event only for services that return data; others answer `400`.

**Read one entity**: publish `{"authorization": "...", "entity_id": "sensor.office_temperature"}` to `cloud-iot/home-assistant/state/get`.

**Pull the history of a sensor**: publish to `cloud-iot/home-assistant/history/get-since`:

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "authorization": "Bearer <long-lived access token>",
  "start_time": "2026-10-05T00:00:00+01:00",
  "query": "filter_entity_id=sensor.office_temperature,switch.compressor_2&end_time=2026-10-05T12%3A00%3A00%2B01%3A00&minimal_response&no_attributes"
}
```

Use `cloud-iot/home-assistant/history/get` with the same `query` (without `start_time`) for the past day.

**Start a Home Assistant automation**: add a webhook trigger to an automation (Settings > Automations > Trigger > Webhook) and publish to `cloud-iot/home-assistant/webhook/trigger`:

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "webhook_id": "coreflux-line1-alarm-7f3c9a",
  "body": {"machine": "press-07", "state": "fault"}
}
```

The automation reads the body as `trigger.json`, for example `{{ trigger.json.machine }}`. Home Assistant answers `200` with an empty body even when no automation uses the id, so check the automation trace when testing.

**Render a template**: publish `{"authorization": "...", "body": {"template": "{{ states('sensor.office_temperature') }} °C"}}` to `cloud-iot/home-assistant/template/render`; the reply is the rendered text.

## Helper actions

Mirror a line temperature into Home Assistant and switch off a compressor when the broker raises an alarm:

```lot theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ACTION HomeAssistantMirrorLineTemperature
ON TOPIC "porto/line1/temperature" DO
    SET "auth" WITH GET SECRET "HOME_ASSISTANT_AUTHORIZATION"
    SET "temp" WITH PAYLOAD
    PUBLISH TOPIC "cloud-iot/home-assistant/state/set" WITH { "authorization": {auth}, "entity_id": "sensor.porto_line1_temperature", "body": { "state": {temp}, "attributes": { "unit_of_measurement": "°C", "device_class": "temperature", "friendly_name": "Line 1 temperature" } } }

DEFINE ACTION HomeAssistantCompressorOff
ON TOPIC "porto/line1/compressor2/alarm" DO
    SET "auth" WITH GET SECRET "HOME_ASSISTANT_AUTHORIZATION"
    PUBLISH TOPIC "cloud-iot/home-assistant/service/call" WITH { "authorization": {auth}, "domain": "switch", "service": "turn_off", "body": { "entity_id": "switch.compressor_2" } }
```

Restrict who can publish to `cloud-iot/home-assistant/#` with a rule: its payloads carry the token and can switch real equipment.

## Notes

* Errors come back on the response topic: `400` for bad JSON, an unknown domain or service, a missing `filter_entity_id` or a `return_response` mismatch, `401` for a missing or wrong token, `404` for an unknown entity or calendar, and `405` for a wrong method.
* `SetState` changes Home Assistant's view of an entity, not the device. To act on a device, call a service with `CallService`.
* `query` and `end_time` values must be URL-encoded (`:` as `%3A`, `+` as `%2B`). `start_time` in the path can stay as plain ISO 8601, for example `2026-10-05T00:00:00+01:00`.
* History and logbook need the `history` and `logbook` integrations (part of `default_config`), and only cover what the recorder keeps (10 days by default).
* For a live stream of every state change, use Home Assistant's MQTT integration or its WebSocket API instead of polling `ListStates`.

## Related

* [REST API Connectors](/latest/lot-language/routes/rest-api-routes)
* [REST API app templates](/latest/lot-language/routes/rest-api-apps/index)
* [ThingsBoard](/latest/lot-language/routes/rest-api-apps/thingsboard)
* [Eclipse Ditto](/latest/lot-language/routes/rest-api-apps/eclipse-ditto)
* [Eclipse hawkBit](/latest/lot-language/routes/rest-api-apps/eclipse-hawkbit)


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