Skip to content

Heartbeats

A heartbeat watches a job that should run on a schedule. Your cron job, backup or script calls a private URL after each run. If a call is late, PingLoom sends an alert to your team, and tells you when the job is back.

Create a heartbeat

Open a project, then Heartbeats, then New heartbeat. Pick how often the job should check in and a grace period, which is how late a ping may be before PingLoom alerts. The grace period should be longer than the job normally takes to run. Alerts go to the channel you choose.

PingLoom shows the ping URL once. Store it where the job can read it, such as an environment variable called HEARTBEAT_URL. If you lose it, rotate the URL on the heartbeat page: the old URL stops working right away.

Careful: Anyone with the URL can send pings for that heartbeat. Keep it out of your repository, browser code and mobile apps.

Call it from your job

Ping after the job succeeds. GET and POST both work, so use whichever your tool can send. A POST body is optional; the first 1 KB is kept in the ping history to help you debug.

crontab
# Run the backup at 02:00, ping only if it succeeded
0 2 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 --retry 3 "$HEARTBEAT_URL" > /dev/null

You can also report the start and a failure. /start records that a run began, and /fail raises a high-priority alert immediately instead of waiting for the schedule.

shell
curl -fsS -m 10 "$HEARTBEAT_URL/start"
/usr/local/bin/backup.sh \
  && curl -fsS -m 10 "$HEARTBEAT_URL" \
  || curl -fsS -m 10 "$HEARTBEAT_URL/fail"

When alerts fire

  • Late, then down. A check that misses its due time is Late. Once the grace period also passes, it is Down and PingLoom sends one alert at high priority. Further missed periods during the same outage do not send more alerts.
  • Never pinged. A new heartbeat that gets no ping within its first period plus grace goes Down too.
  • Recovered. The next successful ping sets it Up and sends an alert that it is back.
  • Failure. A call to /fail alerts at once, unless an alert is already open.
  • Paused. A paused heartbeat sends no alerts. Pings are still recorded. Resume it to start a fresh period.

Alerts are normal events: they show up in your inbox and on your phones through the same push route as any other event. Pings do not count toward your monthly event quota. The alerts they cause do.

API reference

Ping endpoints

GET|POST /v1/heartbeats/{token}, /start and /fail. There is no Authorization header: the token in the path is the credential. Each returns 200 with {"ok": true}. An unknown or rotated token returns 404, with no hint about what was wrong. Too many calls return 429 with a Retry-After header.

Management endpoints

These need a signed-in user session. Owners and admins can change heartbeats; members can read them. API keys cannot manage heartbeats.

  • POST /v1/projects/{project_id}/heartbeats: create. Returns 201 with the heartbeat and the one-time ping_url.
  • GET /v1/projects/{project_id}/heartbeats: list.
  • GET /v1/projects/{project_id}/heartbeats/{heartbeat_id}: one heartbeat with its recent pings.
  • PATCH the same path: change the name, period, grace or channel.
  • POST .../pause and POST .../resume.
  • POST .../rotate-token: new ping_url, shown once.
  • DELETE the same path.
Create request
{
  "name": "Nightly backup",
  "period_seconds": 86400,
  "grace_seconds": 900,
  "channel_id": "01J9ZQ8M3K7W4X2B6N5T0R1VCD"
}

Create response
{
  "heartbeat": { "id": "01J9ZQ9...", "name": "Nightly backup", "status": "new", "...": "..." },
  "ping_url": "https://api.example.com/v1/heartbeats/hb_...",
  "curl_example": "curl -fsS -m 10 --retry 3 \"https://api.example.com/v1/heartbeats/hb_...\""
}

Limits

  • The number of heartbeats depends on your plan. Creating more returns 409 with the code PLAN_LIMIT_REACHED.
  • The period is 1 minute to 366 days and the grace period 0 to 7 days. Cron-style schedules are coming soon.
  • Each ping URL accepts 60 calls a minute, and each IP address a few hundred.
  • The ping history keeps the latest 100 calls per heartbeat.