Heartbeats
A heartbeat monitor is passive. Instead of kamustatus probing your service, your job calls a ping URL each time it runs. When no ping arrives within the expected period plus grace, the monitor is down and its alert rules fire. Use it for cron jobs, queue workers and anything without public ingress.
Create one
Dashboard: Monitor → project → New monitor, type Heartbeat. Set Expected period (s) (how often the job runs) and Grace (s) (how late it may be). CLI:
kamu status monitors add <project-id> --name "Nightly backup" --type heartbeat \
--interval 86400 --grace 3600
kamu status monitors show <monitor-id> # prints the ping URL
| Field | Default |
|---|---|
Expected period (--interval) | 300 s |
Grace (--grace) | 0 s |
The ping URL is shown on the monitor page and in kamu status monitors show:
https://api.kamustatus.com/ping/<token>
The token is the only credential. Anyone holding the URL can ping it, which is
harmless, so it can live in fly.toml [env].
Sending pings
Any method works. A plain GET is enough:
curl -fsS https://api.kamustatus.com/ping/<token>
Crontab, pinging only when the job succeeded:
0 3 * * * /usr/local/bin/backup.sh && curl -fsS https://api.kamustatus.com/ping/<token>
Responses:
| Status | Body | Meaning |
|---|---|---|
| 200 | {"ok": true} | Ping recorded. |
| 200 | {"ok": true, "status": "disabled"} | Monitor is paused; nothing recorded. |
| 404 | {"error": "Unknown heartbeat token"} | Wrong or deleted token. |
| 413 | {"error": "Body too large (max 1024 bytes)"} | See metrics below. |
| 400 | {"error": "Too many metric keys (max 20)"} | See metrics below. |
| 429 | {"error": "Rate limited. Next ping in Ns", "retryAfter": N} | Pinged too soon. |
Rate limit. One ping per expected period, with a floor of 10 seconds. A
monitor with the default 300 s period accepts one ping every 5 minutes; extra
pings get 429 and are not recorded. Ping once per run, not in a tight loop.
If the job runs more often than the period, lower the period.
When it goes down
The worker checks heartbeats every minute. A monitor is down when the last ping is older than expected period + grace. A new monitor that has never been pinged can go down at the next check, so send a first ping right after creating it. The alert says "No heartbeat received" or "No heartbeat within interval".
Heartbeat alerts ignore the rule's consecutive-failure count. While down, each
rule notifies again every 10 minutes; the first ping after that sends an UP.
Maintenance windows do not suppress heartbeat alerts.
Metrics in the ping body
A POST can carry a flat JSON object of numbers and strings:
curl -fsS -X POST https://api.kamustatus.com/ping/<token> \
-H "Content-Type: application/json" \
-d '{"duration_ms": 1234, "rows": 500, "result": "ok"}'
- Body at most 1024 bytes, at most 20 top-level keys.
- Only string and number values are kept. Nested objects, arrays and booleans are dropped.
- A body that is not a JSON object is stored as-is and the ping still counts.
- Only
POSTbodies are read; there is no query-string form.
Stored metrics are kept for 30 days. Read them back with
GET /api/status/monitors/<id>/heartbeat-metrics?hours=24 through the
front door (an access key with status.read).
Metric threshold rules
A metric rule compares one numeric key of each incoming ping against a threshold.
| Field | Values |
|---|---|
metricKey | A key from your ping body, e.g. duration_ms. |
operator | gt, lt, gte, lte, eq, neq |
threshold | Number. |
consecutiveTriggers | Breaching pings in a row before it fires (default 1). |
channelId | Optional. |
curl -X POST https://app.kamuhub.com/api/status/monitors/<monitor-id>/metric-alerts \
-H "Authorization: Bearer $KAMU_ACCESS_KEY" \
-H "Content-Type: application/json" \
-d '{"metricKey": "duration_ms", "operator": "gt", "threshold": 600000}'
GET on the same path lists rules; DELETE /api/status/metric-alerts/<id>
removes one. Pings without the key, or with a string value for it, are
skipped.
Current limits, so set expectations accordingly:
- A firing rule is not delivered to any channel. It is returned in the ping
response (
"alerts": ["duration_ms gt 600000 (value: 734000)"]) and, when the rule has a channel, written to the monitor's alert history asmetric_threshold. If you need to be paged, have the job check the value itself and skip the ping, so the heartbeat goes down. - The dashboard's Metric alerts section only offers the keys
response_time_msanduptime_percent, which are not heartbeat metrics. Create rules for your own keys through the API. ThekamuCLI has no metric rule commands.