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.
Install the Integration
Section titled “Install the Integration”Through HACS, as a custom repository (the HACS default listing is coming):
- HACS → three-dot menu → Custom repositories →
https://github.com/OpenAlarm/homeassistant, category Integration. - HACS → search for OpenAlarm → Download.
- Restart Home Assistant.
- Settings → Devices & Services → Add Integration → OpenAlarm.
Without HACS, copy custom_components/openalarm from the repository into your Home Assistant
config/custom_components/ directory and restart.
Set It Up
Section titled “Set It Up”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.
What You Get
Section titled “What You Get”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 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, showing as triggered while an incident is open, or for two minutes after a trigger on a Local Only mode.
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.
The Panel Knows Its Mode
Section titled “The Panel Knows Its Mode”The panel entity carries two attributes, mode and mode_name: the armed mode while the alarm is
armed, the incident’s mode while it is triggered, and empty while disarmed. Branch on them
directly:
conditions: - condition: state entity_id: alarm_control_panel.home attribute: mode state: awayThis matters because Home Assistant’s own is_armed_away conditions read the panel’s current
state, which is triggered for as long as an incident is open (or for two minutes on a Local Only
mode) - so once the alarm has fired they can no longer tell Away from Home. The attribute can.
Vacation Shows as Away in HomeKit
Section titled “Vacation Shows as Away in HomeKit”Vacation is a real Home Assistant state, armed_vacation, with its own service and its own panel
button - so automations branch on it like any other mode.
HomeKit has no vacation. Apple’s security system accessory offers only Home, Away, Night and
Off, so Home Assistant’s HomeKit bridge maps armed_vacation to Away. That is accurate rather
than lossy - a vacation is an extended away - but two things follow: the Home app cannot tell
Vacation from Away, and you cannot select Vacation from HomeKit, because the bridge only sends
arm home, arm away, arm night and disarm. Arm it from Home Assistant, the console, or the API.
Sensor Check: Refuse to Arm While Something Is Open
Section titled “Sensor Check: Refuse to Arm While Something Is Open”Each alarm can carry a list of sensors that must be clear before it arms. Settings → Devices & Services → OpenAlarm → Configure → pick the alarm → Sensor check → pick the sensors → Submit. Binary sensor group helpers work well here: one group for doors, one for windows, one for tamper sensors.
When an arm is attempted and any picked sensor is on, unavailable, or unknown, the arm fails before it reaches OpenAlarm and the panel stays disarmed. The error names the sensor at fault. Groups are checked member by member, so one open door or one offline sensor is enough. Only the sensors you picked are checked - nothing is inferred from areas, labels, or device types - and a pick counts whatever kind of sensor it is. Disarming is never gated.
The failure shows wherever you armed from: an error in Home Assistant or the companion app, a failed step in an automation trace, or - through the HomeKit bridge - a scene that fails and a Siri that says so, because the panel never reached the state HomeKit asked for. That is the same signal a Ring panel gives when it is not clear to arm.
Build It Like a Panel
Section titled “Build It Like a Panel”OpenAlarm is the people layer; Home Assistant is the panel. The setup that holds up is three separate automations with three separate jobs.
Inputs - sensors trigger OpenAlarm, and OpenAlarm decides. Door, window, and tamper sensors
call openalarm.alarm_trigger with no mode. Don’t second-guess arming in the automation:
Trigger Only When Armed already ignores triggers while disarmed, the incident opens in whatever
mode the alarm is armed to, and repeat triggers fold into the incident that is already open. A
single is_armed condition is fine as hygiene; anything more is a second copy of logic OpenAlarm
already owns. While away, a door closing counts as much as one opening - an intruder shuts the
window they came in through.
automation: - alias: "OpenAlarm - Home" triggers: - trigger: state entity_id: binary_sensor.exterior_doors - trigger: state entity_id: binary_sensor.exterior_windows - trigger: state entity_id: binary_sensor.exterior_sensors_tamper to: "on" conditions: - condition: state entity_id: alarm_control_panel.home state: - armed_home - armed_away - armed_night actions: - action: openalarm.alarm_trigger data: device_id: your_openalarm_alarm_deviceResponses - the panel drives your devices. A siren, lights, a camera: trigger on the panel
entering triggered, branch on the mode attribute (a siren when Away, none when Home), and
stand down when the panel leaves triggered - back to its armed mode after a Local Only reset,
or to disarmed. Never call an openalarm.* action from a
response automation - the panel state came from OpenAlarm, and feeding it back makes a loop.
Trouble - tamper tells the owner, always. A tamper while disarmed is not an alarm, but it is never nothing: notify yourself, unconditionally, naming the sensor. That is the model every monitored panel uses, Ring included; the alarm channel and the trouble channel are different signals.
If a real panel - Alarmo, UniFi, a keypad - already owns your arming, skip the input automation and use the blueprint below instead: it forwards the panel’s own arming and trigger events.
Alarmo, Wired in One Step
Section titled “Alarmo, Wired in One Step”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.
Trigger From Any Automation
Section titled “Trigger From Any Automation”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_deviceFor sensors that should fire a specific response regardless of arming, pass a mode - a named
mode never falls back.
Test It Before You Need It
Section titled “Test It Before You Need It”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.
Without the Integration: rest_command
Section titled “Without the Integration: rest_command”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:
openalarm_api_key: "oa_m9s346q3d25vt4f5v37e3s3e28jt97kb6cq643dzvmxxqkfbf5kznwj47tan9zt2"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_keyMirroring 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_triggerBy 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.
If the Call Fails
Section titled “If the Call Fails”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.