Skip to content
Pingwell

Heartbeat pings

A heartbeat expects a ping at least once per period. If none arrives within the period it goes late; once the grace has passed as well it goes down, and your channels hear about it. The URL is the credential: anyone with it can ping, so keep it out of public logs.

Endpoints

Every endpoint accepts GET and POST, needs no authentication, and never redirects.

Request Meaning
/p/<key> The run succeeded.
/p/<key>/start A run started. A later success or failure ends it and records its duration.
/p/<key>/fail The run failed: the heartbeat goes down at once.
/p/<key>/<code> The run ended with this exit code, 0 to 255. 0 is a success; anything else is a failure.

Add ?rid=<run id> to tie a start to its end when runs overlap. A run id is 1 to 64 of A-Z a-z 0-9 . _ : -.

A POST body is kept with the ping: the first 10 KB of up to 100 KB, shown on the heartbeat’s page. Send the tail of your job’s log and you will know why it failed without logging in to the server.

Responses

Plain text, never cached:

Status Body Meaning
200 OK Recorded.
400 an explanation The run id is malformed.
404 not found No heartbeat has this key, or the path is not a ping URL.
413 too large The body is over 100 KB.
429 rate limited Too many pings for this key; Retry-After says when to try again.

Examples

curl

# At the end of a script
curl -fsS -m 10 --retry 3 https://<your ping host>/p/<key> > /dev/null

crontab

A crontab entry is one line, run by /bin/sh. Put the job and its report in a small script:

#!/bin/sh
# /usr/local/bin/backup-and-report.sh: report the exit code, with the end of the log as the body
/usr/local/bin/backup.sh > /tmp/backup.log 2>&1
code=$?
tail -c 10000 /tmp/backup.log | curl -fsS -m 10 --retry 3 --data-binary @- "https://<your ping host>/p/<key>/$code" > /dev/null
0 3 * * * /usr/local/bin/backup-and-report.sh

Start and finish

RID=$(date +%s)
curl -fsS -m 10 "https://<your ping host>/p/<key>/start?rid=$RID"
./long-job.sh
code=$?
curl -fsS -m 10 "https://<your ping host>/p/<key>/$code?rid=$RID"

GitHub Actions

jobs:
  nightly:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: ./scripts/nightly.sh
      - name: Report to Pingwell
        if: always()
        run: |
          if [ "${{ job.status }}" = "success" ]; then path=""; else path="/fail"; fi
          curl -fsS -m 10 --retry 3 "https://<your ping host>/p/${{ secrets.PINGWELL_PING_KEY }}$path"