There are a few methods to communicate with Home Assistant. In this blog I wanted to document my notes on using the REST API.
Getting Started
I found that loading the File Editor Add-on made configuration changes quite easy. To load the File Editor, select the Supervisor item, then Add-on Store:

With the File Editor option you be able to modify your /config/configuration.yaml file. For this you’ll need to add an api: statement. I also added a command line sensor that shows the Raspberry Pi CPU idle time. I did this so that I could see a dynamic analog value:

After I made these changes I restarted my HA application, by the “Configuration” -> “Server Controls”.
Next I needed to create a user token. Select your user and then click on “Create Token” in the Long-Lived Access Tokens section. This token is very long and it only is shown once, so copy and paste it somewhere save.

Access the REST API with CURL
Curl is a command line utility that exists on Linux, Mac OS and Windows. I work in Linux mostly and it’s pre-installed with Ubuntu. If you’re working in Windows you’ll need to install CURL.
Getting started with curl isn’t required and you got straight to programming in your favourite language, however I found that it was usefully testing things out in curl before I did any programming.
The REST API is essentially an HTTP URL with some headers and parameters passed to it. For a full definition see the HA API document. The key items in REST API are:
- Request type – GET or POST (note: there are other types)
- Authorization – this is where the user token is passed
- Data – is used for setting and defining tags
- URL – the Home Assistant URL and the end point (option to view or set)
To check that the HA API is running a curl GET command can used with the endpoint of /api/.
$ curl -X GET -H "Authorization: Bearer eyJ0eXAiO....zLjc" http://192.168.0.103:8123/api/ {"message": "API running."}
The user token is super long so your can use the \ character to break up your command. For example:
curl -X GET \ -H "Authorization: Bearer eyJ0eXAiOiJKV......zLjc" \ http://192.168.0.106:8123/api/states
Read a Specific HA Item
To get a specific HA item you’ll need to know its entity id. This can found by looking at the “Configuration” -> “Entities” page:

For my example I created a sensor called Idle Time, its entity id is: sensor.idle_time.
A curl GET command with the endpoint of /states/sensor.idle_time will return information on this sensor. The full curl command and the results would look like:
$ curl -X GET -H "Authorization: Bearer eyJ0eXAiOiJKV1Q....zLjc" \ http://192.168.0.103:8123/api/states/sensor.idle_time {"entity_id": "sensor.idle_time", "state": "98.45", "attributes": {"unit_of_measurement": "%", "friendly_name": "Idle Time"}, "last_changed": "2020-12-12T17:34:10.472304+00:00", "last_updated": "2020-12-12T17:34:10.472304+00:00", "context": {"id": "351548f602f5a3887ff09f26903712bc", "parent_id": null, "user_id": null}}
Write to a New HA Item
A new or dynamic items can be created and written to remotely using a POST command with the definitions included in the data section. An example to create an entity called myput1 with a value of 88.6 would be:
curl -X POST \
-H "Authorization: Bearer eyJ0eXAiOi....zLjc" \
-H "Content-Type: application/json" \
-d '{"state":"88.6", "attributes": {"unit_of_measurement": "%", "friendly_name": "Remote Input 1"}}' \
http://192.168.0.103:8123/api/states/sensor.myinput1
This new entity is now available to HA and shown on the dashboard.

Write to a Switch
If you have a writeable device such as a switch you can use the REST to remotely control it.
For myself I have a Wemo switch with an entity name of : switch.switch1.
To control the switch the entity id is passed in the data section and the endpoint uses either a turn_on or turn_off parameter.
curl -X POST \ -H "Authorization: Bearer eyJ0eXAiOiJ....zLjc" \ -H "Content-Type: application/json" \ -d '{"entity_id": "switch.switch1"}' \ http://192.168.0.103:8123/api/services/switch/turn_on
Python and the HA API
Python can parse the JSON responses from the reading a sensor value:
from requests import get
import json
url = "http://192.168.0.103:8123/api/states/sensor.idle_time"
token = "eyJ0eXAiOiJK...zLjc"
headers = {
"Authorization": "Bearer " + token,
"content-type": "application/json",
}
response = get(url, headers=headers)
print("Rest API Response\n")
print(response.text)
# Create a json variable
jdata = json.loads(response.text)
print("\nJSON values\n")
for i in jdata:
print(i, jdata[i])
The output will be something like:
Rest API Response {"entity_id": "sensor.idle_time", "state": "98.46", "attributes": {"unit_of_measurement": "%", "friendly_name": "Idle Time"}, "last_changed": "2020-12-12T19:29:10.655530+00:00", "last_updated": "2020-12-12T19:29:10.655530+00:00", "context": {"id": "2509c01cadb9e5b0681fa22d914e7b10", "parent_id": null, "user_id": null}} JSON values entity_id sensor.idle_time state 98.46 attributes {'unit_of_measurement': '%', 'friendly_name': 'Idle Time'} last_changed 2020-12-12T19:29:10.655530+00:00 last_updated 2020-12-12T19:29:10.655530+00:00 context {'id': '2509c01cadb9e5b0681fa22d914e7b10', 'parent_id': None, 'user_id': None}
To write a value to myinput1 in Home Assistant:
from requests import post
import json
url = "http://192.168.0.103:8123/api/states/sensor.myinput1"
token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJkMDI2YjAxY2VkZWU0M2E1OWY1NmI1OTM2OGU1NmI0OSIsImlhdCI6MTYwNzc5Mzc0NCwiZXhwIjoxOTIzMTUzNzQ0fQ.qEKVKdadxNWp249H3s_nmKyzQMIu5WDQkS9hiT-zLjc"
mydata = '{"state":"99.3", "attributes": {"unit_of_measurement": "%", "friendly_name": "Remote Input 1"}}'
headers = {
"Authorization": "Bearer " + token,
"content-type": "application/json",
}
response = post(url, headers=headers,data =mydata)
print("Rest API Response\n")
print(response.text)
# Create a json variable
jdata = json.loads(response.text)
print("\nJSON values\n")
for i in jdata:
print(i, jdata[i])
The output will look something like:
Rest API Response {"entity_id": "sensor.myinput1", "state": "99.3", "attributes": {"unit_of_measurement": "%", "friendly_name": "Remote Input 1"}, "last_changed": "2020-12-12T20:40:05.797256+00:00", "last_updated": "2020-12-12T20:40:05.797256+00:00", "context": {"id": "31b422d02db41cde94470ebae7fac48c", "parent_id": null, "user_id": "1392a10c7bbb4cf0891a7f8a351740c7"}} JSON values entity_id sensor.myinput1 state 99.3 attributes {'unit_of_measurement': '%', 'friendly_name': 'Remote Input 1'} last_changed 2020-12-12T20:40:05.797256+00:00 last_updated 2020-12-12T20:40:05.797256+00:00 context {'id': '31b422d02db41cde94470ebae7fac48c', 'parent_id': None, 'user_id': '1392a10c7bbb4cf0891a7f8a351740c7'}
Final Comments
A REST API interface allows foreign devices such as PCs, Raspberry Pi and Arduino module to be used as remote I/O devices.
There are REST client HTTP libraries that are available for the Arduino, however it might be cleaner to implement an MQTT interface instead.