Coding Projects

Home Assistant Automations That Ping Your Phone

A rest_command gives Home Assistant a push notification service in eight lines of YAML, with no companion app running in the background on your phone.

Red and black halftone illustration: a dark hallway at night, a single light switch plate on the wall, a door standing ajar at the far end (TheNotificationApp)

The companion app is the obvious way to get notifications out of Home Assistant, and for most people it is the right answer. It is also a background process on your phone, tied to a device tracker, that needs to stay logged in and stay running.

Sometimes you want the alert without the rest of it. A second phone that is not set up. A partner who wants the freezer alarm but not the whole location-tracking arrangement. Or you would rather one critical automation did not depend on a websocket staying connected.

A rest_command covers that in about eight lines of YAML.

Step 1: Put the key in secrets.yaml

Create an application in TheNotificationApp, call it Home, and copy the app_key. Then put it where it belongs, in secrets.yaml:

tna_app_key: your_app_key_here

Home Assistant configs get shared in forum posts more than almost any other kind of config. Referencing a secret costs nothing and means a screenshot of your automation is not a screenshot of your key.

Step 2: Define the service

In configuration.yaml:

rest_command:
  phone_notify:
    url: https://thenotification.app/api/sendNotification
    method: POST
    headers:
      app_key: !secret tna_app_key
      Content-Type: application/json
    payload: '{"title": "{{ title }}", "body": "{{ body }}"}'
    content_type: application/json

Restart Home Assistant, or reload the REST commands from Developer Tools. You now have a rest_command.phone_notify service that takes a title and a body, callable from anywhere a service can be called.

Test it from Developer Tools, then Actions before wiring it into anything:

action: rest_command.phone_notify
data:
  title: Test from Home Assistant
  body: If this arrives, the rest_command works.

Step 3: Call it from an automation

The freezer is the canonical example, because it is the failure you find out about far too late:

automation:
  - alias: Freezer temperature alert
    trigger:
      - platform: numeric_state
        entity_id: sensor.freezer_temperature
        above: -15
        for:
          minutes: 20
    action:
      - action: rest_command.phone_notify
        data:
          title: Freezer is warming up
          body: >-
            {{ states('sensor.freezer_temperature') }}C for 20 minutes.
            Door may be open.

The for: minutes: 20 is the part that makes this liveable. Without it, opening the freezer door to get ice sends you a notification. Every temperature, humidity or power sensor you alert on wants a duration condition, and leaving it off is the single most common reason people turn their own automations off.

The alerts actually worth having

Home Assistant can notify you about anything, which is precisely why most setups end up notifying about nothing useful. The ones that earn a lock screen buzz share a shape: something is wrong, it will get worse, and you can do something about it.

  • Freezer or fridge above temperature for 20 minutes. The classic. Catches a door left ajar before it costs you a freezer full of food.
  • Water leak sensor triggered. No duration condition on this one. Fire immediately.
  • Washing machine finished. A power sensor dropping below a threshold for five minutes. Low stakes, surprisingly useful.
  • Nobody home and a door is unlocked. Actionable while you are still nearby.
  • Home Assistant restarted unexpectedly. The one that tells you the rest of these have stopped working.

Notice what is not on that list: motion, presence, lights, anything that happens several times a day. Those belong in the log, not on your lock screen.

Adding a tap-through

Extend the payload with an optional link and the notification opens straight into your dashboard:

rest_command:
  phone_notify:
    url: https://thenotification.app/api/sendNotification
    method: POST
    headers:
      app_key: !secret tna_app_key
      Content-Type: application/json
    payload: >-
      {"title": "{{ title }}", "body": "{{ body }}",
       "link": "{{ link | default('https://your-ha-url.example.com') }}"}
    content_type: application/json

Point it at the relevant dashboard view and a leak alert is one tap from the sensor history rather than a hunt through the app. The optional fields are listed in the API reference.

Watch the templating

The payload is a JSON string built by a template, which means a sensor whose state contains a quote or a newline produces invalid JSON and the call fails silently. If any of your values come from something free-form, like a camera event description, pipe it through tojson:

payload: '{"title": {{ title | tojson }}, "body": {{ body | tojson }}}'

Note the quotes move: tojson adds them. This is slightly uglier and considerably harder to break.

The honest part

The free tier is 100 notifications for the lifetime of the account, not per month. For the five automations above that is a year or more, because a well-chosen alert is one that rarely fires. Wire it to a motion sensor and it is gone in a weekend.

Pro is $2.99 a month for 1,000 if you want more headroom. And this delivers to iPhone only, since it rides Apple's push service, so a household on Android wants the companion app or something else entirely.

One more honest note: this is a fire-and-forget POST with no retry. If your Home Assistant box loses its network connection, the notification is simply lost. For critical alerts, that is an argument for having a second path rather than trusting a single one.

Where this fits

Same one-line POST as everything else, pointed at a sensor instead of an exit code. If your home lab includes servers as well as sensors, the same idea for uptime is in getting a server down phone notification.

Grab a key at thenotification.app and give the freezer a voice.