API Reference

Monitors

Monitors are the core resource. Every monitor has a top-level monitor_typehttp, ping, port, heartbeat or cron — which determines the shape of the request payload and which sub-checks (SSL, DNS, domain, keyword, JSON) are allowed.

GET /monitors

List monitors for your team. Paginated.

Query Parameters

Parameter Type Description
search string Filter by URL (partial match)
status string online, offline, degraded, pending
type string http, ping, port, heartbeat, cron
interval number Filter by check interval in minutes (e.g. 0.5, 1, 5)
sort string url, status, check_interval, last_checked_at, created_at
direction string asc or desc
per_page integer Page size, max 100 (default 20)
curl "https://sentinel.rootstuff.io/api/monitors?type=heartbeat&status=online" \
  -H "Authorization: Bearer YOUR_API_TOKEN"

GET /monitors/{id}

Get a single monitor with its recent incidents and response times.

{
  "id": 1,
  "monitor_type": "http",
  "url": "https://example.com",
  "friendly_name": "My Website",
  "status": "online",
  "check_interval": 1,
  "check_types": ["ssl", "dns"],
  "monitored_regions": ["ash", "pdx", "nbg", "sin"],
  "is_paused": false,
  "last_checked_at": "2026-05-29T10:30:00Z",
  "last_heartbeat_at": null,
  "heartbeat_expected_at": null,
  "ping_url": null,
  "incidents": [...],
  "response_times": [...]
}

For heartbeat and cron monitors, ping_url is the unique URL your job should ping; last_heartbeat_at and heartbeat_expected_at are populated; and url mirrors the ping URL.

POST /monitors

Create a monitor. The request body shape depends on monitor_type.

Common Fields

Field Type Required Description
monitor_type string No (defaults to http) http, ping, port, heartbeat, cron. Plan-gated.
friendly_name string Required for push Display name. Required for heartbeat/cron; optional otherwise.
check_interval number Required for pull Minutes between checks (0.560). Not used for heartbeat/cron.
monitored_regions array No Any of ash, pdx, nbg, sin. Defaults to all.
check_types array No Sub-checks. HTTP: ssl, dns, domain, keyword, json. Ping/port: dns, domain. Heartbeat/cron: none.

Type-Specific Fields

Field Type Used By Description
url string http (URL), ping/port (host or URL) Full URL for HTTP; hostname or URL for ping/port. Generated by the server for heartbeat/cron.
port integer port (required) TCP port (1–65535).
heartbeat_interval integer heartbeat (required) Expected interval in seconds (30–2592000).
heartbeat_cron_expression string cron (required) 5-field cron expression (e.g. */5 * * * *).
heartbeat_timezone string heartbeat/cron IANA timezone (e.g. America/New_York). Defaults to UTC.
heartbeat_grace integer heartbeat/cron Grace period in seconds before a missed ping is treated as failure (0–86400, defaults to 60).

Example: HTTP monitor

curl -X POST "https://sentinel.rootstuff.io/api/monitors" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "monitor_type": "http",
    "url": "https://example.com",
    "check_interval": 1,
    "check_types": ["ssl", "dns"]
  }'

Example: Ping monitor

curl -X POST "https://sentinel.rootstuff.io/api/monitors" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "monitor_type": "ping",
    "url": "db.example.com",
    "check_interval": 1
  }'

Example: Port monitor

curl -X POST "https://sentinel.rootstuff.io/api/monitors" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "monitor_type": "port",
    "url": "db.example.com",
    "port": 5432,
    "check_interval": 1
  }'

Example: Heartbeat monitor

curl -X POST "https://sentinel.rootstuff.io/api/monitors" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "monitor_type": "heartbeat",
    "friendly_name": "Nightly Backup",
    "heartbeat_interval": 86400,
    "heartbeat_grace": 300
  }'

The response includes ping_url — the unique URL your job should hit after each successful run. Append ?status=fail to report a failed run.

Example: Cron monitor

curl -X POST "https://sentinel.rootstuff.io/api/monitors" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "monitor_type": "cron",
    "friendly_name": "Weekday Billing",
    "heartbeat_cron_expression": "30 2 * * 1-5",
    "heartbeat_timezone": "America/New_York",
    "heartbeat_grace": 300
  }'

PUT /monitors/{id}

Update a monitor. monitor_type is locked — create a new monitor instead of changing type. For heartbeat/cron, url and check_interval are ignored (the ping URL is system-owned); changes to heartbeat_interval or heartbeat_cron_expression recompute the next-expected ping time.

curl -X PUT "https://sentinel.rootstuff.io/api/monitors/1" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"check_interval": 0.5}'

DELETE /monitors/{id}

Delete a monitor and all associated data.

curl -X DELETE "https://sentinel.rootstuff.io/api/monitors/1" \
  -H "Authorization: Bearer YOUR_API_TOKEN"

# Response: 204 No Content

POST /monitors/{id}/check

Trigger an immediate check outside the normal schedule. HTTP/ping/port only — heartbeat and cron monitors are push-based and have no outbound check to trigger.

{
  "uptime": {
    "is_up": true,
    "response_time": 245,
    "status_code": 200,
    "checked_from_region": "ash"
  }
}

POST /monitors/{id}/pause

Pause monitoring. Useful during deployments. For heartbeat/cron, pausing also ignores inbound pings.

{
  "success": true,
  "message": "Monitor paused",
  "monitor": { "id": 1, "is_paused": true }
}

POST /monitors/{id}/resume

Resume monitoring after it was paused.

{
  "success": true,
  "message": "Monitor resumed",
  "monitor": { "id": 1, "is_paused": false }
}

GET / POST /ping/{token} (public, no auth)

The public ingest endpoint for heartbeat/cron monitors. Your job hits this URL when it finishes successfully — the token is the monitor's ping_url token. GET, POST and HEAD are all accepted; throttled to 120 requests per minute. Append ?status=fail to report a failed run and open an incident immediately.

# Success ping
curl -fsS "https://sentinel.rootstuff.io/ping/your-token"

# Failure ping — opens an incident
curl -fsS "https://sentinel.rootstuff.io/ping/your-token?status=fail"