Docs / Strand / connectors/home-assistant
Home Assistant Connector
Direction: Read/Write | Type: homeassistant
Control smart home devices, read entity states, fire events, and render templates from your Strand workflows via the Home Assistant REST API.
Prerequisites#
Your instance must be reachable from the internet#
This is the first thing to sort out, because most Home Assistant installs are on a home network and Strand runs in the cloud. Strand can only connect to addresses that are publicly reachable, so a URL like http://homeassistant.local:8123 or http://192.168.1.50:8123 will not work — even though it works perfectly from your own browser. Private addresses (10.x, 172.16–31.x, 192.168.x, 127.x) and .local mDNS names are all in that category.
Any of these gives Strand a reachable address:
- Home Assistant Cloud (Nabu Casa) — use your
*.ui.nabu.casaURL. The - A reverse proxy or tunnel — Cloudflare Tunnel, Tailscale Funnel, or your
- A public hostname with HTTPS pointing at your instance.
simplest option, and no ports are opened on your router.
own nginx/Caddy with a real certificate.
Whichever you choose, confirm the URL loads from outside your home network before creating the connector.
Access token#
You need a Long-Lived Access Token from your Home Assistant instance:
- Open your Home Assistant dashboard
- Click your profile icon (bottom-left)
- Scroll to Long-Lived Access Tokens
- Click Create Token, name it (e.g., "Strand"), and copy the token
Tip: Use a dedicated token for your Strand workflows. Tokens can be revoked individually from your HA profile page.
Required Permissions#
The access token inherits the permissions of the user who created it. For full access to all operations, use an administrator account.
| Operation | API Endpoint | Notes |
|---|---|---|
| Call Service | POST /api/services/{domain}/{service} |
Controls devices |
| Fire Event | POST /api/events/{event_type} |
Fires events on the bus |
| Set State | POST /api/states/{entity_id} |
Creates/updates entities |
| Get Entity State | GET /api/states/{entity_id} |
Reads a single entity |
| Get All States | GET /api/states |
Reads all entities |
| Get History | GET /api/history/period/{timestamp} |
Requires history integration |
| Get Services | GET /api/services |
Lists available services |
| Render Template | POST /api/template |
Server-side Jinja2 rendering |
Connector Setup#
Create a Home Assistant connector from the Connectors page.
Configuration Fields#
| Field | Required | Description |
|---|---|---|
| Name | Yes | Friendly name (e.g., "Home HA") |
| Base URL | Yes | Publicly reachable HA URL (e.g., https://your-id.ui.nabu.casa). A private or .local address is rejected — see Prerequisites. |
| Access Token | Yes | Long-lived access token (encrypted at rest) |
| Timeout | No | Request timeout in seconds (default: 30, range: 1-300) |
| Verify SSL | No | Verify SSL certificate (default: true). Disable for self-signed certs. |
Operations#
Call Service#
Control any Home Assistant device by calling a service action.
| Field | Required | Description |
|---|---|---|
| Domain | Yes | Service domain (e.g., light, switch, automation, climate, script) |
| Service | Yes | Service action (e.g., turn_on, turn_off, toggle) |
| Target (JSON) | No | Target entities, devices, or areas as JSON |
| Service Data (JSON) | No | Additional service parameters as JSON (e.g., brightness, color) |
| Return Response | No | Whether to return service response data (default: No) |
Example: Turn on a light at 50% brightness:
- Domain:
light - Service:
turn_on - Target:
{"entity_id": "light.living_room"}
- Service Data:
{"brightness_pct": 50}
Example: Run a script with variables:
- Domain:
script - Service:
{{ payload.script_name }} - Service Data:
{"message": "{{ payload.alert_message }}"}
Fire Event#
Fire a custom event on the Home Assistant event bus to trigger automations.
| Field | Required | Description |
|---|---|---|
| Event Type | Yes | Event type name (e.g., strand_notification) |
| Event Data (JSON) | No | Event data payload as JSON |
Example: Fire a notification event:
- Event Type:
strand_notification - Event Data:
{"message": "{{ payload.alert }}", "severity": "warning", "source": "strand"}
Set State#
Create or update the state and attributes of an entity.
| Field | Required | Description |
|---|---|---|
| Entity ID | Yes | Entity ID to create or update (e.g., sensor.strand_status) |
| State | Yes | New state value |
| Attributes (JSON) | No | Entity attributes as JSON |
Example: Update a custom sensor:
- Entity ID:
sensor.strand_last_run - State:
{{ payload.status }} - Attributes:
{"friendly_name": "Last Strand Run", "timestamp": "{{ payload.timestamp }}"}
Get Entity State#
Get the current state and attributes of a single entity.
| Field | Required | Description |
|---|---|---|
| Entity ID | Yes | Entity ID to retrieve (e.g., sensor.temperature, light.living_room) |
Get All States#
Get the current state of every entity in Home Assistant. No fields required.
Note: This can return a large payload depending on the number of entities in your HA instance. Use Get Entity State for targeted lookups.
Get History#
Get state change history for entities over a time period.
| Field | Required | Description |
|---|---|---|
| Entity ID | No | Filter to a specific entity. If empty, returns all entities (may be large). |
| Start Time | No | ISO 8601 start time (default: 1 day ago) |
| End Time | No | ISO 8601 end time (default: now) |
| Minimal Response | No | Return only state and last_changed for a smaller payload (default: No) |
Example: Get last 24 hours of a sensor:
- Entity ID:
sensor.outdoor_temperature - Minimal Response: Yes
Get Services#
List all available service domains and their actions. No fields required.
Useful for discovering what services are available on your HA instance.
Render Template#
Render a Home Assistant Jinja2 template on the HA server.
| Field | Required | Description |
|---|---|---|
| Template | Yes | Home Assistant Jinja2 template string |
Note: This template is rendered by Home Assistant, not Strand. You can use Strand Jinja templates to inject dynamic values into the HA template.
Example: Get a computed value:
{{ states("sensor.temperature") }} {{ state_attr("sensor.temperature", "unit_of_measurement") }}
Example: Count lights that are on:
{{ states.light | selectattr("state", "eq", "on") | list | count }}
Output#
Call Service Output#
{
"success": true,
"status": "completed",
"data": {
"domain": "light",
"service": "turn_on",
"response": []
},
"service": "homeassistant",
"operation": "call_service"
}
Fire Event Output#
{
"success": true,
"status": "fired",
"data": {
"event_type": "strand_notification",
"message": "Event strand_notification fired."
},
"service": "homeassistant",
"operation": "fire_event"
}
Set State Output#
{
"success": true,
"status": "completed",
"data": {
"entity_id": "sensor.strand_status",
"state": "active",
"attributes": {
"friendly_name": "Strand Status",
"timestamp": "2025-01-15T10:30:00Z"
}
},
"service": "homeassistant",
"operation": "set_state"
}
Get Entity State Output#
{
"success": true,
"status": "completed",
"data": {
"entity_id": "sensor.temperature",
"state": "22.5",
"attributes": {
"unit_of_measurement": "\u00b0C",
"friendly_name": "Temperature Sensor",
"device_class": "temperature"
},
"last_changed": "2025-01-15T10:30:00+00:00",
"last_updated": "2025-01-15T10:30:00+00:00"
},
"service": "homeassistant",
"operation": "get_state"
}
Key fields for subsequent nodes:
{{ steps.node_id.output_payload.data.state }}: Entity state value{{ steps.node_id.output_payload.data.attributes.friendly_name }}: An attribute{{ steps.node_id.output_payload.data.last_changed }}: Last state change time
Get All States Output#
{
"success": true,
"status": "completed",
"data": {
"entities": [ ... ],
"count": 156
},
"service": "homeassistant",
"operation": "get_states"
}
Get History Output#
{
"success": true,
"status": "completed",
"data": {
"history": [
[
{"state": "21.0", "last_changed": "2025-01-15T08:00:00+00:00"},
{"state": "22.5", "last_changed": "2025-01-15T10:30:00+00:00"}
]
],
"entity_id": "sensor.temperature"
},
"service": "homeassistant",
"operation": "get_history"
}
Get Services Output#
{
"success": true,
"status": "completed",
"data": {
"services": [
{"domain": "light", "services": {"turn_on": {}, "turn_off": {}, "toggle": {}}},
{"domain": "switch", "services": {"turn_on": {}, "turn_off": {}, "toggle": {}}}
],
"count": 2
},
"service": "homeassistant",
"operation": "get_services"
}
Render Template Output#
{
"success": true,
"status": "completed",
"data": {
"template": "{{ states('sensor.temperature') }}",
"rendered": "22.5"
},
"service": "homeassistant",
"operation": "render_template"
}
Key field: {{ steps.node_id.output_payload.data.rendered }}: The rendered template result
Errors#
| Error | Meaning |
|---|---|
| Home Assistant authentication failed | Access token is invalid or expired. Regenerate from your HA profile. |
| SSL verification failed | Self-signed certificate detected. Disable "Verify SSL" in connector settings. |
| Failed to connect to Home Assistant | Instance unreachable. Most often the Base URL is a private or .local address, which Strand cannot connect to from the cloud — see Prerequisites. Otherwise check the URL and that the instance is up. |
| API endpoint not found (404) | Entity ID doesn't exist or the URL is wrong. |
| Access to '…' is blocked | The Base URL resolves to a private address. Give Strand a publicly reachable URL — see Prerequisites. |
| Home Assistant API error (400) | Bad request; check entity IDs, service names, or template syntax. |
| Template rendering failed | Invalid Home Assistant Jinja2 template syntax. |
Example Workflow#
- Get Entity State: Check a temperature sensor: entity_id
sensor.outdoor_temperature - Logic node: Evaluate if temperature > 30
- Call Service: Turn on the AC: domain
climate, serviceset_temperature, target{"entity_id": "climate.living_room"}, service data{"temperature": 24} - Fire Event: Log the action: event_type
strand_ac_activated, event data{"temperature": "{{ steps.step1.output_payload.data.state }}"}
Limitations#
- WebSocket API: Only the REST API is supported. WebSocket-based subscriptions and real-time event streams are not available.
- Media: Media upload/download and camera proxy endpoints are not supported.
- Config entries: Managing HA integrations and config entries via API is not supported.
- Large history queries: History queries for many entities over long periods may timeout. Use the entity_id filter and minimal_response option for large datasets.
- Rate limiting: Home Assistant does not enforce rate limits by default, but rapid-fire requests may slow down the instance.
Tendrl