Skip to content

HTTP Actions

HTTP Actions let you fire any HTTP/REST request you define — a webhook, a smart-home API, a self-hosted script — straight from a watch tile, a Quick Menu, or Siri. The request runs in-app: no jump to Shortcuts, no app switch, no Home Assistant round-trip. Tap, get a haptic, done.

An HTTP Action is a reusable, named request you build once and reference anywhere. The watch fires it; you can even pull a value out of the reply and show it on the tile like a sensor.

  • Hit a webhook — fire a Node-RED, n8n, or IFTTT webhook with a tap.
  • Call a non-HA service — anything that speaks HTTP, including a box your Home Assistant doesn’t manage.
  • Run a self-hosted script — POST to your own server behind a private CA or mutual TLS.
  • Read a value back — pull a price, a temperature, or a status line out of the reply and pin it on the tile.

The free tier includes exactly one HTTP Action — enough to wire up your most-used request. Creating a second one (via New or Duplicate) is a Pro feature, behind the Unlock Unlimited HTTP Actions paywall. Buy Pro and the locked buttons unlock live, no restart needed.

Open the editor for an action and set:

  • Name — shown in pickers and used as the default tile label.
  • MethodGET, POST, PUT, PATCH, or DELETE.
  • URLhttp:// or https:// only. A space or a stray % typed straight into the URL is percent-encoded for you, so you don’t have to hand-encode a query.
  • Headers — an ordered list (order and duplicates are preserved).
  • Body — only on body-carrying verbs (POST/PUT/PATCH/DELETE). GET hides the Body section.
  • Body typeNone, JSON, Form, Text, or Voice recording. The app sets the matching Content-Type (application/json, application/x-www-form-urlencoded, text/plain, or audio/mp4) automatically — unless you set a Content-Type header yourself. Picking Voice recording turns the action into a record-and-send tile — see Voice Clip Actions.
  • Timeout — request deadline in seconds (defaults to 10).

The editor’s tabs are Request (timeout, headers, body, variables), Auth (authentication and TLS), and Output (reply value extraction and the inline Test).

The Auth tab has an Authentication card that composes a header for you — Bearer Token, Username & Password (Basic), or API Key Header. Whatever you choose is saved as an ordinary header, so it inherits the same encryption, backup stripping, and watch sync as everything else.

The API Key Header defaults to X-Api-Key, but you can rename it to whatever your service expects. A Basic password is masked, with an eye toggle to reveal it.

If you paste a request that already carries an Authorization header — or import a cURL with one — the editor recognizes it and lifts it into the Authentication card: a Bearer token, Basic credentials, or a known API-key header all migrate on their own. A scheme the card can’t represent (Digest, an HMAC signature, and the like) simply stays a plain, editable header.

Each action can carry a custom icon and color.

Every editor has a Test button (on the Output tab) that fires the real request from the phone and shows you the status, the reply, and the extracted value — so you debug your setup on the phone, never by squinting at watch toasts. If the action has variables, Test prompts you for them first.

Don’t want to type a request out by hand? Tap Import cURL and paste a curl command — from API docs or a browser’s Copy as cURL menu — and the method, URL, headers, body, and basic auth (-u) all fill in.

The importer models the flags people actually copy. Transport-only flags it can’t honor on-device — -k (insecure), -L (follow redirects), -s (silent), -v, -i, and friends — are silently dropped. A -d/--data flag implies POST; -G forces GET and folds data into the query. A @file body is skipped (the file can’t be read on-device), but you still get a POST skeleton to complete.

Set an action’s Body type to Voice recording and it becomes a record-and-send tile: instead of a typed body, tapping the action records a short voice clip on your watch and POSTs it raw as the request body (Content-Type: audio/mp4 — AAC-LC in an M4A container, 16 kHz mono). It’s built for Whisper transcription, voice notes, and voice-triggered automations — anywhere an endpoint wants an audio file.

There’s nothing to fill in under Body — the recording is the body. A Voice recording needs a body-carrying verb (POST, PUT, PATCH, or DELETE); everything else about the action — URL, headers, auth, TLS, timeout — works exactly as it does for any other request.

Tap the tile and the watch starts recording immediately — you already tapped, so there’s no separate “start” step. You see the elapsed time and a big Stop button, and recording auto-stops at 30 seconds. Then you get a Send / Re-record confirm before anything leaves the watch. Swipe or tap away to cancel — nothing is sent.

The clip is captured fresh each time and handed straight to the request. It is never stored on the watch, never synced, and never included in a backup.

In the editor, add an HTTP Action tile and pick the action from the HTTP Actions picker. The tile only references the action — the request itself lives in your library — so editing the action in one place updates every tile that points at it.

If you delete an action, any tile still pointing at it shows a warning and stops firing (a failure haptic, no silent no-op). Re-point the tile at a live action to fix it.

Press and hold an HTTP Action tile and slide to open its detail view — it shows the last extracted value, when it was last updated (“updated 2m ago”), whether the last fetch failed, and a Run Now button to fire it on the spot.

Drop a {{name}} token into the URL, a header, or the body and it becomes an input variable — a value you’re prompted for each time the action fires. The editor keeps the variable list in sync with the tokens you type. Each variable has a kind:

  • Text — escaped safely wherever it lands (percent-encoded in a URL, JSON-escaped inside a JSON body, CR/LF-stripped in a header).
  • Number — injected unquoted in a JSON body when it’s a valid number (so {"brightness": 100}, not "100").

Give a variable a list of quick values and they appear as tappable suggestions at fire time, so you usually tap instead of type.

Flip Quick values only and fire time skips the keyboard, dictation, and scribble entirely — you get a clean full-screen tappable list of just your quick values. It auto-enables the first time you add a quick value to a variable. If you later remove every quick value, the flag goes inert and the variable falls back to a normal typed prompt rather than dead-ending the action.

The editor also offers an inline {{ picker so you can insert a token (or a global) without typing the braces.

A global variable is a library-level {{name}} constant you set once and reuse across every action — perfect for a base URL or an API host. Change {{haurl}} in one place and every action that references it follows.

Globals and input variables share the {{name}} syntax; they’re told apart by name, not by brace count:

  • A {{name}} that matches a defined global expands to that global’s fixed value before the request is built.
  • Any other {{name}} prompts at fire time.
  • A global therefore wins over a same-named prompt — define a global message and an action’s {{message}} stops asking.

On the Output tab, turn on extraction by picking a Source other than None, and the app pulls one value out of a successful reply. Choose from:

  • JSON Field — a simple dot-path into the JSON reply. Dictionary segments are keys; a bare integer indexes an array, so data.0.temp reaches the first array element’s temp. An empty path returns the whole body.
  • Regex Capture — pulls a value out of any text reply (JSON, XML, HTML, plain text, logs). Returns capture group 1 when your pattern declares one, else the whole match — there’s no group picker. The dot matches across newlines.
  • Status Code — the HTTP status as the value.
  • Body Text — a one-line snippet of the response body.
  • Response Header — read a named header. The lookup is case-insensitive.

An optional Unit suffix is appended to the value exactly as you type it. The leading space in " W" is intentional — it’s how you put a gap between the number and the unit.

Don’t know the exact dot-path or header name? The Output tab has a field-picker button (a sparkle over a magnifying glass) that fires the request once and lists what came back — every JSON leaf as a ready-to-use dot-path, or every response header — so you tap to insert instead of typing it by hand.

Where the reply appears is a per-tile choice, set in the editor — while the extraction itself lives on the action, so two tiles firing the same request can display it differently:

  • Banner — the value flashes in the bottom banner after each fire (or the raw body snippet, if the action has no extraction).
  • Tile Value — the extracted value is pinned on the tile like a sensor reading. This needs the action to have an extraction configured. A user-initiated tap or pull flashes the tile green on success; if the last fire failed, the tile flags the held value as stale.

Pick Tile Value and the tile drops its icon, handing the whole face to the extracted value — a price, a temperature, a status line shown like a built-in sensor. The unit from the action’s Reply Value is already appended.

Each Tile Value tile carries its own look, set under the display picker in the editor:

  • Show Name — captions the value with the tile’s name, so a glance reads “humidity 55” instead of a bare “55”. On by default; turn it off for a pure big-number look.
  • Text Size6–36 pt, or Auto (scales with the tile’s icon size). Drag to pin a size; tap Auto to clear it.
  • Lines — cap how many lines the value may wrap to (1–8), or Auto (grows with the tile’s row span).
  • Line Spacing — extra points between wrapped lines, Default up to +12 pt.
  • Vertical Position — nudge the value Up or Down (±20 pt) from Center.
  • Text Color — a theme swatch or a custom color; Reset returns to the default.

A Tile Value normally only changes when you tap the tile. Auto-Refresh lets it keep itself current while you’re looking at it. It’s one escalating ladder — pick a single rung:

  • Off — only re-fires on tap (the default).
  • On Open — re-fires once each time you swipe to the tile’s page.
  • 1s / 3s / 5s / 10s / 30s — keeps polling on a timer so the value ticks like a live sensor.

A separate Refresh on Pull toggle re-fires whenever you pull-to-refresh the page — an explicit refresh, independent of the ladder.

The tile tells you whether the number you’re seeing is trustworthy:

  • Green pulse — a tap or pull just reloaded the value successfully. It’s the “it worked” cue even when the refreshed number is unchanged. Silent timer and on-open refreshes do not pulse — a polling tile never strobes green every tick.
  • Red exclamation + dimmed value — the last fire failed (a non-2xx, a transport error, or a request that wouldn’t build), so the value on screen is the last good one, now flagged stale. A later successful fire clears the flag.

The same action runs from every surface:

  • Standalone tile — tap the HTTP Action tile.
  • Quick Menu slots — assign Run HTTP Action to a slot in an Entity, Universal, or per-entity Quick Menu.
  • Hold-and-slide — point any tile’s press-and-slide direction at an HTTP Action.
  • Widgets & complications — fire from a complication or widget.
  • Siri & Shortcuts — use the Run HTTP Action Shortcuts action.

Variable handling differs by surface:

  • Tile, Quick Menu, hold-and-slide — prompt for any variables at fire time (or show the quick-value list). An action whose tokens are all globals fires immediately.
  • Widgets & complications — a variable-free action direct-fires from the widget with no app launch. An action with variables opens the watch app to prompt, then fires.
  • Siri & Shortcuts — substitutes preset (or empty) values; it never prompts.

A Voice Clip Action is the exception: even though it takes no variables, it can only record inside the watch app, so a widget or complication deep-links in to record rather than direct-firing, and Siri/Shortcuts declines it.

The Shortcuts action is Run HTTP Action (Wrist Assistant). It returns the extracted reply value, so a Shortcut can chain the result into the next step. There is no spoken Siri phrase — build the shortcut manually in the Shortcuts app, then run it however you like.

The same Run HTTP Action (Wrist Assistant) action is available in the watch’s own Shortcuts app, so you can fire an action straight from the wrist without going through your phone.

An HTTP Action succeeds only when the server replies with a 2xx status (200–299). Anything else — a 4xx, a 5xx, a transport error, or a request that wouldn’t build — is a failure: you get a failure haptic, and a Tile Value flags its held number stale with a red exclamation.

Redirects are handled deliberately. A 3xx that reaches the app counts as a failure rather than being silently followed, and a redirect that would downgrade a body-carrying verb to GET (POST/PUT/PATCH/DELETE → GET) is refused outright. This stops an action that’s been 302’d to a login page from quietly dropping its body and reporting a false success — you see a real failure instead of a request that looks like it worked but didn’t.

For a self-hosted endpoint, the Auth tab has two independent, per-action TLS opt-ins, both off by default and both scoped to that action’s own host (never sent to a host it might redirect to):

  • Allow self-signed certificate — accept an untrusted server certificate (self-signed or private CA) for this action’s host. Loosens trust in the server’s certificate only.
  • Send client certificate — present the app’s imported mutual-TLS identity when firing this action — for a server behind mTLS or Cloudflare Access. This option only appears once you’ve imported a certificate in Credentials.
  • Requests are stored in the device Keychain (encrypted at rest) and synced to the watch over the encrypted Watch Connectivity link.
  • The request details (URL, headers, body) and any global values are excluded from plaintext backups — they ride only the encrypted backup envelope. After a plaintext-only restore, an action comes back as a “Needs setup” skeleton for you to re-supply.
  • HTTP Actions never present Home Assistant’s own mTLS client certificate to an arbitrary endpoint — the identity is offered only when you turn on Send client certificate for that specific action.
  • Macros — chain an HTTP Action together with Home Assistant calls, waits, and prompts into one multi-step tile.
  • Wrist Webhooks — the inbound counterpart: a private URL that delivers alerts to your wrist. A webhook’s Run an Action button fires one of these HTTP Actions on the watch.