Documentation

Heartbeat ping endpoint

The endpoint

GET  https://<your-whatping-host>/monitor/ping/<token>
POST https://<your-whatping-host>/monitor/ping/<token>

Both methods behave identically. No headers, no body, no authentication beyond the token in the path.

The exact URL is shown once, when you create the heartbeat monitor.

Responses

Status Body Meaning
200 {"ok":true} Ping recorded
404 {"ok":false} Unknown token

The response is deliberately uniform and detail-free. A 404 does not say whether the token is malformed, expired or simply wrong, so the endpoint cannot be used to enumerate or probe monitors.

Tokens longer than 128 characters are rejected without a lookup.

The token

Generated when the monitor is created and shown once. It is stored hashed, in the same way as an API key, so it cannot be recovered — only rotated, which invalidates the previous one immediately.

Where to call it

Only on success, at the end of the happy path. Never in a finally, a trap, or an always() step — that reports “I ran”, when what you meant was “I worked”.

cron

0 3 * * * /usr/local/bin/backup.sh && curl -fsS "$WHATPING_PING_URL"

&& means a failing backup does not ping. -f makes curl fail on HTTP errors, -sS keeps it quiet unless something goes wrong — so cron emails you only on a genuine problem.

Bash script

#!/usr/bin/env bash
set -euo pipefail

pg_dump mydb | gzip > /backups/mydb-$(date +%F).sql.gz
aws s3 cp /backups/mydb-$(date +%F).sql.gz s3://backups/

curl -fsS --retry 3 --max-time 10 "$WHATPING_PING_URL"

With set -e, reaching the last line means everything before it succeeded. --retry 3 covers a transient network failure on the ping itself — the endpoint is idempotent, so a retry is safe.

systemd

[Service]
Type=oneshot
EnvironmentFile=/etc/whatping.env
ExecStart=/usr/local/bin/backup.sh
ExecStartPost=/usr/bin/curl -fsS --retry 3 ${WHATPING_PING_URL}

ExecStartPost runs only if ExecStart succeeded. Keep the URL in an EnvironmentFile with mode 0600, not in the unit.

GitHub Actions

- name: Run nightly sync
  run: ./scripts/sync.sh

- name: Report success
  if: success()
  run: curl -fsS --retry 3 "${{ secrets.WHATPING_PING_URL }}"

if: success(). Not if: always().

Docker / Kubernetes CronJob

command: ["/bin/sh", "-c"]
args:
  - |
    set -e
    /app/run-job
    curl -fsS --retry 3 "$WHATPING_PING_URL"
env:
  - name: WHATPING_PING_URL
    valueFrom:
      secretKeyRef: { name: whatping, key: ping-url }

Python

import requests

run_the_job()                                   # raises on failure
requests.get(PING_URL, timeout=10)              # only reached on success

Node

await runTheJob();                              // throws on failure
await fetch(process.env.WHATPING_PING_URL);

Timing

The deadline is expected interval + grace. A job that pings hourly with a 5-minute grace is overdue at 65 minutes past the last ping.

A monitor that has never been pinged is measured from when it was created, so a heartbeat that was configured but never wired up will eventually alert rather than sitting quiet forever.

Idempotency

Pinging more often than expected is harmless — extra pings simply reset the deadline. A job that retries internally and pings twice does not create a problem.