# Heartbeat — Cron Monitoring

> Are your cron jobs running? Heartbeat watches for you

Dead man's switch for cron jobs and background processes. Each heartbeat has a unique ping URL — if the ping doesn't arrive within the expected time, status changes to "down".

## Features

- **Dead man's switch**: Heartbeat expects a ping at a set interval. No ping = alarm. Simple and reliable principle.
- **Unique ping URLs**: Each heartbeat generates a token (hb_*). Your cron job pings GET or POST to /hb/{token}.
- **Period + grace**: Expected interval (period) + additional tolerance (grace) for network delays and clock drift.
- **Three statuses**: pending (no pings), up (pinged on time), down (deadline exceeded). Status computed on-demand.
- **50 per project limit**: Enough even for complex systems with many scheduled tasks.
- **Edit without losing history**: Change name, period, or grace without resetting last ping and status.

## How it works

1. **Create a heartbeat**: Set a name (e.g., "Nightly backup"), expected interval (e.g., 60 min), and grace (e.g., 5 min).
2. **Copy the ping URL**: System generates a unique URL: /hb/hb_abc123xyz. Shows example cURL and crontab configuration.
3. **Add ping to your cron job**: At the end of your script add: curl -s https://your-instance/hb/hb_abc123xyz
4. **Monitor status**: Dashboard shows status: green (up), red (down), gray (pending). Sidebar badge counts "down" heartbeats.

## AI and MCP

Your AI agent can check heartbeat statuses, create new ones, and modify configuration — 5 MCP tools.

- `list_heartbeats`: All heartbeats with computed status
- `get_heartbeat`: Details with ping URL, period/grace, status
- `create_heartbeat`: New heartbeat with name, period, and grace (in minutes)
- `update_heartbeat`: Change name, period, or grace
- `delete_heartbeat`: Remove heartbeat

## Technical details

- **Token**: Format hb_ + 16 chars URL-safe base64. Unique across the database.
- **Status**: Computed on-demand: elapsed_time = now - last_ping_at. If elapsed > period + grace → down.
- **Ping endpoint**: GET/POST /hb/{token}. Public endpoint — no auth required. Updates last_ping_at.
- **Storage**: period and grace stored in seconds in DB, converted to/from minutes in UI.
