Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Control your smart home via the Home Assistant REST API with safety enforcement, inventory
.claude/skills/ha-ultimate/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | — | — |
| case-01 | ✗→✓ | ▲ Improved | — | — |
| case-11 | ✗→✓ | ▲ Improved | — | — |
| case-03 | ✗→✓ | ▲ Improved | — | — |
| case-19 | ✗→✓ | ▲ Improved | — | — |
Control your smart home via the Home Assistant REST API with safety enforcement, inventory awareness, and full domain coverage.
bashexport HA_URL="http://your-ha-instance:8123" export HA_TOKEN="your-long-lived-access-token"
Or create a .env file in the skill directory (auto-loaded by ha.sh):
envHA_URL=http://192.168.1.100:8123 HA_TOKEN=eyJ...your-token...
The CLI wrapper also checks $HOME/.config/homeassistant/config.json as a fallback (JSON with url and token keys). Protect this file with restrictive permissions (chmod 600) since it may contain your token.
bashcurl -s -H "Authorization: Bearer $HA_TOKEN" "$HA_URL/api/" | jq
Or with the CLI wrapper:
bashscripts/ha.sh info
Note: Node.js is an optional dependency, only needed for inventory.js. If Node.js is not available, ha.sh inventory falls back to a curl+jq listing.
bashnode scripts/inventory.js
This generates ENTITIES.md with all entities organized by domain, including name, area, and current state. Read ENTITIES.md before acting on devices to know what is available.
If running inside Docker:
http://192.168.1.100:8123http://homeassistant.ts.net:8123homeassistant.local often doesn't resolvehttps://xxxxx.ui.nabu.casa (requires subscription)This skill implements a layered safety system to prevent accidental actions on security-critical devices.
Always confirm with the user before performing these actions:
cover.* with device_class: garage)Never act on security-sensitive devices without explicit user confirmation.
For critical domains (locks, alarm panels, garage doors, covers controlling physical access), follow this workflow before executing any command:
Important: The agent (not the script) is responsible for enforcing this confirmation flow. The CLI wrapper (scripts/ha.sh) checks blocked_entities.json as a hard block, but interactive confirmation must be handled at the agent conversation level before invoking any command on critical domains.
Users can permanently block entities by listing them in a blocked_entities.json file:
json{ "blocked": ["switch.main_breaker", "lock.front_door"], "notes": "Main breaker should never be automated. Front door is manual-only." }
Blocked entities cannot be controlled under any circumstance, even with user confirmation. Check this file before executing any action if it exists.
The scripts/ha.sh CLI provides easy access to all HA functions:
bash# Test connection scripts/ha.sh info # List entities scripts/ha.sh list all # all entities scripts/ha.sh list light # just lights scripts/ha.sh list switch # just switches # Search entities scripts/ha.sh search kitchen # find entities by name # Get/set state scripts/ha.sh state light.living_room scripts/ha.sh full light.living_room # full details with attributes scripts/ha.sh on light.living_room scripts/ha.sh on light.living_room 200 # with brightness (0-255) scripts/ha.sh off light.living_room scripts/ha.sh toggle switch.fan # Scenes & scripts scripts/ha.sh scene movie_night scripts/ha.sh script goodnight # Climate scripts/ha.sh climate climate.thermostat 22 # Dashboard (quick status of everything) scripts/ha.sh dashboard # Call any service scripts/ha.sh call light turn_on '{"entity_id":"light.room","brightness":200}' # Areas scripts/ha.sh areas
bashcurl -s "$HA_URL/api/states" -H "Authorization: Bearer $HA_TOKEN" \ | jq -r '.[].entity_id' | sort
bash# Lights curl -s "$HA_URL/api/states" -H "Authorization: Bearer $HA_TOKEN" \ | jq -r '.[] | select(.entity_id | startswith("light.")) | "\(.entity_id): \(.state)"' # Sensors (with units) curl -s "$HA_URL/api/states" -H "Authorization: Bearer $HA_TOKEN" \ | jq -r '.[] | select(.entity_id | startswith("sensor.")) | "\(.entity_id): \(.state) \(.attributes.unit_of_measurement // "")"'
Replace the domain prefix (switch., light., sensor., etc.) to discover entities in any domain.
bashcurl -s "$HA_URL/api/states/ENTITY_ID" -H "Authorization: Bearer $HA_TOKEN"
Use the template API to query areas, floors, and labels.
bash# List all areas curl -s -X POST "$HA_URL/api/template" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"template": "{{ areas() }}"}' # Entities in a specific area curl -s -X POST "$HA_URL/api/template" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"template": "{{ area_entities(\"kitchen\") }}"}' # Find which area an entity belongs to curl -s -X POST "$HA_URL/api/template" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"template": "{{ area_name(\"light.kitchen\") }}"}' # List all floors and their areas curl -s -X POST "$HA_URL/api/template" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"template": "{% for floor in floors() %}{{ floor }}: {{ floor_areas(floor) }}\n{% endfor %}"}'
bash# Turn on curl -s -X POST "$HA_URL/api/services/switch/turn_on" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "switch.office_lamp"}' # Turn off curl -s -X POST "$HA_URL/api/services/switch/turn_off" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "switch.office_lamp"}' # Toggle curl -s -X POST "$HA_URL/api/services/switch/toggle" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "switch.office_lamp"}'
bash# Turn on with brightness (percentage) curl -s -X POST "$HA_URL/api/services/light/turn_on" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "light.living_room", "brightness_pct": 80}' # Turn on with color (RGB) curl -s -X POST "$HA_URL/api/services/light/turn_on" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "light.living_room", "rgb_color": [255, 150, 50]}' # Turn on with color temperature (mireds, 153-500) curl -s -X POST "$HA_URL/api/services/light/turn_on" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "light.living_room", "color_temp": 300}' # Turn on with transition (seconds) curl -s -X POST "$HA_URL/api/services/light/turn_on" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "light.living_room", "brightness_pct": 100, "transition": 3}' # Turn off curl -s -X POST "$HA_URL/api/services/light/turn_off" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "light.living_room"}'
bashcurl -s -X POST "$HA_URL/api/services/scene/turn_on" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "scene.movie_time"}'
bash# List all scripts curl -s "$HA_URL/api/states" -H "Authorization: Bearer $HA_TOKEN" \ | jq -r '.[] | select(.entity_id | startswith("script.")) | "\(.entity_id): \(.state)"' # Run a script curl -s -X POST "$HA_URL/api/services/script/turn_on" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "script.bedtime_routine"}' # Run a script with variables curl -s -X POST "$HA_URL/api/services/script/bedtime_routine" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"variables": {"brightness": 20, "delay_minutes": 5}}'
bash# List all automations curl -s "$HA_URL/api/states" -H "Authorization: Bearer $HA_TOKEN" \ | jq -r '.[] | select(.entity_id | startswith("automation.")) | "\(.entity_id): \(.state)"' # Trigger an automation curl -s -X POST "$HA_URL/api/services/automation/trigger" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "automation.morning_routine"}' # Enable / Disable automation curl -s -X POST "$HA_URL/api/services/automation/turn_on" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "automation.morning_routine"}' curl -s -X POST "$HA_URL/api/services/automation/turn_off" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "automation.morning_routine"}'
bash# Get thermostat state curl -s "$HA_URL/api/states/climate.thermostat" -H "Authorization: Bearer $HA_TOKEN" \ | jq '{state: .state, current_temp: .attributes.current_temperature, target_temp: .attributes.temperature}' # Set temperature curl -s -X POST "$HA_URL/api/services/climate/set_temperature" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "climate.thermostat", "temperature": 22}' # Set HVAC mode (heat, cool, auto, off) curl -s -X POST "$HA_URL/api/services/climate/set_hvac_mode" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "climate.thermostat", "hvac_mode": "auto"}' # Set preset mode (away, home, sleep, etc.) curl -s -X POST "$HA_URL/api/services/climate/set_preset_mode" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "climate.thermostat", "preset_mode": "away"}'
Safety: Confirm with the user before opening/closing garage doors or gates.
bash# Open curl -s -X POST "$HA_URL/api/services/cover/open_cover" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "cover.garage_door"}' # Close curl -s -X POST "$HA_URL/api/services/cover/close_cover" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "cover.garage_door"}' # Set position (0 = closed, 100 = open) curl -s -X POST "$HA_URL/api/services/cover/set_cover_position" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "cover.blinds", "position": 50}' # Stop curl -s -X POST "$HA_URL/api/services/cover/stop_cover" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "cover.blinds"}'
Safety: Always confirm with the user before locking/unlocking.
bash# Lock curl -s -X POST "$HA_URL/api/services/lock/lock" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "lock.front_door"}' # Unlock curl -s -X POST "$HA_URL/api/services/lock/unlock" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "lock.front_door"}'
bash# Turn on with speed percentage curl -s -X POST "$HA_URL/api/services/fan/turn_on" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "fan.bedroom", "percentage": 50}' # Turn off curl -s -X POST "$HA_URL/api/services/fan/turn_off" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "fan.bedroom"}'
bash# Play/pause curl -s -X POST "$HA_URL/api/services/media_player/media_play_pause" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "media_player.living_room_tv"}' # Set volume (0.0 to 1.0) curl -s -X POST "$HA_URL/api/services/media_player/volume_set" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "media_player.living_room_tv", "volume_level": 0.5}' # Play media curl -s -X POST "$HA_URL/api/services/media_player/play_media" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "media_player.tv", "media_content_id": "https://example.com/stream", "media_content_type": "music"}'
bash# Start cleaning curl -s -X POST "$HA_URL/api/services/vacuum/start" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "vacuum.robot"}' # Return to dock curl -s -X POST "$HA_URL/api/services/vacuum/return_to_base" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "vacuum.robot"}'
Safety: Always confirm with the user before arming/disarming.
bash# Arm (home mode) curl -s -X POST "$HA_URL/api/services/alarm_control_panel/alarm_arm_home" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "alarm_control_panel.home"}' # Arm (away mode) curl -s -X POST "$HA_URL/api/services/alarm_control_panel/alarm_arm_away" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "alarm_control_panel.home"}' # Disarm (requires code if configured) curl -s -X POST "$HA_URL/api/services/alarm_control_panel/alarm_disarm" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "alarm_control_panel.home", "code": "1234"}'
bash# List available notification targets curl -s "$HA_URL/api/services" -H "Authorization: Bearer $HA_TOKEN" \ | jq -r '.[] | select(.domain == "notify") | .services | keys[]' | sort # Send a notification to a mobile device curl -s -X POST "$HA_URL/api/services/notify/mobile_app_phone" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"message": "Front door opened", "title": "Home Alert"}' # Send to all devices (default notify service) curl -s -X POST "$HA_URL/api/services/notify/notify" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"message": "System alert", "title": "Home Assistant"}'
Replace mobile_app_phone with the actual service name from the list command.
bash# Who is home? curl -s "$HA_URL/api/states" -H "Authorization: Bearer $HA_TOKEN" \ | jq -r '.[] | select(.entity_id | startswith("person.")) | "\(.attributes.friendly_name // .entity_id): \(.state)"' # Device tracker locations curl -s "$HA_URL/api/states" -H "Authorization: Bearer $HA_TOKEN" \ | jq -r '.[] | select(.entity_id | startswith("device_tracker.")) | "\(.entity_id): \(.state)"'
States: home, not_home, or a zone name.
bash# Current weather curl -s "$HA_URL/api/states/weather.home" -H "Authorization: Bearer $HA_TOKEN" \ | jq '{state: .state, temperature: .attributes.temperature, humidity: .attributes.humidity, wind_speed: .attributes.wind_speed}' # Get forecast (daily) curl -s -X POST "$HA_URL/api/services/weather/get_forecasts" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "weather.home", "type": "daily"}' # Get forecast (hourly) curl -s -X POST "$HA_URL/api/services/weather/get_forecasts" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "weather.home", "type": "hourly"}'
bash# Toggle an input boolean curl -s -X POST "$HA_URL/api/services/input_boolean/toggle" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "input_boolean.guest_mode"}' # Set input number curl -s -X POST "$HA_URL/api/services/input_number/set_value" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "input_number.target_temperature", "value": 72}' # Set input select curl -s -X POST "$HA_URL/api/services/input_select/select_option" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "input_select.house_mode", "option": "Away"}' # Set input text curl -s -X POST "$HA_URL/api/services/input_text/set_value" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "input_text.welcome_message", "value": "Welcome home!"}' # Set input datetime curl -s -X POST "$HA_URL/api/services/input_datetime/set_datetime" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "input_datetime.alarm_time", "time": "07:30:00"}'
bash# List all calendars curl -s "$HA_URL/api/calendars" -H "Authorization: Bearer $HA_TOKEN" \ | jq -r '.[].entity_id' # Get upcoming events (next 7 days) START=$(date -u +%Y-%m-%dT%H:%M:%S.000Z) END=$(date -u -d "+7 days" +%Y-%m-%dT%H:%M:%S.000Z 2>/dev/null || date -u -v+7d +%Y-%m-%dT%H:%M:%S.000Z) curl -s "$HA_URL/api/calendars/calendar.personal?start=$START&end=$END" \ -H "Authorization: Bearer $HA_TOKEN" \ | jq '[.[] | {summary: .summary, start: .start.dateTime, end: .end.dateTime}]'
bashcurl -s -X POST "$HA_URL/api/services/tts/speak" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "tts.google_en", "media_player_entity_id": "media_player.living_room_speaker", "message": "Dinner is ready"}'
Replace tts.google_en with your TTS entity and the media player with the target speaker.
The general pattern for any HA service:
bashcurl -s -X POST "$HA_URL/api/services/{domain}/{service}" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": "domain.entity_name", ...}'
Control multiple entities in one call by passing an array of entity IDs:
bashcurl -s -X POST "$HA_URL/api/services/light/turn_off" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"entity_id": ["light.living_room", "light.kitchen", "light.bedroom"]}'
The /api/template endpoint evaluates Jinja2 templates server-side. Useful for computed queries that go beyond simple state reads.
bashcurl -s -X POST "$HA_URL/api/template" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"template": "TEMPLATE_STRING"}'
bash# Count entities by domain curl -s -X POST "$HA_URL/api/template" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"template": "{{ states.light | list | count }} lights"}' # List all entities that are "on" curl -s -X POST "$HA_URL/api/template" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"template": "{{ states | selectattr(\"state\", \"eq\", \"on\") | map(attribute=\"entity_id\") | list }}"}' # Entities in an area filtered by domain curl -s -X POST "$HA_URL/api/template" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"template": "{{ area_entities(\"kitchen\") | select(\"match\", \"light.\") | list }}"}'
Available template functions: states(), is_state(), state_attr(), areas(), area_entities(), area_name(), floors(), floor_areas(), labels(), label_entities(), devices(), device_entities(), now(), relative_time().
bash# Last 24 hours for a specific entity curl -s "$HA_URL/api/history/period?filter_entity_id=sensor.temperature" \ -H "Authorization: Bearer $HA_TOKEN" \ | jq '.[0] | [.[] | {state: .state, last_changed: .last_changed}]' # Specific time range (ISO 8601) curl -s "$HA_URL/api/history/period/2025-01-15T00:00:00Z?end_time=2025-01-15T23:59:59Z&filter_entity_id=sensor.temperature" \ -H "Authorization: Bearer $HA_TOKEN" \ | jq '.[0]'
bash# Recent logbook entries curl -s "$HA_URL/api/logbook" -H "Authorization: Bearer $HA_TOKEN" \ | jq '.[:10]' # Logbook for a specific entity curl -s "$HA_URL/api/logbook?entity=light.living_room" \ -H "Authorization: Bearer $HA_TOKEN" \ | jq '.[:10] | [.[] | {name: .name, message: .message, when: .when}]'
Quick status of all active devices:
bash# All lights that are on curl -s "$HA_URL/api/states" -H "Authorization: Bearer $HA_TOKEN" \ | jq -r '.[] | select(.entity_id | startswith("light.")) | select(.state == "on") | .entity_id' # All open doors/windows (binary sensors) curl -s "$HA_URL/api/states" -H "Authorization: Bearer $HA_TOKEN" \ | jq -r '.[] | select(.entity_id | startswith("binary_sensor.")) | select(.state == "on") | select(.attributes.device_class == "door" or .attributes.device_class == "window") | .entity_id' # Temperature sensors curl -s "$HA_URL/api/states" -H "Authorization: Bearer $HA_TOKEN" \ | jq -r '.[] | select(.entity_id | startswith("sensor.")) | select(.attributes.device_class == "temperature") | "\(.attributes.friendly_name // .entity_id): \(.state)\(.attributes.unit_of_measurement // "")"' # Climate summary curl -s "$HA_URL/api/states" -H "Authorization: Bearer $HA_TOKEN" \ | jq -r '.[] | select(.entity_id | startswith("climate.")) | "\(.attributes.friendly_name // .entity_id): \(.state), current: \(.attributes.current_temperature)°, target: \(.attributes.temperature)°"' # Lock status curl -s "$HA_URL/api/states" -H "Authorization: Bearer $HA_TOKEN" \ | jq -r '.[] | select(.entity_id | startswith("lock.")) | "\(.attributes.friendly_name // .entity_id): \(.state)"' # Who is home curl -s "$HA_URL/api/states" -H "Authorization: Bearer $HA_TOKEN" \ | jq -r '.[] | select(.entity_id | startswith("person.")) | "\(.attributes.friendly_name // .entity_id): \(.state)"'
To receive events from Home Assistant automations:
yaml# configuration.yaml rest_command: notify_agent: url: "https://your-agent-url/webhook/home-assistant" method: POST headers: Authorization: "Bearer {{ webhook_secret }}" Content-Type: "application/json" payload: '{"event": "{{ event }}", "area": "{{ area }}", "entity": "{{ entity }}"}'
yaml# automations.yaml - alias: "Notify agent on motion" trigger: - platform: state entity_id: binary_sensor.motion_hallway to: "on" action: - service: rest_command.notify_agent data: event: motion_detected area: hallway entity: binary_sensor.motion_hallway
The agent receives the webhook POST and can notify the user or take action based on the event type and data.
For complete webhook setup, see references/webhooks.md.
bashcurl -s -o /dev/null -w "%{http_code}" "$HA_URL/api/" \ -H "Authorization: Bearer $HA_TOKEN" # Expect: 200
bashHTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \ "$HA_URL/api/states/light.nonexistent" \ -H "Authorization: Bearer $HA_TOKEN") # 200 = exists, 404 = not found
| Code | Meaning | |------|---------| | 200 | Success | | 400 | Bad request (malformed JSON or invalid service data) | | 401 | Unauthorized (bad or missing token) | | 404 | Entity or endpoint not found | | 405 | Method not allowed (wrong HTTP method) | | 503 | Home Assistant is starting up or unavailable |
Service calls return an array of state objects for affected entities:
json[{"entity_id": "light.living_room", "state": "on", "attributes": {...}, "last_changed": "..."}]
[] (empty array)/api/states/...): returns a single state object{"message": "..."} with an HTTP error codeFor more troubleshooting, see references/troubleshooting.md.
| Domain | Examples | |--------|----------| | switch.* | Smart plugs, generic switches | | light.* | Lights (Hue, LIFX, etc.) | | scene.* | Pre-configured scenes | | script.* | Reusable action sequences | | automation.* | Automations | | climate.* | Thermostats, AC units | | cover.* | Blinds, garage doors, gates | | lock.* | Smart locks | | fan.* | Fans, ventilation | | media_player.* | TVs, speakers, streaming devices | | vacuum.* | Robot vacuums | | alarm_control_panel.* | Security systems | | notify.* | Notification targets | | person.* | People / presence tracking | | device_tracker.* | Device locations | | weather.* | Weather conditions and forecasts | | calendar.* | Calendar events | | tts.* | Text-to-speech engines | | sensor.* | Temperature, humidity, power, etc. | | binary_sensor.* | Motion, door/window, presence | | input_boolean.* | Virtual toggles | | input_number.* | Numeric sliders | | input_select.* | Dropdown selectors | | input_text.* | Text inputs | | input_datetime.* | Date/time inputs |
scripts/inventory.js to generate a full entity map before first useblocked_entities.json if it exists before acting on any entity| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 21 counted toward the lift figure. The other 1 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +23 percentage points is the difference between those two pass rates over the 21 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.