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: and action: syntax; older versions use platform: and service:).
  • Access to configuration.yaml and secrets.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

  1. Add the key and the REST command

    Put the API key in secrets.yaml and add a rest_command named send_sms to configuration.yaml. The to_json filter 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 is x-api-key, not Authorization.

    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: 15
  2. Check 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_sms action exists.

  3. Send a test text

    In Developer tools → Actions switch to YAML mode, paste the code below and click Perform action. A response with status: 200 means the message is queued on the phone. Use international format for numbers.

    Test action
    action: rest_command.send_sms
    data:
      recipients: ["+14155550123"]
      message: "Test from Home Assistant"
  4. Use it in an automation

    The example texts you when the door sensor opens while the alarm is armed. response_variable stores 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.

  1. 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_only can then stay true). With your own reverse proxy set local_only: false.
  2. Add the automation below. Change webhook_id to your own random string and list the numbers allowed to send commands.
  3. 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 tick MESSAGE_RECEIVED.
  4. Text the word status from a listed number to the gateway phone. The reply arrives within seconds.
Automation: reply to a "status" text
- 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') }} C

Ready-made scenarios

  • Alarm and door sensors

    A door or motion sensor firing while the alarm is armed texts you and a family member (recipients takes 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 status text 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_sms does not exist
Cause: Home Assistant has not loaded the new rest_command section, 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-key header, a typo in secrets.yaml, or an Authorization header instead of x-api-key.
Fix: Check the key name in secrets.yaml and 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 payload from this recipe with the to_json filter. In the dashboard check that the phone is enabled and the email is confirmed.
The webhook never starts the automation
Cause: A localhost or LAN address, local_only: true behind a reverse proxy, or a different webhook_id in the dashboard than in the automation.
Fix: Register the public HTTPS address ending in /api/webhook/<webhook_id>. Behind a reverse proxy set local_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 in trigger.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

  1. Home Assistant: RESTful Command
  2. Home Assistant: automation triggers (Webhook trigger)
  3. Home Assistant: storing secrets
  4. 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.