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.
Thanks! This was a great—I was trying to use the Node Red HA API block, but could not get it to work (it was returning a 404 error). Found your post & built the same functionality with the Change block (to set the JSON fields) and the HTTP block (using it to POST to the API).
LikeLike
Awesome, glad that it worked for you.
LikeLike
Hello, this Post did helped me very much. I had tried to use the the state url but not the service turn_on one.
Now my Python script is working fine.
Thanks!
LikeLike