# How to Get a Cron Job Notification on Your Phone

> Use a heartbeat monitor to detect a missed scheduled run, then send one fixed down or recovery Ping to a private shared Room.

- Published: 2026-11-12
- Author: PingRoom
- Category: Automation
- Topics: cron job notification, cron job monitoring notification, scheduled task phone alert, heartbeat webhook to PingRoom
- Canonical: https://pingroom.io/blog/cron-job-phone-notifications
- Cover image: https://pingroom.io/blog/cron-job-phone-notifications-cover.webp
- Cover description: Two PingRoom avatars inspect four wooden heartbeat pendulums while Pingo watches the one that stopped.

To get a **cron job notification** when a recurring task stops running, use a heartbeat monitor to watch for an expected check-in. Let the monitor decide when the job is late, then send one fixed down or recovery message to a private PingRoom Room through its webhook.

A curl command after the job is not enough. It can report success or failure after the process exits, but it cannot report a job that never started because the scheduler, host, or container was unavailable.

PingRoom is the shared attention path in this setup. The heartbeat service remains the monitoring record.

## Choose completion or absence detection

Start with the smallest setup that covers the actual failure mode:

| What you need to know                                      | Use                                                                                        |
| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| One long command finished or failed while its shell ran    | A [post-command wrapper](/blog/notify-when-long-running-command-finishes)                  |
| A recurring task missed its expected schedule or ran late  | A heartbeat monitor with schedule and grace settings                                       |
| A critical operational path needs escalation and ownership | Your approved monitoring and on-call system; treat PingRoom as an additional shared signal |

[Healthchecks.io](https://healthchecks.io/docs/monitoring_cron_jobs/), [Cronitor](https://cronitor.io/docs/cron-job-monitoring), and [Dead Man's Snitch](https://deadmanssnitch.com/docs/monitor/cron-jobs) all document the heartbeat pattern. Use the monitor that fits your scheduler, retention needs, and existing alert process.

The worked example below uses Healthchecks.io because its custom webhooks support separate down and up request bodies. This is a custom webhook recipe, not a native Healthchecks.io integration.

## Prepare one check and one private Room

You need:

- one Healthchecks.io check for the scheduled task;
- a schedule and grace period that reflect the job's real start time and normal runtime;
- a private PingRoom Room with a [Pro incoming webhook](/features/incoming-webhook); and
- both secret URLs in protected configuration, never in a repository or a shared message.

If the task starts nightly at 01:00 and normally takes 12 minutes, do not set its expected check-in to 01:00. A practical illustrative setup is an expected check-in at 01:15 with a 10-minute grace period. Measure your own runtime and choose a margin that avoids ordinary variation without hiding a real miss.

Create or choose the private Room, then add an incoming webhook under **Settings → Connections → From another app**. PingRoom's [webhook reference](/documents/webhooks) documents the accepted fields and current limits. Treat the full webhook URL as a credential.

## Signal start, success, and failure from the job

Keep the monitor's ping URL in an environment variable. This wrapper sends a start signal, runs the command, and reports its exit status without copying command output anywhere:

```bash
#!/usr/bin/env bash
set -u

: "${HEALTHCHECKS_PING_URL:?Set HEALTHCHECKS_PING_URL}"

curl --fail --silent --show-error --max-time 10 \
  "${HEALTHCHECKS_PING_URL}/start" >/dev/null || true

/opt/reports/nightly-report
status=$?

curl --fail --silent --show-error --max-time 10 --retry 3 \
  "${HEALTHCHECKS_PING_URL}/${status}" >/dev/null || true

exit "${status}"
```

Healthchecks.io documents `/start`, success, failure, and exit-status signals in its [pinging API](https://healthchecks.io/docs/http_api/). The `|| true` clauses keep a temporary monitoring-network error from changing the task's own exit status. Decide separately whether failure to report monitoring state should be logged or handled by your existing operations tooling.

Do not append stdout, stderr, file paths, hostnames, customer records, or secret values to either webhook. A notification preview can appear on a locked screen.

![Two PingRoom avatars watch a restored wooden heartbeat pendulum beside Pingo and a single recovery token.](/blog/cron-job-phone-notifications-1.webp)

## Map down and recovery to fixed PingRoom copy

Add a custom webhook integration to the Healthchecks.io check. Use `POST`, set `Content-Type: application/json`, and use the private PingRoom webhook URL as the destination.

For the **down** body, send:

```json
{
  "title": "Scheduled job needs attention",
  "message": "Nightly report missed its expected check-in.",
  "data": {
    "source": "healthchecks",
    "state": "down",
    "job": "nightly-report"
  }
}
```

For the **up** body, send:

```json
{
  "title": "Scheduled job checking in again",
  "message": "Nightly report returned to its expected schedule.",
  "data": {
    "source": "healthchecks",
    "state": "up",
    "job": "nightly-report"
  }
}
```

Use a separate integration for each important check so the fixed `job` value cannot be replaced by unexpected input. Healthchecks.io supports variables such as `$NAME` and `$STATUS`, but fixed copy is the smaller privacy boundary here.

Healthchecks.io can retry a webhook after an ambiguous response. A direct monitor-to-PingRoom connection is therefore suitable only when an occasional duplicate is acceptable. If you need durable deduplication, source authentication beyond the secret destination URL, or a broader payload policy, put a small relay you operate between the two services.

Pingo, PingRoom's fictional CMO, considered the stopped pendulum and waited. His title gives him no access to a job, monitor, or private Room. The monitor detects the state; people decide what to do.

## Rehearse four cases before relying on it

Run a controlled test with harmless copy:

1. **Ordinary success:** run the wrapper with a command that exits `0`. Confirm the check remains up and no down Ping is created.
2. **Explicit failure:** run it with a command that exits non-zero. Confirm the monitor records the failure and the Room receives only the fixed down copy.
3. **Missed check-in:** shorten a test check's schedule, then deliberately send nothing. Confirm the monitor waits through the grace period before sending the down body.
4. **Recovery:** send the next successful check-in. Confirm the monitor returns to up and the Room receives the fixed recovery copy.

Review the monitor's event history as the source of truth. A successful webhook response means the request was accepted; it does not prove that a particular phone displayed a notification or that a person responded. Device settings, provider behavior, connectivity, and Room membership still matter.

## Keep the handoff small

The useful boundary is simple:

- the scheduler runs the task;
- the heartbeat monitor decides whether the expected signal is missing;
- PingRoom draws a small group's attention to a fixed down or recovery state; and
- a named person opens the monitor and the source system to investigate.

Do not use this as the only channel for emergencies or safety-critical operations. For an ordinary team workflow, [create or choose a private Room](/app/rooms), add its incoming webhook, and rehearse the four cases before you depend on the signal.

_Illustrations feature Pingo and fictional PingRoom avatars. The scenario is illustrative; no customer deployment or delivery result is claimed._
