REST API docs for automations?

i’m developing my own HA web client, part of which includes creating automations.

i can’t find any API docs on the REST endpoint for doing so. inspecting the network requests from the existing automation editor in HASS UI shows that it’s a POST to /api/config/automation/config/<a_generated_id> with a JSON object as the payload.

i can work with that, but is there official documentation? is this api stable?

in fact i’d prefer to create automations via the websocket api, but when i query /api/services, the services available under the automations domain are reload/toggle/trigger/turn_off/turn_on . is there a service call available to create/edit an automation?

1 Like

You mean something like this? I just did a quick Google search.

https://developers.home-assistant.io/docs/en/external_api_rest.html

especially this.

https://developers.home-assistant.io/docs/en/external_api_websocket.html

i’m aware of those docs. what i’m asking for is specific API documentation about the automation domain and its services.

The REST API should be browseable at /api/. I am at work & cannot test right now.

thanks for the reply. hitting http://localhost:8123/api/ only returns an “api is running” message.

Did you find any doc for automations?

I did, let me know when you come online.

please share!

Did you ever find this info. Im looking for the same thing

Hi, friends.

I’ve been able to reverse engineer a little bit of this by reading the frontend code: https://github.com/home-assistant/frontend/blob/fafad302ba5dd8b279ace7eb082a2bb4046c670f/src/panels/config/automation/ha-config-automation.ts

The frontend gets a list of automations by parsing the list of States. You can get the states with the websocket message get_state and finding any states in the automation domain. This gives back some basic information abotu the automations, e.g.:

$ ghastly state list | jq 'map(select(.entity_id | startswith("automation.")).attributes)'
[
  {
    "friendly_name": "Upstairs Heater - Off",
    "id": "5fd2063e021b476b800d42790ae33572",
    "last_triggered": "2020-05-04T03:45:00.024172+00:00"
  },
  {
    "friendly_name": "Growlights On at 6am",
    "id": "4956d98ce52246b395295e76440bd979",
    "last_triggered": "2020-05-19T13:00:00.059517+00:00"
  },
  {
    "friendly_name": "Downstairs Heater - Off",
    "id": "211bc95e4741423b9a52058da6747298",
    "last_triggered": "2020-05-14T18:01:00.056826+00:00"
  },
  {
    "friendly_name": "Downstairs Heater - On",
    "id": "f869704cfd1f497891b4bfed86da3ce7",
    "last_triggered": "2020-05-13T13:29:09.061536+00:00"
  },
  {
    "friendly_name": "Upstairs Heater - On",
    "id": "625933858a54497390306f643e59b4ef",
    "last_triggered": "2020-05-03T20:29:10.850650+00:00"
  },
  {
    "friendly_name": "Bedroom lights at dawn",
    "id": "22650126ff7c46059363912643842fd6",
    "last_triggered": "2020-05-13T13:15:00.055598+00:00"
  },
  {
    "friendly_name": "Growlights Off at 6pm",
    "id": "73b6047662104b3da06bf75fd58b0c8f",
    "last_triggered": "2020-05-19T01:00:00.038803+00:00"
  }
]

Given the id from attributes, the REST URL config/automation/config/[automation-id] can be used to retrieve the details of an automation:

$ ghastly raw config/automation/config/22650126ff7c46059363912643842fd6 | jq
{
  "action": {
    "data": {
      "brightness": 255,
      "entity_id": "light.ge_14294_inwall_smart_dimmer_level",
      "transition": 900
    },
    "service": "light.turn_on"
  },
  "alias": "Bedroom lights at dawn",
  "condition": {
    "condition": "or",
    "conditions": [
      {
        "condition": "state",
        "entity_id": "device_tracker.oneplus7t_2",
        "state": "home"
      },
      {
        "condition": "state",
        "entity_id": "device_tracker.oneplus6tsingle_2",
        "state": "home"
      }
    ]
  },
  "id": "22650126ff7c46059363912643842fd6",
  "trigger": [
    {
      "at": "06:15:00",
      "platform": "time"
    }
  ]
}

This is RESTful, so you can configure an automation by POSTing the same sort of JSON blob back to the same URL config/automation/config/[automation-id].

Similarly, deleting an automation is a RESTful DELETE to that same API.

2 Likes

Hi Patrick, I can confirm this works perfectly for amending an automation when you already know the automation ID.

Thank you.

Could you offer any advice on creating a completely new automation

I know this is years old, but this is the first result on Google.

It seems you can do a post to a random Automation ID and include that in the settings -

In Postman: http://[IP]:8123/api/config/automation/config/[randomID]

Example body:

{
    "id": "[randomID]",
    "alias": "[Name of Automation]",
    "description": "",
    "trigger": [
        {
            "platform": "webhook",
            "webhook_id": "REDACTED"
        }
    ],
    "condition": [],
    "action": [
        {
            "service": "scene.turn_on",
            "target": {
                "entity_id": "scene.office_lights"
            },
            "metadata": {}
        }
    ],
    "mode": "single"
    }

Edit: Just to clarify, [random ID] is a variable and can be whatever you want, such as:

http://homeassistant.local:8123/config/automation/config/thisismyautomationid

1 Like

I have a similar requirement, except that I need to create automations via Ansible. I am getting a “HTTP Error 405: Method Not Allowed” when I do a POST to http://homeassistant.local:8123/config/automation/config/[random ID].

Here is my Ansible YAML, which includes the JSON body exactly as described above.

- name: Generate deterministic 13-character numeric IDs for each hostname and env var name combination
  set_fact:
    "{{ inventory_hostname }}_{{ env_uuid }}_deterministic_id": "{{ '%013d' | format((((inventory_hostname ~ env_uuid) | hash('sha1')) | int(base=16)) % (10**13 - 1)) }}"
  loop: "{{ env_uuids }}"
  loop_control:
    loop_var: env_uuid

- name: Print the deterministic IDs
  debug:
    msg: "The deterministic ID for {{ env_uuid }} on {{ inventory_hostname }} is {{ lookup('vars', inventory_hostname ~ '_' ~ env_uuid ~ '_deterministic_id') }}"
  loop: "{{ env_uuids }}"
  loop_control:
    loop_var: env_uuid

- name: Create or update automations in Home Assistant for each UUID
  uri:
    url: "http://homeassistant.local:8123/config/automation/config/{{ lookup('vars', inventory_hostname ~ '_' ~ env_uuid ~ '_deterministic_id') }}"
    method: POST
    body_format: json
    headers:
      Authorization: "Bearer {{ home_assistant_token }}"
      Content-Type: "application/json"
    body: >
      {
          "id": "{{ lookup('vars', inventory_hostname ~ '_' ~ env_uuid ~ '_deterministic_id') }}",
          "alias": "{{ inventory_hostname }} {{ env_uuid }}",
          "description": "",
          "trigger": [
              {
                  "platform": "webhook",
                  "webhook_id": "{{ lookup('vars', inventory_hostname ~ '_' ~ env_uuid ~ '_uuid') }}"
              }
          ],
          "condition": [],
          "action": [
              {
                  "service": "light.turn_on",
                  "target": {
                      "entity_id": "light.office_smart_light_bulb"
                  },
                  "data": {
                    "color_name": "blue"
                  },
                  "metadata": {}
              }
          ],
          "mode": "single"
          }
    status_code: [200, 201]
    validate_certs: no
  loop: "{{ env_uuids }}"
  loop_control:
    loop_var: env_uuid

What am I doing wrong?

On the original thread topic, I’m assuming the answer here is that the REST API for automations (and other configuration) is intentionally undocumented as its subject to change.

I’d love to see the thinking there documented somehow, so we have a good idea of what the direction is with Home Assistant. It seems that GUI-first is the direction, YAML configurations are on their way out, and configuration APIs desired in this thread are unstable.

The decision on GUI-first integration configuration and YAML deprecation for integrations of devices and services is explored a bit in this Architecture Decision Record (ADR): ADR-0010 Integration configuration.

I am sorry for the really long delay. I did not see the notification for this until now.

I don’t think I was clear in my post, so I will edit it.

[random ID] is not the string in the url, but a placeholder for whatever you put there. So for example: `http://homeassistant.local:8123/config/automation/config/adfasdfasfwaasd

You would want to generate the random ID before hand or manually fill one in.

edit: I am sorry again, I misread your post and it seems you are doing it correctly. I haven’t worked with Ansible much, I can give it a test and get back to this thread. Or if you have squared it away, let us know!

Hello again,

So after some testing, I realized your URL does not have the /api/ in the path:

http://homeassistant.local:8123/config/automation/config/

Should be:

http://homeassistant.local:8123/api/config/automation/config/

I believe that’s it that may be needed for your example. Here is my successful (and simple) playbook for the sake of it:

- name: HA Stuff
  hosts: localhost  # Change this to your target host
  tasks:
    - name: Create HA automation
      uri:
        url: "http://homeassistant.local:8123/api/config/automation/config/ANSIBLETESTAUTOMOTIA"
        method: POST
        body_format: json
        body: >
          {
              "id": "ANSIBLETESTAUTOMOTIA",
              "alias": "ansibletestname",
              "description": "",
              "trigger": [
                  {
                      "platform": "webhook",
                      "webhook_id": "REDACTED"
                  }
              ],
              "condition": [],
              "action": [
                  {
                      "service": "scene.turn_on",
                      "target": {
                          "entity_id": "scene.office_lights"
                      },
                      "metadata": {}
                  }
              ],
              "mode": "single"
          }        
        
        headers:
          Authorization: "Bearer LONGLIVEACCESSTOKEN"
          Content-Type: "application/json"
      register: response
      failed_when: response.status != 200