Skip to content

Home Assistant

Home Assistant already decides when something is worth alerting about. OpenAlarm is the layer it hands that decision to: texts, calls, and email to your people, in order, until someone acknowledges. The official integration is the easiest way to wire the two together; plain rest_command works too and is documented at the bottom of this page.

Through HACS:

  1. HACS → search for OpenAlarm → Download.
  2. Restart Home Assistant.
  3. Settings → Devices & Services → Add IntegrationOpenAlarm.

If OpenAlarm is not yet in your HACS search results, add it as a custom repository first: HACS → three-dot menu → Custom repositorieshttps://github.com/OpenAlarm/homeassistant, category Integration.

Without HACS, copy custom_components/openalarm from the repository into your Home Assistant config/custom_components/ directory and restart.

The config flow asks for one thing: an API key. Create it in the OpenAlarm console under Developers → API Keys - see the Authentication guide.

The key decides what Home Assistant can see. A key scoped to one alarm exposes one alarm. Scope it deliberately: this key lives in your Home Assistant configuration, and anything it can reach, an automation can fire.

If the key reaches more than one location, the flow asks which one to set up. Add the integration again for each additional location.

Every alarm and panic button the key can reach becomes a device - automations target Cabin Perimeter, never a 32-character ID. Six actions drive them:

Action What it does
openalarm.alarm_arm Arms an alarm, optionally in a named mode
openalarm.alarm_disarm Disarms an alarm
openalarm.alarm_trigger Triggers an alarm, starting its escalation policy
openalarm.alarm_clear Clears an alarm’s open incident
openalarm.panic_trigger Triggers a panic button
openalarm.panic_clear Clears a panic button’s open incident

Your modes - including custom ones - appear in the arm and trigger dropdowns by name. Each alarm also carries an alarm control panel entity for dashboards: arm, disarm, and trigger it like any other panel, with an open incident showing as triggered until it clears.

State is pushed. The integration holds a realtime connection to OpenAlarm, so an arm, disarm, or trigger made anywhere - the console, another integration, a curl - shows on the panel within a couple of seconds. If the connection drops, a one-minute poll covers the gap until it reconnects. The inventory (alarms, panic buttons, modes) refreshes every six hours; just changed something in the console and want it now? Settings → Devices & Services → OpenAlarm → three-dot menu → Reload.

If Alarmo (or any alarm_control_panel) owns your arming, the Forward an alarm panel to OpenAlarm blueprint mirrors it: arming states carry across, a trigger opens an OpenAlarm incident so your contacts are alerted, and a disarm ends it. Alarmo keeps its entry delays and its siren; OpenAlarm adds the people.

Import the blueprint (or Settings → Automations & Scenes → Blueprints → Import Blueprint with the repository URL), then create an automation from it: pick your panel entity and your OpenAlarm alarm. That is the whole setup.

Anything that can run an action can fire an alarm - leak, smoke, freezer door, sump pump:

automation:
- alias: "OpenAlarm - water leak"
triggers:
- trigger: state
entity_id: binary_sensor.utility_room_leak
to: "on"
actions:
- action: openalarm.alarm_trigger
data:
device_id: your_openalarm_alarm_device

For sensors that should fire a specific response regardless of arming, pass a mode - a named mode never falls back.

Set the alarm’s Environment to Test in the console and trip the sensor for real. The incident records everyone who would have been reached - and nobody is contacted. Flip to Live when the chain reads right; nothing in Home Assistant changes.

One deliberate caveat: OpenAlarm suppresses people, not systems. A test trigger still looks like a real trigger to Home Assistant - the panel entity shows triggered, and any automation you hang off it (a siren, a light scene) will run. Test mode rehearses your alerting chain; it does not mute your own automations. See Test Mode.

Every call is a bodyless GET with the key in a header - nothing sensitive ever sits in the URL. Keep the key in secrets.yaml:

secrets.yaml
openalarm_api_key: "oa_m9s346q3d25vt4f5v37e3s3e28jt97kb6cq643dzvmxxqkfbf5kznwj47tan9zt2"
configuration.yaml
rest_command:
openalarm_arm_away:
url: "https://api.openalarm.io/v1/alarm/k7m3x9q2f8d4w1b5n6p0r3t7v2x5z9c4/arm/away"
headers:
X-API-Key: !secret openalarm_api_key
openalarm_arm_home:
url: "https://api.openalarm.io/v1/alarm/k7m3x9q2f8d4w1b5n6p0r3t7v2x5z9c4/arm/home"
headers:
X-API-Key: !secret openalarm_api_key
openalarm_disarm:
url: "https://api.openalarm.io/v1/alarm/k7m3x9q2f8d4w1b5n6p0r3t7v2x5z9c4/disarm"
headers:
X-API-Key: !secret openalarm_api_key
openalarm_trigger:
url: "https://api.openalarm.io/v1/alarm/k7m3x9q2f8d4w1b5n6p0r3t7v2x5z9c4/trigger"
headers:
X-API-Key: !secret openalarm_api_key

Mirroring an alarm panel by hand looks like this - it is exactly what the blueprint does for you:

automation:
- alias: "OpenAlarm - mirror Alarmo state"
triggers:
- trigger: state
entity_id: alarm_control_panel.alarmo
actions:
- choose:
- conditions: "{{ trigger.to_state.state == 'armed_away' }}"
sequence:
- action: rest_command.openalarm_arm_away
- conditions: "{{ trigger.to_state.state == 'armed_home' }}"
sequence:
- action: rest_command.openalarm_arm_home
- conditions: "{{ trigger.to_state.state == 'disarmed' }}"
sequence:
- action: rest_command.openalarm_disarm
- alias: "OpenAlarm - Alarmo triggered"
triggers:
- trigger: state
entity_id: alarm_control_panel.alarmo
to: "triggered"
actions:
- action: rest_command.openalarm_trigger

By the time triggered reaches OpenAlarm, Alarmo has already applied every delay and override you configured - which is exactly why a trigger always fires, armed or not.

rest_command logs the response in Home Assistant’s log. A 401 means the key; a 404 means the alarm ID is not one this key can fire - see Errors for what each code means and what to quote when reporting a problem.