Everything you need to wire your first cron job in under five minutes. The HTTP API is intentionally tiny — three endpoints — so you can integrate from any language without an SDK.
Concepts
A monitor is one scheduled job you want to watch. Every monitor has a UUID — that UUID is also the secret in its ping URL. Treat it as a credential.
Monitors transition through four states:
Ping API
Three endpoints, all accept GET, POST, and HEAD. POST lets you attach up to 10KB of captured output (stdout/stderr) — anything past 10KB is truncated, not rejected.
POST /ping/<uuid> — heartbeat
The simplest case. Tells us "the job ran successfully right now".
Equivalent to POST /ping/<uuid>/success.
curl -fsS -m 10 --retry 5 https://cronheart.com/ping/<uuid>
POST /ping/<uuid>/start — run started
Send before the job runs. Lets us track duration and surface "job
stuck" warnings if a /start isn't followed by a
terminal event within the grace period.
POST /ping/<uuid>/success — run finished cleanly
Send when the job exits 0. Pair with /start to get a
duration column on the dashboard.
POST /ping/<uuid>/fail — run errored
Send when the job exits non-zero. Drives alert delivery immediately — no need to wait for the next scheduled window.
Bash recipe with start + result reporting
UUID=<your-monitor-uuid>
BASE=https://cronheart.com/ping/$UUID
curl -fsS -m 10 --retry 3 "$BASE/start"
if /usr/bin/php /app/bin/console hourly:rollup; then
curl -fsS -m 10 --retry 3 --data-binary @<(tail -c 8000 ./run.log) "$BASE/success"
else
curl -fsS -m 10 --retry 3 --data-binary @<(tail -c 8000 ./run.log) "$BASE/fail"
fi
Schedule formats
Pick whichever matches how you actually run the job:
- Cron — standard 5-field expression
(
*/5 * * * *). UI shows the next 5 runs as you type. - Interval — "every N seconds" / "every N minutes" / "every N hours". Use this when you don't want to think in cron for "run every 6 hours".
- Simple — daily at HH:MM, hourly at MM, etc. Best for non-developers who configure monitors via the UI.
Alerts & channels
An alert fires the moment a monitor transitions to late
or down — no fixed-window batching, so the
time-to-page is "the scanner sweep that detected it" (≤ 30 s) plus
the channel transport latency. Anti-flap dedupe makes sure a
recovering job doesn't double-page you.
Configure channels per project. Currently supported:
- Email (default)
- Telegram bot (set up via
/startwith the bot) - Slack incoming webhook
- Discord incoming webhook
- Generic webhook with HMAC-SHA256 signature
Status badges
Every monitor exposes a public read-only SVG at
/badge/<uuid>.svg. Drop it into your README to
show the world your nightly-rollup is healthy.

The badge URL is the only public surface that exposes the monitor UUID. We deliberately don't expose ping metadata in the badge — only the colour-coded status — so a stolen badge URL can't be replayed as a ping.
Changelog
Coming soon — weekly release notes will live here.
Privacy & security
Monitor UUIDs are treated as per-monitor secrets and never logged at INFO+ on the request path. Audit logs (login, failed logins, impersonation, admin actions) live in a dedicated channel and rotate daily. Email and pings transit over TLS only.
Terms
Standard SaaS terms apply. Replace this page with your final legal copy before launch.