Statuspage component status notifications on your phone.

Get a push notification when a component on a status page you follow (yours or a vendor's) goes degraded, partially or fully down, into maintenance, or back to operational.

How it works

Three steps to your first push

STEP 01

Install the recipe

One click in Studio gives you a personal webhook URL.

STEP 02

Paste your URL into Statuspage

Add it as a webhook for Webhook subscription.

STEP 03

Get a push on your phone

With the text, sound and buttons from the recipe.

Setup

How to set up the Statuspage webhook subscription webhook

  1. Click Install in Studio and sign in. The recipe is added to your account and you get a personal webhook URL.
  2. Open the status page you want to follow (your own, or a vendor's Statuspage-hosted page) and click Subscribe to updates.
  3. Pick the webhook tab, paste your webhook URL as the Webhook URL, and enter your email address (Statuspage emails it if deliveries keep failing).https://••••••••/•••••••• your personal URL, shown after install
  4. No webhook tab? The page doesn't allow webhook subscribers. On your own page, turn on Webhook under Subscribers > Options > Settings first.
  5. Statuspage webhooks are a kind of **subscriber**, so this works for any Statuspage-hosted status page that allows webhook subscriptions: your own, or a vendor you depend on (for example `githubstatus.com`).
  6. Open the status page and click **Subscribe to updates**, then the **webhook** tab. If there's no webhook tab, the page owner hasn't enabled webhook subscribers. On your own page, turn it on under **Subscribers → Options → Settings → Webhook** and save.
  7. Paste the URL above as the **Webhook URL** and enter your **email address**. Statuspage uses it to email you if your endpoint keeps failing. If a confirmation email arrives, confirm it.
  8. Subscribe. If the page lets you pick components, choose the ones you care about.
  9. One subscription sends **both** incident and component webhooks to the same URL. This recipe only pushes for component status changes; the Incident update recipe handles incidents. A component usually changes status as part of an incident, so with both installed you'll get a push for each.
  10. Optional query parameters on the URL above:
  11. `?name=GitHub` puts the page's name in the title (the webhook itself doesn't include it).
  12. `?only=API Requests,Git Operations` only pushes for those components (names as shown on the page, case-insensitive; URL-encode spaces as `%20`).
  13. `?recovered=0` skips the "is operational" pushes when a component recovers.
  14. Combine them with `&`, e.g. `?name=GitHub&only=Actions`.
  15. Requests aren't signed, so keep your endpoint URL private. After 10 failed deliveries in about an hour the subscription is quarantined and you get an email; re-subscribe to reactivate it.
The code

What runs when the webhook arrives

Studio calls handleRequest(request) with the incoming webhook and sends the message it returns. It's yours after install; change anything.

transform.js
1// Statuspage → component status changed
2// Fires when a component on a status page you subscribed to by webhook changes status
3// (operational, degraded, partial or major outage, under maintenance). Works for your own
4// page and for any vendor's Statuspage-hosted page that allows webhook subscribers.
5// Docs: https://support.atlassian.com/statuspage/docs/enable-webhook-notifications/
6
7// Component statuses: how to phrase them, and how loud to be.
8const STATES = {
9 major_outage: { emoji: "🔴", title: "has a major outage", was: "a major outage", priority: 2 }, // Highest — it's down right now
10 partial_outage: { emoji: "🟠", title: "has a partial outage", was: "a partial outage", priority: 1 }, // High — partly down, you may need to work around it
11 degraded_performance: { emoji: "🟡", title: "has degraded performance", was: "degraded performance", priority: 0 }, // Normal — slow, not down
12 under_maintenance: { emoji: "🛠️", title: "is under maintenance", was: "maintenance", priority: -1 }, // Low — planned work
13 operational: { emoji: "✅", title: "is operational", was: "operational", priority: -1 }, // Low — good news, back to normal
14}
15
16// Look a key up without tripping over inherited names such as "toString".
17function pick(table, key, fallback) {
18 return typeof key === "string" && Object.prototype.hasOwnProperty.call(table, key) ? table[key] : fallback
19}
20
21// Only link to real http(s) URLs.
22function link(url, cta) {
23 return typeof url === "string" && /^https?:\/\//.test(url) ? [{ cta, url }] : []
24}
25
26// The status page itself, from the unsubscribe link's host (e.g. https://www.githubstatus.com).
27function pageUrl(body) {
28 const match = typeof body.meta?.unsubscribe === "string" ? body.meta.unsubscribe.match(/^https?:\/\/[^/?#]+/) : null
29 return match ? match[0] : null
30}
31
32function handleRequest(request) {
33 const body = request.body && typeof request.body === "object" ? request.body : {}
34 const update = body.component_update && typeof body.component_update === "object" ? body.component_update : null
35 const state = pick(STATES, update?.new_status, null)
36
37 // Guard: only component webhooks. Incident webhooks (incident) and junk stay quiet.
38 if (!update || !state) {
39 console.log(`Ignoring Statuspage payload — not a component update (${update?.new_status ?? "no component_update"})`)
40 return null
41 }
42
43 if (update.old_status === update.new_status) {
44 console.log(`Component status unchanged (${update.new_status}) — skipping`)
45 return null
46 }
47
48 const query = request.query || {}
49 const component = typeof body.component?.name === "string" && body.component.name.trim() ? body.component.name.trim() : "A component"
50
51 // ?only=API,Git Operations limits pushes to those components (names, case-insensitive).
52 const only = typeof query.only === "string"
53 ? query.only.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean)
54 : []
55 if (only.length && !only.includes(component.toLowerCase())) {
56 console.log(`Skipping "${component}" — not in ?only=`)
57 return null
58 }
59
60 // ?recovered=0 skips the "back to operational" pushes.
61 if (update.new_status === "operational" && ["0", "false", "no"].includes(String(query.recovered ?? "").toLowerCase())) {
62 console.log("Skipping recovery (?recovered=0)")
63 return null
64 }
65
66 const page = typeof query.name === "string" && query.name.trim() ? `${query.name.trim()}: ` : ""
67 const was = pick(STATES, update.old_status, null)
68 const overall = typeof body.page?.status_description === "string" ? body.page.status_description.trim() : ""
69
70 return {
71 title: `${state.emoji} ${page}${component} ${state.title}`,
72 message: [was ? `Was ${was.was}` : null, overall ? `Page status: ${overall}` : null].filter(Boolean).join(" · ") ||
73 "Component status changed",
74 topic: "Statuspage",
75 priority: state.priority,
76 buttons: link(pageUrl(body), "Status page"),
77 }
78}
Payload

The Statuspage component_update webhook

This is what Statuspage sends to your URL for webhook subscription. It is a sample, trimmed to the fields recipes use.

component_update · sample.json
1{
2 "meta": {
3 "unsubscribe": "https://status.example.com/?unsubscribe=j0vqr9kl3513",
4 "documentation": "https://doers.statuspage.io/customer-notifications/webhooks/"
5 },
6 "page": {
7 "id": "j2mfxwj97wnj",
8 "status_indicator": "major",
9 "status_description": "Partial System Outage"
10 },
11 "component": {
12 "id": "rb5wq1dczvbm",
13 "name": "API Requests",
14 "status": "major_outage",
15 "created_at": "2024-05-29T21:32:28Z"
16 },
17 "component_update": {
18 "id": "k7730b5v92bv",
19 "created_at": "2026-09-29T21:32:28Z",
20 "new_status": "major_outage",
21 "old_status": "operational",
22 "component_id": "rb5wq1dczvbm"
23 }
24}
FAQ

Statuspage component status notifications: questions

Does this work on iPhone and Android?

Yes. Install the JustPush app from the App Store or Google Play and sign in. Every phone signed in to your account gets the notification.

Do I need to write code?

No. Install the recipe in Studio, paste your webhook URL into Statuspage and you are done. The code is there if you want to change the text, the sound or the buttons.

Can I change what the notification says?

Yes. After install the recipe's code is yours. Edit it in Studio and test it against the sample payload before you save.

What does it cost?

JustPush is free for 30 days. After that it's $19.99 a year, or $39.99 once. There is no extra charge for recipes.

Ready when you are

Statuspage on your phone in two minutes.

Install the recipe, paste one URL, done. Free for 30 days, no credit card required.