Cronitor monitor failed or recovered notifications on your phone.

Get a push notification when a Cronitor cron job, heartbeat or website check fails, and a quiet one when it recovers.

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 Cronitor

Add it as a webhook for Webhooks.

STEP 03

Get a push on your phone

With the text, sound and buttons from the recipe.

Setup

How to set up the Cronitor webhooks webhook

  1. Click Install in Studio and sign in. The recipe is added to your account and you get a personal webhook URL.
  2. In Cronitor, open Settings > Integrations, click Create Integration and select Webhooks.
  3. Give it a name and identifier, paste your webhook URL as the URL and press Create Integration.https://••••••••/•••••••• your personal URL, shown after install
  4. Add the integration to the Notification Lists your jobs and monitors use.
  5. In Cronitor, open **Settings → Integrations**, click **Create Integration** and select **Webhooks**. Give it a name and a unique identifier, paste the URL above and press **Create Integration**. Webhooks are available on every plan, including the free Hacker plan.
  6. Then add the integration to one or more **Notification Lists** (Settings → Alerts). Every job, heartbeat or check that uses those lists will send a push when it fails and a quiet one when it recovers.
  7. Optional query parameters on the URL:
  8. `?env=production` only pushes alerts from that Cronitor environment.
  9. `?urgent=1` sends failures at Highest priority instead of High, e.g. for a list that only holds website checks.
  10. Combine them with `&`, e.g. `your webhook URL?env=production&urgent=1`.
  11. **Testing:** Cronitor has no test button for webhooks. Create a heartbeat monitor on the same notification list, open its telemetry URL once, then again with `?state=fail` added (an alert), then once more without it (a recovery).
  12. Cronitor's docs list the payload fields (`id`, `monitor`, `description`, `type`, `rule`, `environment`, `group`, `issue_url`, `monitor_url`) but don't show an example, request headers or signing, so the wording of `description` and `rule` in `sample.json` is illustrative. Keep your endpoint URL private.
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// Cronitor → monitor alert or recovery
2// Fires when a Cronitor job, heartbeat or check fails (type ALERT) and when it becomes
3// healthy again (type RECOVERY), via a Webhooks integration on a Notification List.
4// Docs: https://cronitor.io/docs/using-webhooks
5
6// Webhook "type" values we handle (Cronitor documents RECOVERY|ALERT).
7const TYPES = {
8 ALERT: "alert",
9 RECOVERY: "recovery",
10}
11
12// Look up a key without tripping over inherited names like "toString".
13function pick(table, key, fallback) {
14 return typeof key === "string" && Object.prototype.hasOwnProperty.call(table, key) ? table[key] : fallback
15}
16
17// Only link to real http(s) URLs.
18function link(url, cta) {
19 return typeof url === "string" && /^https?:\/\//.test(url) ? [{ cta, url }] : []
20}
21
22// A trimmed string, or null for anything empty or not text-like.
23function text(value) {
24 if (typeof value !== "string" && typeof value !== "number") return null
25 const s = String(value).trim()
26 return s ? s : null
27}
28
29// "1", "true" or "yes" in the query string.
30function flag(request, name) {
31 return ["1", "true", "yes"].includes(String(request.query?.[name] ?? "").toLowerCase())
32}
33
34function handleRequest(request) {
35 const body = request.body && typeof request.body === "object" && !Array.isArray(request.body) ? request.body : {}
36 const kind = pick(TYPES, text(body.type)?.toUpperCase(), null)
37 const name = text(body.monitor) ?? text(body.id)
38
39 // Guard: only Cronitor alert/recovery webhooks, which always name a monitor.
40 if (!kind || !(name || text(body.monitor_url))) {
41 console.log(`Not a Cronitor alert ("${text(body.type) ?? "unknown"}") — skipping`)
42 return null
43 }
44
45 // ?env=production only pushes alerts from that environment.
46 const env = text(body.environment)
47 const onlyEnv = text(request.query?.env)
48 if (onlyEnv && env && env.toLowerCase() !== onlyEnv.toLowerCase()) {
49 console.log(`Skipping Cronitor alert for environment "${env}" (only "${onlyEnv}")`)
50 return null
51 }
52
53 const monitor = name ?? "Your monitor"
54 const context = [text(body.group), env].filter(Boolean)
55 const buttons = [...link(body.issue_url, "View issue"), ...link(body.monitor_url, "View monitor")]
56
57 if (kind === "alert") {
58 const why = text(body.description) ?? text(body.rule) ?? "It failed a check"
59 return {
60 title: `🔴 ${monitor} failed`,
61 message: [why, ...context].join(" · "),
62 topic: "Cronitor",
63 // High — a job or site you rely on is failing. ?urgent=1 makes it Highest (2)
64 // for monitors where a failure means something is down right now.
65 priority: flag(request, "urgent") ? 2 : 1,
66 buttons,
67 }
68 }
69
70 return {
71 title: `✅ ${monitor} recovered`,
72 message: [text(body.description) ?? "It's healthy again", ...context].join(" · "),
73 topic: "Cronitor",
74 priority: -1, // Low — back to normal, nothing to do
75 buttons,
76 }
77}
Payload

The Cronitor alert webhook

This is what Cronitor sends to your URL for webhooks. It is a sample, trimmed to the fields recipes use.

alert · sample.json
1{
2 "id": "nightly-backup",
3 "rule": "job failed",
4 "type": "ALERT",
5 "group": "Backups",
6 "monitor": "Nightly backup",
7 "issue_url": "https://cronitor.io/app/issues/a1b2c3d4",
8 "description": "Job exited with status code 1",
9 "environment": "production",
10 "monitor_url": "https://cronitor.io/app/monitors/nightly-backup"
11}
FAQ

Cronitor monitor failed or recovered 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 Cronitor 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

Cronitor on your phone in two minutes.

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