Monitors are the core resource. Every monitor has a top-level
monitor_type —
http, 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.5–60). 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"