HomeAssistantApiClient (HomeAssistantApiClient v0.1.0)
View SourceClient for the Home Assistant home automation platform.
Provides functions to query states, activate services, modify entities, validate configurations, and evaluate templates.
entry_point_get/1 and entry_point_post/2 are the low-level entry points to the API
(GET and POST respectively); every other function in this module is built on top of them.
GET functions
get_config/0- retrieves the.yamlconfiguration.get_logbook/1- retrieves the log before the given date, in"YYYY-MM-DDThh:mm:ssTZD"format. If no date is provided, returns the logs from the current day.get_service_domains/0- returns the domain types.get_service_domain/1- given a specific domain, returns the full service.get_entities/0- returns the names of all entities.get_entity/1- returns the state of the entity with the given name.get_entities_by_type/1- returns all the entities of a specific type.get_entity_types/0- returns the types of entities there are.
POST functions (state changes)
set_entity_state/2 changes the state of an entity directly:
{:ok, _element} = HomeAssistantApiClient.set_entity_state({:input_boolean, "luz_cuarto_gabriel_principal"}, false)set_service/2 and set_service/3 call a service for a given domain, optionally with an
extra argument such as a value or option:
{:ok, _element} = HomeAssistantApiClient.set_service({:input_number, "temperatura_simulada"}, :set_value, 20)template_host/1 evaluates a Home Assistant template:
{:ok, _value} = HomeAssistantApiClient.template_host("{{ states('sensor.sensor_temperatura_mock') }}")check_config/0 checks the configuration to ensure everything is correct.
intent/2 triggers a semantic intent in Home Assistant, simulating a voice query or virtual
assistant action (e.g. HassTurnOn, HassGetState), with the necessary data so Home Assistant
interprets and responds as if it were a conversational interaction:
{:ok, _map} = HomeAssistantApiClient.intent("HassGetState", %{"name" => "sensor.sensor_temperatura_mock"})Domains
A domain identifies the type of entity or service being addressed (e.g. :light,
:input_boolean, :alarm_control_panel). Throughout this module's public API, a domain is
always an atom — that is what you pass in as an argument, and what functions such as
get_entities/0 or get_service_domains/0 return.
Home Assistant's REST API, however, works with domains as strings, since entity ids on the
wire look like "light.salon" and JSON responses list domains as "light". This module
converts between the two representations at its boundary with the HTTP layer:
- Outgoing requests: the atom is turned into a string with
Atom.to_string/1when building the entity id or service path (e.g."#{Atom.to_string(domain)}.#{entity_id}"inset_entity_state/2, or"services/#{domain}/..."inset_service/2). - Incoming responses:
get_service_domains/0reads each domain as a string from the decoded JSON body (item["domain"]) and converts it back to an atom withString.to_atom/1before returning it;get_entities/0does the same when splitting"light.salon"into{:light, "salon"}.
So a domain only ever exists as a string right at the HTTP boundary; everywhere else in this module's public API — every argument and every return value — it is an atom.
Summary
Functions
Builds the base payload for a service call on a domain that requires an extra
argument (e.g. :weather, :mqtt, :input_text), merging in any overrides.
Builds the base payload for a service call on a domain that does not require extra
arguments (e.g. :light, :switch, :automation), merging in any overrides.
Triggers a check to the configuration.yaml file of home assistant returning a map with the errors, warnings that the system could have.
It delets the entity with the name provided as the input.
This function returns the response from GET requests pointing to the path ending with the input endpoint. The response format is the same as for entry_point_post.
This function sends a POST request to the Home Assistant instance specified in the configuration.
Returns the complete configuration of the Home Assistant instance.
Returns a map with all of its entity names
This function returns a list of {type, name} of entities of the type that you specify. iex> {:ok, _} = HomeAssistantApiClient.get_entities_by_type(:light)
Returns the state for all of the entity types except for :input_select in which case it returns state and attributes.
Returns the state and available options of an :input_select entity.
Returns the logbook entries, if a date is give, the format should be "YYYY-MM-DDThh:mm:ssTZD", if no date is provided, the logs will be from the current day. iex> HomeAssistantApiClient.get_logbook("")
Returns an specific domain with all his data.
Returns the service domains in a map, and adds a key to each so that they can be easily accessed later. iex> {:ok, _element} = HomeAssistantApiClient.get_service_domains()
Triggers a semantic intent in Home Assistant, simulating a voice query or virtual assistant action.
For the function: set_entity_state({domain, entity_id}, state) The input is the domain, using the type atom, the entity name specified as an String.t() and the state, note that the state is specified in a type check which one to use for the entity type.
In this function the value of a given service can be changed. The domain type is specified in the service what is being done, and within the change the entity and the value of the change are specified.
Renders a Home Assistant template against the current state of the instance.
Functions
Builds the base payload for a service call on a domain that requires an extra
argument (e.g. :weather, :mqtt, :input_text), merging in any overrides.
iex> HomeAssistantApiClient.build_payload_services_with(:input_text, %{"value" => "hola"})
%{"entity_id" => "input_text.default", "value" => "hola"}
Builds the base payload for a service call on a domain that does not require extra
arguments (e.g. :light, :switch, :automation), merging in any overrides.
iex> HomeAssistantApiClient.build_payload_services_without(:light, %{"entity_id" => "light.salon"})
%{"entity_id" => "light.salon"}
Triggers a check to the configuration.yaml file of home assistant returning a map with the errors, warnings that the system could have.
Also it returns the overall status of the instance.
@spec drop_entity( {HomeAssistantApiClient.Types.entity_type(), HomeAssistantApiClient.Types.entity_id()} ) :: {:ok, any()} | {:error, any()}
It delets the entity with the name provided as the input.
This function returns the response from GET requests pointing to the path ending with the input endpoint. The response format is the same as for entry_point_post.
iex> {:ok, _} = HomeAssistantApiClient.entry_point_get("config")
This function sends a POST request to the Home Assistant instance specified in the configuration.
Input requires the path to the endpoint and a payload specifying the body to be sent.
Returns a tuple {:ok, response} if the request is successful, where response is the decoded body of the response.
If an error occurs, the function returns {:error, error}, where the variable error contains the details of the error.
iex> {:ok, _} = HomeAssistantApiClient.entry_point_post("intent/handle", %{"name" => "HassGetState", "data" => %{"name" => "sensor.sensor_temperatura_mock"}})
Returns the complete configuration of the Home Assistant instance.
Example
iex> {:ok, _} = HomeAssistantApiClient.get_config()
@spec get_entities() :: {:ok, [ {HomeAssistantApiClient.Types.entity_type(), HomeAssistantApiClient.Types.entity_id()} ]} | {:error, String.t()}
Returns a map with all of its entity names
iex> {:ok, _names} = HomeAssistantApiClient.get_entities()
@spec get_entities_by_type(HomeAssistantApiClient.Types.entity_type()) :: {:ok, [ {HomeAssistantApiClient.Types.entity_type(), HomeAssistantApiClient.Types.entity_id()} ]} | {:error, map()}
This function returns a list of {type, name} of entities of the type that you specify. iex> {:ok, _} = HomeAssistantApiClient.get_entities_by_type(:light)
@spec get_entity({:alarm_control_panel, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, HomeAssistantApiClient.Types.alarm_control_panel_state()} | {:error, String.t()}
@spec get_entity({:automation, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, HomeAssistantApiClient.Types.automation_state()} | {:error, String.t()}
@spec get_entity({:binary_sensor, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, HomeAssistantApiClient.Types.binary_sensor_state()} | {:error, String.t()}
@spec get_entity({:conversation, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, atom()} | {:error, String.t()}
@spec get_entity({:event, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, atom()} | {:error, String.t()}
@spec get_entity({:input_boolean, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, HomeAssistantApiClient.Types.input_boolean_state()} | {:error, String.t()}
@spec get_entity({:input_number, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, HomeAssistantApiClient.Types.input_number_state()} | {:error, String.t()}
@spec get_entity({:input_select, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, HomeAssistantApiClient.Types.input_select_state()} | {:error, String.t()}
@spec get_entity({:input_text, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, HomeAssistantApiClient.Types.input_text_state()} | {:error, String.t()}
@spec get_entity({:light, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, HomeAssistantApiClient.Types.light_state()} | {:error, String.t()}
@spec get_entity({:person, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, HomeAssistantApiClient.Types.person_state()} | {:error, String.t()}
@spec get_entity({:sensor, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, HomeAssistantApiClient.Types.sensor_state() | String.t()} | {:error, String.t()}
@spec get_entity({:sun, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, HomeAssistantApiClient.Types.sun_state()} | {:error, String.t()}
@spec get_entity({:switch, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, HomeAssistantApiClient.Types.switch_state()} | {:error, String.t()}
@spec get_entity({:timer, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, HomeAssistantApiClient.Types.switch_state()} | {:error, String.t()}
@spec get_entity({:todo, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, HomeAssistantApiClient.Types.todo_state()} | {:error, String.t()}
@spec get_entity({:tts, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, HomeAssistantApiClient.Types.tts_state()} | {:error, String.t()}
@spec get_entity({:weather, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, HomeAssistantApiClient.Types.weather()} | {:error, String.t()}
@spec get_entity({:zone, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, HomeAssistantApiClient.Types.zone_state()} | {:error, String.t()}
Returns the state for all of the entity types except for :input_select in which case it returns state and attributes.
iex> {:ok, [entity | _]} = HomeAssistantApiClient.get_entities()
iex> {:ok, _individual_entity} = HomeAssistantApiClient.get_entity(entity)
@spec get_entity_attributes({:input_select, HomeAssistantApiClient.Types.entity_id()}) :: {:ok, %{ state: HomeAssistantApiClient.Types.input_select_state(), options: [String.t()] }} | {:error, String.t()}
Returns the state and available options of an :input_select entity.
iex> {:ok, %{state: _state, options: _options}} =
...> HomeAssistantApiClient.get_entity_attributes({:input_select, "puerta"})
@spec get_entity_types() :: {:ok, [HomeAssistantApiClient.Types.entity_type()]} | {:error, String.t()}
@spec get_entity_types!() :: [HomeAssistantApiClient.Types.entity_type()] | no_return()
Returns the logbook entries, if a date is give, the format should be "YYYY-MM-DDThh:mm:ssTZD", if no date is provided, the logs will be from the current day. iex> HomeAssistantApiClient.get_logbook("")
iex> HomeAssistantApiClient.get_logbook("2025-11-03")
Returns an specific domain with all his data.
iex> {:ok, [domain | _]} = HomeAssistantApiClient.get_service_domains()
iex> {:ok, element} = HomeAssistantApiClient.get_service_domain(domain)
iex> is_map(element)
Returns the service domains in a map, and adds a key to each so that they can be easily accessed later. iex> {:ok, _element} = HomeAssistantApiClient.get_service_domains()
Triggers a semantic intent in Home Assistant, simulating a voice query or virtual assistant action.
Allows executing intents like HassTurnOn, HassGetState, etc., with the necessary data so Home
Assistant interprets and responds as if it were a conversational interaction. The intent
component needs to be enabled in the instance's configuration.yaml file.
iex> {:ok, _map} = HomeAssistantApiClient.intent("HassGetState", %{"name" => "sensor.sensor_temperatura_mock"})
@spec set_entity_state( {:automation, HomeAssistantApiClient.Types.entity_id()}, HomeAssistantApiClient.Types.automation_state() ) :: {:ok, HomeAssistantApiClient.Types.automation_state()} | {:error, String.t()}
@spec set_entity_state( {:input_boolean, HomeAssistantApiClient.Types.entity_id()}, HomeAssistantApiClient.Types.input_boolean_state() ) :: {:ok, HomeAssistantApiClient.Types.input_boolean_state()} | {:error, String.t()}
@spec set_entity_state( {:input_number, HomeAssistantApiClient.Types.entity_id()}, HomeAssistantApiClient.Types.input_number_state() ) :: {:ok, HomeAssistantApiClient.Types.input_number_state()} | {:error, String.t()}
@spec set_entity_state( {:input_text, HomeAssistantApiClient.Types.entity_id()}, HomeAssistantApiClient.Types.input_text_state() ) :: {:ok, HomeAssistantApiClient.Types.input_text_state()} | {:error, String.t()}
@spec set_entity_state( {:input_select, HomeAssistantApiClient.Types.entity_id()}, HomeAssistantApiClient.Types.input_select_state() ) :: {:ok, HomeAssistantApiClient.Types.input_select_state()} | {:error, String.t()}
@spec set_entity_state( {:light, HomeAssistantApiClient.Types.entity_id()}, HomeAssistantApiClient.Types.light_state() ) :: {:ok, HomeAssistantApiClient.Types.light_state()} | {:error, String.t()}
@spec set_entity_state( {:switch, HomeAssistantApiClient.Types.entity_id()}, HomeAssistantApiClient.Types.switch_state() ) :: {:ok, HomeAssistantApiClient.Types.switch_state()} | {:error, String.t()}
@spec set_entity_state( {:alarm_control_panel, HomeAssistantApiClient.Types.entity_id()}, HomeAssistantApiClient.Types.alarm_state() ) :: {:ok, HomeAssistantApiClient.Types.alarm_state()} | {:error, String.t()}
For the function: set_entity_state({domain, entity_id}, state) The input is the domain, using the type atom, the entity name specified as an String.t() and the state, note that the state is specified in a type check which one to use for the entity type.
iex> {:ok, _element} = HomeAssistantApiClient.set_entity_state({:input_boolean, "luz_cuarto_gabriel_principal"}, false)
@spec set_service( {:light, HomeAssistantApiClient.Types.entity_ids()}, HomeAssistantApiClient.Types.light_services() ) :: {:ok, any()} | {:error, any()}
@spec set_service( {:switch, HomeAssistantApiClient.Types.entity_ids()}, HomeAssistantApiClient.Types.switch_services() ) :: {:ok, any()} | {:error, any()}
@spec set_service( {:switch, HomeAssistantApiClient.Types.entity_ids()}, HomeAssistantApiClient.Types.switch_services() ) :: {:ok, any()} | {:error, any()}
@spec set_service( {:input_number, HomeAssistantApiClient.Types.entity_ids()}, :increment | :decrement | :reload ) :: {:ok, any()} | {:error, any()}
@spec set_service( :homeassistant, :restart | :stop ) :: {:ok, any()} | {:error, any()}
@spec set_service( {:alarm_control_panel, HomeAssistantApiClient.Types.entity_ids()}, HomeAssistantApiClient.Types.alarm_state() ) :: {:ok, any()} | {:error, any()}
@spec set_service( {:alarm_control_panel, HomeAssistantApiClient.Types.entity_ids()}, :alarm_trigger ) :: {:ok, any()} | {:error, any()}
@spec set_service( {HomeAssistantApiClient.Types.domain_without_extra_values(), String.t() | [String.t()]}, HomeAssistantApiClient.Types.basic_service() ) :: {:ok, [atom()] | atom() | String.t() | [float()] | [String.t()]} | {:error, any()}
In this function the value of a given service can be changed. The domain type is specified in the service what is being done, and within the change the entity and the value of the change are specified.
Domain: It has to be atom. Service: Atom also. change: The change has to be a map so that you can write all the entity_id names and all the values, etc... extra: some services require an extra like set_value where the value needs to be passed, so in this cases there is an extra slot in the funtion forthis change, the user can specify the change itself. Example of change:
iex> {:ok, _element} = HomeAssistantApiClient.set_service({:input_boolean, "aire_central"}, :turn_off) iex> {:ok, _element} = HomeAssistantApiClient.set_service({:input_number, "temperatura_simulada"}, :set_value, 20)
@spec set_service( {:input_select, HomeAssistantApiClient.Types.entity_ids()}, :select_option, String.t() ) :: {:ok, any()} | {:error, any()}
@spec set_service( {:weather, HomeAssistantApiClient.Types.entity_ids()}, HomeAssistantApiClient.Types.weather_services(), String.t() | [String.t()] ) :: {:ok, any()} | {:error, any()}
@spec set_service( {:mqtt, HomeAssistantApiClient.Types.entity_ids()}, :publish, String.t() | boolean() | number() ) :: {:ok, any()} | {:error, any()}
@spec set_service( {:input_number, HomeAssistantApiClient.Types.entity_ids()}, :set_value, number() ) :: {:ok, any()} | {:error, any()}
@spec set_service( {:input_text, HomeAssistantApiClient.Types.entity_ids()}, :set_value, String.t() ) :: {:ok, any()} | {:error, any()}
@spec set_service( {:input_select, HomeAssistantApiClient.Types.entity_ids()}, :set_options, [String.t()] | String.t() ) :: {:ok, any()} | {:error, any()}
@spec set_service( {HomeAssistantApiClient.Types.domain_with_extra_args(), String.t() | [String.t()]}, atom(), String.t() | Integer | map() | number() ) :: {:ok, [atom()] | atom() | [float()] | [String.t()]} | {:error, any()}
@spec set_service( {:alarm_control_panel, HomeAssistantApiClient.Types.entity_ids()}, HomeAssistantApiClient.Types.alarm_password_services(), String.t() ) :: {:ok, any()} | {:error, any()}
@spec set_service( {:light, HomeAssistantApiClient.Types.entity_ids()}, atom(), integer() ) :: {:ok, any()} | {:error, any()}
@spec set_service( {:tts, HomeAssistantApiClient.Types.entity_ids()}, atom(), String.t() ) :: {:ok, any()} | {:error, any()}
@spec set_service({:notify, HomeAssistantApiClient.Types.entity_ids()}, atom(), map()) :: {:ok, any()} | {:error, any()}
Renders a Home Assistant template against the current state of the instance.
iex> {:ok, _value} = HomeAssistantApiClient.template_host("{{ states('sensor.sensor_temperatura_mock') }}")