Webhooks
How to give a widget its own web address so another service can push a value straight onto a screen, and what Mirra does and does not send back.
The webhook widget and its address are part of the Pro plan, the same gate as the REST API.
What a webhook is in Mirra
A webhook here is one direction only: something else posts a value, and a widget shows it. A queue length, a production count, a delivery ETA, the next name on a list — anything that changes often and already exists in a system you cannot easily poll.
The widget has its own address and needs no API key at all. That is the point of it. Use a webhook when the other service is doing the sending; use a key when your own code is doing the asking.
- One address per widget, not per account — so an address you hand to a third party reaches exactly one tile on one design.
- No key, no signing, no library. A single HTTP request from anything that can make one.
- The value arrives on the screen by the same path everything else does, so there is nothing to publish and no polling on the screen's side.
Setting one up
Add a Webhook widget to a scene
Screens, then the screen you want, then add a widget and choose Webhook. It starts four columns wide and two rows tall.
Select it and find "Where to send messages"
The address panel sits at the foot of the selected widget's settings, below the appearance fields. The address is created the first time you open the panel — there is no separate step to forget.
Copy the address
It looks like https://your-mirra-address/api/hook/ followed by a long random token.
Paste it into the other service
Wherever that service asks for a webhook URL, a POST URL or a callback address.
Press Send a test
This posts a real message through the real endpoint, so a pass means it works. The line beside the button then reads "Last message just now" with the value it received.
The address is created for you when the panel opens, so a widget that has never had its settings opened has no address yet. Open it once and copy.
What to send it, and what comes back
The endpoint accepts whatever the sending service happens to produce, because the alternative is a household being told their webhook is wrong by a service they cannot change. JSON, a form field, plain text or a query string all set the same thing.
Whatever arrives is trimmed and cut at 280 characters — long enough for a sentence, short enough that nobody pastes a novel onto a wall.
- A JSON body: the first of value, text, message, state or value1 that is present. IFTTT's own field names therefore work untouched.
- A JSON body that is just a string or a number: used as it is.
- A form-encoded body: value, text or value1, and failing those the whole body.
- Any other content type, or something labelled JSON that is not: the raw body, verbatim.
- A query string: ?value= or ?text=, which wins over the body if you send both.
- A plain GET with a query string, for services that can manage nothing else.
- The reply is {"ok": true, "value": "…", "screens": 3} — screens being how many paired screens were told to refetch.
A GET with no value at all stores an empty value, and the widget falls back to its placeholder. That is a tidy way to clear a stale number, and a surprise if you were only checking that the address answers.
The widget's settings
Everything above the address panel is about how the value looks on the wall.
Doing something as well as showing something
The action runs after the value has been stored, and it is deliberately best-effort: a misconfigured action does not make the sending service think the whole call failed and retry it.
Switching to a scene is the one worth thinking about. If the widget lives on a shared scene, there is no way to know which wall the message was "for", so every screen showing that scene changes. That is what shared means, and it is exactly what you want for a lockdown notice and exactly what you do not want for a kitchen timer.
- Switch to a scene — every screen the widget's scene is on is told to show the named scene.
- Show another widget / Hide another widget — flips that widget's own switch and leaves any visibility rule it has alone, so putting it back restores the rule.
- With no action set, the value is simply shown, which is what most webhooks want.
The address is the credential
The token in the URL is the only thing protecting the widget. There is no second secret and no signature to check, because the entire design goal is that somebody who has never seen an API can get this working by copying one address.
So treat the address like a password. Anyone holding it can post to that widget — nothing else, on no other screen, but that one tile is theirs.
- Change the address, under Show the technical details, mints a new token and instantly breaks anything still using the old one. It is confirmed first, and recorded in the audit log.
- Sixty calls a minute per webhook. Past that it answers 429 with retryAfterSeconds, so a stuck automation firing in a loop cannot cost you anything.
- An unknown or rotated token gets exactly the same 404 as one that never existed, with no hint about which — the endpoint is unauthenticated and enumerable by definition.
- Prefer POST over the GET form where you have the choice. A value in a URL ends up in more logs along the way than one in a body.
Do not put a webhook address in a public repository, a shared document or a screenshot. There is no way to tell who has used it beyond the count of deliveries, and the only repair is to rotate it and update every service you had given it to.
Mirra does not send webhooks
This is the limit people most often assume away, so it is worth stating plainly: Mirra never calls your server when something happens. There are no outbound events, no event names to subscribe to, no delivery retries, and consequently nothing signed — there is no signature header to verify, because there is no outbound request to sign.
If your system needs to know something Mirra knows, ask for it. The REST API is the supported route: poll /api/v1/broadcast to find out whether an emergency broadcast is running, /api/v1/screens to see which screens are online, /api/v1/lights for the state of the house. That is a poll rather than a push, and it is honest about being one.
The one thing in Mirra that verifies a webhook signature is the billing endpoint, which receives events from Stripe. That belongs to whoever runs the install rather than to a household, and it is covered under self-hosting.
When nothing arrives
- Check the line beside Send a test. "Nothing received yet" means no delivery has ever reached this widget — the other service has the wrong address, or is not sending at all.
- Press Send a test. If that works and your service does not, the problem is at the sending end, not here.
- If the panel says the webhook answered 429, the sending service is firing more than sixty times a minute. Slow it down; the limit is not adjustable.
- A 404 from the other service almost always means the address was rotated after it was pasted. Copy the current one again.
- If a value arrives but the widget still shows the placeholder, the message contained no field Mirra recognises — check it is sending value, text, message, state or value1.
- If the value is right but looks old, that is the age line doing its job. Whatever posts to the webhook has stopped.
Related
- The REST API and your keysHow to create an API key, what a single key is allowed to reach, and every endpoint the public v1 API exposes.
- Every widget there isThe complete list of widgets Mirra ships with, grouped the way the scene editor groups them, with what each one shows and what it needs before it will show anything.
- The scene editorThe scene editor is where you arrange a screen's widgets on a twelve-column grid, watch the real widgets render behind them, and push the result to the wall.
- Plans and allowancesWhat each Mirra plan includes — screens, household members and assistant credits — how credits are metered, and what happens when you reach a limit.