Home Assistant SMS from your own number: alerts and commands
Checked against the docs:
Home Assistant sends SMS through rest_command: in configuration.yaml you define a POST to https://smsportal.app/api/v1/gateway/send-sms with an x-api-key header, and an automation calls the rest_command.send_sms action. The text goes out from your own Android phone. Incoming texts reach an automation with a webhook trigger, because smsportal posts a MESSAGE_RECEIVED event to it.
What you need
- Home Assistant 2024.10 or newer (
triggers:andaction:syntax; older versions useplatform:andservice:). - Access to
configuration.yamlandsecrets.yaml(for example the File editor or Studio Code Server add-on). - A smsportal account with an Android phone and SIM card connected, plus an API key (API Keys → Generate API Key).
- To receive texts: Home Assistant reachable from the internet over HTTPS (Home Assistant Cloud by Nabu Casa or a reverse proxy).
How to send an SMS from Home Assistant
Add the key and the REST command
Put the API key in
secrets.yamland add arest_commandnamedsend_smstoconfiguration.yaml. Theto_jsonfilter turns the number list and the text into valid JSON, so a quote or an accented letter in the message cannot break the request. The header isx-api-key, notAuthorization.secrets.yaml and configuration.yaml# secrets.yaml smsportal_api_key: "YOUR_API_KEY" # configuration.yaml rest_command: send_sms: url: "https://smsportal.app/api/v1/gateway/send-sms" method: post headers: x-api-key: !secret smsportal_api_key content_type: "application/json" payload: '{"recipients": {{ recipients | to_json }}, "message": {{ message | to_json }}}' timeout: 15Check the configuration and restart
In Developer tools open the YAML tab, click Check configuration, then restart Home Assistant. After the restart the
rest_command.send_smsaction exists.Send a test text
In Developer tools → Actions switch to YAML mode, paste the code below and click Perform action. A response with
status: 200means the message is queued on the phone. Use international format for numbers.Test actionaction: rest_command.send_sms data: recipients: ["+14155550123"] message: "Test from Home Assistant"Use it in an automation
The example texts you when the door sensor opens while the alarm is armed.
response_variablestores the API response: on status 400 or above (wrong key, no phone, plan limit used up) you get a notification in Home Assistant. Replace the entity names with yours.Automation: alarm and door# automations.yaml (in the editor: ⋮ menu → Edit in YAML, without the leading dash) - id: "sms_door_alarm" alias: "SMS: door opened while alarm is armed" triggers: - trigger: state entity_id: binary_sensor.front_door to: "on" conditions: - condition: state entity_id: alarm_control_panel.home state: armed_away actions: - action: rest_command.send_sms data: recipients: ["+14155550123"] message: "Alarm: front door opened at {{ now().strftime('%H:%M') }}" response_variable: sms - if: - condition: template value_template: "{{ sms['status'] >= 400 }}" then: - action: persistent_notification.create data: title: "SMS not sent" message: "smsportal returned {{ sms['status'] }}: {{ sms['content'] }}"
How to control your home by SMS (STATUS command)
When the phone receives a text, smsportal posts JSON to the Home Assistant webhook. In the automation it is under trigger.json: trigger.json.sender is the number and trigger.json.message is the text. Home Assistant cannot check the X-Signature header, so the webhook_id itself is the password: use a long random string (for example openssl rand -hex 16) and keep it private.
- Get a public HTTPS address. With Home Assistant Cloud you enable the automation webhook in the cloud settings and get an address on the Nabu Casa domain (
local_onlycan then staytrue). With your own reverse proxy setlocal_only: false. - Add the automation below. Change
webhook_idto your own random string and list the numbers allowed to send commands. - In the smsportal dashboard open Webhooks → Create Webhook, paste
https://your-home.example.com/api/webhook/<webhook_id>, enter a signing secret (at least 20 characters; Home Assistant ignores it, but the field is required) and tickMESSAGE_RECEIVED. - Text the word
statusfrom a listed number to the gateway phone. The reply arrives within seconds.
- id: "sms_status_command"
alias: "SMS: STATUS command"
mode: queued
triggers:
- trigger: webhook
webhook_id: "sms-c4f1e9a27b8d4e3f96a05b1d2e7c8f40"
allowed_methods: [POST]
local_only: false
conditions:
- condition: template
value_template: >-
{{ trigger.json.webhookEvent == 'MESSAGE_RECEIVED'
and trigger.json.sender in ['+14155550123', '+14155550124']
and (trigger.json.message | trim | lower) == 'status' }}
actions:
- action: rest_command.send_sms
data:
recipients: ["{{ trigger.json.sender }}"]
message: >-
Alarm: {{ states('alarm_control_panel.home') }},
door: {{ states('binary_sensor.front_door') }},
living room: {{ states('sensor.living_room_temperature') }} CReady-made scenarios
Alarm and door sensors
A door or motion sensor firing while the alarm is armed texts you and a family member (
recipientstakes a list). The SMS arrives even when the recipient has no mobile data and push notifications from the app would not.SMS commands to the house
A
statustext from a listed number returns the alarm state, the door and the temperature. Caller ID can be spoofed, so use SMS to read state or switch harmless things like heating. Do not disarm the alarm or open the gate by SMS.Power outage alert
When a UPS integration reports running on battery, an automation sends a text. The request travels from Home Assistant over the internet to smsportal, so the Home Assistant host and the router need a UPS. The gateway phone runs on its battery and mobile data, so it does not need home Wi-Fi.
Errors and fixes
rest_command.send_smsdoes not exist- Cause: Home Assistant has not loaded the new
rest_commandsection, or the YAML has an indentation error. - Fix: Run Check configuration in Developer tools → YAML, fix the error and restart Home Assistant.
- The log shows
Error. Url: ... Status code 401 - Cause: No
x-api-keyheader, a typo insecrets.yaml, or anAuthorizationheader instead ofx-api-key. - Fix: Check the key name in
secrets.yamland in!secret. Generate a new key in the dashboard if the old one was deleted. - Status 400
- Cause: Invalid JSON (text inserted without
to_json), no enabled phone, or the account email is not verified. - Fix: Use the
payloadfrom this recipe with theto_jsonfilter. In the dashboard check that the phone is enabled and the email is confirmed. - The webhook never starts the automation
- Cause: A
localhostor LAN address,local_only: truebehind a reverse proxy, or a differentwebhook_idin the dashboard than in the automation. - Fix: Register the public HTTPS address ending in
/api/webhook/<webhook_id>. Behind a reverse proxy setlocal_only: false. Automation Traces show whether the request arrived. - The command arrives but nothing happens
- Cause: The number in the list is written differently from
sender(for example without+1), or the text has extra words. - Fix: Write numbers as
+14155550123. Open the automation Traces to see what came intrigger.json.
Frequently asked questions
Is there a smsportal integration for Home Assistant?
There is no dedicated integration. The built-in `rest_command` for sending and the `webhook` trigger for receiving are enough, with nothing to install from HACS.
Will the text go out if the home internet is down?
Not if Home Assistant is offline too. The send request goes from Home Assistant over the internet to smsportal and only then to the phone. A router and host on a UPS with a mobile backup link solve this.
How fast does the SMS arrive?
Usually within seconds. The phone sends one message at a time with a 5-second pause by default. If it is offline, the text waits in the queue for up to 72 hours and then expires. The dashboard shows the phone status.
Can Home Assistant verify the webhook signature?
No. The `webhook` trigger does not compute an HMAC, so `X-Signature` goes unchecked. A long random `webhook_id` and a number allowlist in the condition protect you. If you need signature checks, receive the webhook in n8n and call Home Assistant from there.
Does this replace push notifications from the app?
It complements them. SMS reaches a phone without data or an app, which suits alarms. Keep everyday updates in push notifications.
Sources
- Home Assistant: RESTful Command
- Home Assistant: automation triggers (Webhook trigger)
- Home Assistant: storing secrets
- smsportal API documentation
More in the guides
Send your first SMS today
Create a free account, connect your phone and see how customers respond to messages from your number.