Pulse heartbeat API

The public ping endpoint: methods, responses, states and rate limits.

One endpoint, two methods. It is deliberately boring: no auth header, no SDK, no payload required. The token in the path is the credential.

POST /api/v1/ping/{token}

Ingests a heartbeat. Optional JSON body is stored with the ping and appears in the monitor detail. Returns 202 Accepted.

curl -X POST https://api.pingops.cloud/api/v1/ping/<token> \
  -H 'Content-Type: application/json' \
  -d '{"job":"nightly","rows":18422,"duration_s":41}'
{
  "ok": true,
  "monitor": "nightly-backup",
  "status": "healthy",
  "queued": true
}

GET /api/v1/ping/{token}

Same ingestion, no body, returns 200. This exists because cron lines, wget in a minimal container and uptime scripts in shell all prefer GET, and forcing a POST means writing a wrapper.

States

  • healthy — a ping arrived within the interval.
  • late — the interval elapsed, still inside the grace period. No alert yet.
  • down — grace period elapsed with no ping. Alert fires.
  • paused — monitoring suspended; pings are accepted and recorded but do not change the state.

The transition to down happens on a 30-second ticker, so detection is interval + grace + at most 30 seconds.

Response codes

  • 200 / 202 — accepted. queued=true means it is in the Redis buffer; the worker flushes to Postgres every few seconds.
  • 404 — unknown token. A deleted monitor returns this too.
  • 429 — rate limit exceeded for this token.

Ping from anything

# crontab
0 3 * * * /usr/local/bin/backup.sh && curl -fsS https://api.pingops.cloud/api/v1/ping/<token>

# GitHub Actions, last step
- name: heartbeat
  run: curl -fsS https://api.pingops.cloud/api/v1/ping/${{ secrets.PULSE_TOKEN }}

# systemd OnSuccess
[Service]
ExecStartPost=/usr/bin/curl -fsS https://api.pingops.cloud/api/v1/ping/<token>
Something missing? Write to support and it gets added here.