Skip to content

API Overview

The Api resource lets your apps interact with Home Assistant. It wraps the REST and WebSocket APIs with typed Python interfaces and handles authentication, retries, and type conversion automatically.

flowchart TD
    subgraph app["Your App"]
        APP["self.api"]
    end

    subgraph framework["Api Client"]
        REST["REST<br/><i>get_state()</i>"]
        WS["WebSocket<br/><i>call_service()</i>"]
    end

    subgraph ha["Home Assistant"]
        HA["HA API"]
    end

    APP --> REST & WS
    REST & WS --> HA

    style app fill:#e8f0ff,stroke:#6688cc
    style framework fill:#fff0e8,stroke:#cc8844
    style ha fill:#f0f0f0,stroke:#999
Hold "Ctrl" to enable pan & zoom

Usage

self.api is pre-configured and ready to use in any app:

from hassette import App
from hassette.exceptions import HassetteError


class SunApp(App):
    async def on_initialize(self):
        try:
            state = await self.api.get_state("sun.sun")
            self.logger.info("Sun is %s", state.value)
        except HassetteError as e:
            self.logger.error("HA API error: %s", e)

Error Handling

The API raises typed exceptions for common failures:

Network errors are automatically retried. Catch HassetteError to handle all API failures in one place.

Synchronous Usage

If you are writing a synchronous app, subclass AppSync and override on_initialize_sync instead of on_initialize. Hassette runs your sync method in a thread, where self.api.sync provides blocking versions of all API methods:

Note

self.api.sync is only safe to call from outside the event loop — specifically from AppSync lifecycle methods (on_initialize_sync, on_shutdown_sync). Calling it from inside an async def method will deadlock.

from hassette import AppSync


class SyncApp(AppSync):
    def on_initialize_sync(self):
        # Use .sync to access blocking versions of all async methods
        self.api.sync.turn_on("light.office")

API vs. StateManager

The API fetches state directly from Home Assistant over the network. For reading entity state in most situations, prefer self.states — it provides instant synchronous access from a local cache with no network overhead:

  • self.states.light["kitchen"] — domain-specific typed access, no await
  • self.states.get("light.kitchen") — direct lookup by entity ID, no await

Use self.api when you specifically need guaranteed fresh data directly from Home Assistant.

Next Steps