Home Assistant automation notification notifications on your phone.

Get a push notification from any Home Assistant automation or script, with your own title, message, priority and link, sent through a rest_command.

How it works

Three steps to your first push

STEP 01

Install the recipe

One click in Studio gives you a personal webhook URL.

STEP 02

Paste your URL into Home Assistant

Add it as a webhook for rest_command.

STEP 03

Get a push on your phone

With the text, sound and buttons from the recipe.

Setup

How to set up the Home Assistant rest_command webhook

  1. Click Install in Studio and sign in. The recipe is added to your account and you get a personal webhook URL.
  2. Home Assistant has no outgoing webhooks, so add a rest_command to your configuration.yaml that posts JSON to your webhook URL.https://••••••••/•••••••• your personal URL, shown after install
  3. Restart Home Assistant (or reload YAML) so the rest_command action appears.
  4. Call that action from an automation or script, as shown in the recipe's instructions.
  5. Home Assistant has no outgoing webhooks, so you send the push yourself with a **RESTful Command** (`rest_command`). The simplest version has a fixed message. Add this to `configuration.yaml`:
  6. ```yaml
  7. rest_command:
  8. justpush_front_door:
  9. url: "your webhook URL"
  10. method: post
  11. content_type: "application/json"
  12. payload: '{"title": "🚪 Front door opened", "message": "Someone opened the front door", "priority": 1}'
  13. ```
  14. Restart Home Assistant (or reload YAML under **Developer tools → YAML**), then add the action **RESTful Command: justpush_front_door** to any automation, for example one with a state trigger on your door sensor turning on. You can try it straight away from **Developer tools → Actions**.
  15. The body accepts `title`, `message`, `priority` (-2 to 2, or `low`, `normal`, `high`, `highest`), `url` (adds an **Open** button, with an optional `button` label), `entity_id`, `state` and `topic`. There must be a title or a message; values such as `unknown`, `unavailable` or `None` are ignored.
  16. **One reusable command for every automation.** To pass the title and message from each automation (for example "washing machine done", with the energy it used), the payload needs Home Assistant templates. Those examples are in this recipe's README on GitHub: https://github.com/JustPush-io/studio-recipes/tree/main/home-assistant/automation-notification
  17. Add `?ha=` with your Home Assistant address to the URL (e.g. `your webhook URL?ha=https://homeassistant.local:8123`) and pushes that include an `entity_id` get a **View history** button.
  18. Requests aren't signed, so keep your endpoint URL private (put it in `secrets.yaml` if you share your configuration).
The code

What runs when the webhook arrives

Studio calls handleRequest(request) with the incoming webhook and sends the message it returns. It's yours after install; change anything.

transform.js
1// Home Assistant → automation notification (rest_command)
2// Fires when a Home Assistant automation or script calls a rest_command that posts a small JSON
3// body to this integration: {"title", "message", "priority", "url", "entity_id", "state", "topic"}.
4// Docs: https://www.home-assistant.io/integrations/rest_command/
5//
6// Home Assistant has no outgoing webhooks of its own, so you define the body yourself. Every field
7// is optional except that there must be a title or a message. Values that Home Assistant templates
8// render when something is missing ("None", "unknown", "unavailable", "") are ignored.
9
10// What Home Assistant templates render when a value is missing. Treated as "not given".
11const MISSING = new Set(["", "none", "null", "unknown", "unavailable", "undefined", "nan"])
12
13// A trimmed, non-missing string (numbers are turned into text), or null.
14function clean(value, max = 250) {
15 if (typeof value === "number") return Number.isFinite(value) ? String(value) : null
16 if (typeof value === "boolean") return String(value)
17 if (typeof value !== "string") return null
18
19 const text = value.trim()
20 if (MISSING.has(text.toLowerCase())) return null
21 return text.length > max ? `${text.slice(0, max - 1)}…` : text
22}
23
24// Table lookup that ignores inherited names such as "toString".
25function pick(table, key, fallback) {
26 return typeof key === "string" && Object.prototype.hasOwnProperty.call(table, key) ? table[key] : fallback
27}
28
29// Only link to real http(s) URLs.
30function link(url, cta) {
31 return typeof url === "string" && /^https?:\/\//.test(url) ? [{ cta, url }] : []
32}
33
34// Priority as a number (-2…2), a numeric string, or a word such as "high".
35const PRIORITY_WORDS = {
36 lowest: -2,
37 low: -1,
38 normal: 0,
39 default: 0,
40 high: 1,
41 highest: 2,
42 urgent: 2,
43 critical: 2,
44 emergency: 2,
45}
46
47function priority(value, fallback) {
48 const clamp = (n) => Math.max(-2, Math.min(2, Math.round(n)))
49 if (typeof value === "number") return Number.isFinite(value) ? clamp(value) : fallback
50
51 const text = clean(value)
52 if (!text) return fallback
53 if (/^[+-]?\d+(\.\d+)?$/.test(text)) return clamp(Number(text))
54 return pick(PRIORITY_WORDS, text.toLowerCase(), fallback)
55}
56
57// Entity IDs look like "binary_sensor.front_door".
58function entityId(value) {
59 const text = clean(value)
60 return text && /^[a-z0-9_]+\.[a-z0-9_]+$/.test(text) ? text : null
61}
62
63// The request body as an object. A rest_command without content_type: application/json
64// may arrive as a JSON string, so that's parsed too.
65function bodyOf(request) {
66 let body = request.body
67 if (typeof body === "string" && body.trim().startsWith("{")) {
68 try {
69 body = JSON.parse(body)
70 } catch {
71 return {}
72 }
73 }
74 return body && typeof body === "object" && !Array.isArray(body) ? body : {}
75}
76
77// ?ha=https://homeassistant.local:8123 adds a button to the entity's history.
78function historyButton(request, entity) {
79 const base = clean(request.query?.ha, 200)
80 if (!entity || !base || !/^https?:\/\/[^\s]+$/.test(base)) return []
81 return link(`${base.replace(/\/+$/, "")}/history?entity_id=${encodeURIComponent(entity)}`, "View history")
82}
83
84function handleRequest(request) {
85 const body = bodyOf(request)
86
87 // State-change bodies (with to_state) belong to the state-change recipe.
88 if (Object.prototype.hasOwnProperty.call(body, "to_state")) {
89 console.log("Ignoring state-change body — use the state-change recipe")
90 return null
91 }
92
93 const entity = entityId(body.entity_id)
94 const state = clean(body.state, 100)
95 let title = clean(body.title, 120)
96 let message = clean(body.message, 1000)
97
98 // Guard: nothing to say. (An entity and state alone still make a message.)
99 if (!title && !message && !(entity && state)) {
100 console.log("Ignoring Home Assistant request without a title or message")
101 return null
102 }
103
104 if (!message && entity && state) message = `${entity} is ${state}`
105 if (!title) title = "Home Assistant"
106
107 const button = clean(body.button, 30) ?? "Open"
108
109 return {
110 title,
111 message: message ?? "",
112 topic: clean(body.topic, 50) ?? "Home Assistant",
113 // Normal (0) unless the automation asks for something else; the automation knows best.
114 priority: priority(body.priority, 0),
115 buttons: [...link(clean(body.url, 500), button), ...historyButton(request, entity)],
116 }
117}
Payload

The Home Assistant rest_command webhook

This is what Home Assistant sends to your URL for rest_command. It is a sample, trimmed to the fields recipes use.

rest_command · sample.json
1{
2 "url": "",
3 "state": "1.8",
4 "title": "🧺 Washing machine done",
5 "message": "Time to empty it. This wash used 0.9 kWh.",
6 "priority": "0",
7 "entity_id": "sensor.washing_machine_power"
8}
FAQ

Home Assistant automation notification notifications: questions

Does this work on iPhone and Android?

Yes. Install the JustPush app from the App Store or Google Play and sign in. Every phone signed in to your account gets the notification.

Do I need to write code?

No. Install the recipe in Studio, paste your webhook URL into Home Assistant and you are done. The code is there if you want to change the text, the sound or the buttons.

Can I change what the notification says?

Yes. After install the recipe's code is yours. Edit it in Studio and test it against the sample payload before you save.

What does it cost?

JustPush is free for 30 days. After that it's $19.99 a year, or $39.99 once. There is no extra charge for recipes.

Ready when you are

Home Assistant on your phone in two minutes.

Install the recipe, paste one URL, done. Free for 30 days, no credit card required.