One filtered, sorted, paged view of every monitor on the account: HTTP checks, heartbeats and browser checks together.
const url = 'https://api.siteqwality.com/monitors';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url https://api.siteqwality.com/monitors \ --header 'Authorization: Bearer <token>'total is the size of the whole filtered set, not the length of items.
This exists because the three monitor types cannot be paged separately and
merged in the client. GET /monitors/list applies limit and offset to
http_jobs and cron_jobs independently, so limit=10 can return twenty
rows and one offset means two different things; browser checks were not in
that endpoint at all and were merged in from an unfiltered list. A client
asking for “the next page” of the combined array therefore asked for an
offset that existed in none of the three sources, got nothing back, and
concluded there was no more data while monitors it had never shown sat in
the gap.
/monitors/list is unchanged: it is a documented public API surface.
Authorizations
Section titled “Authorizations ”Parameters
Section titled “ Parameters ”Query Parameters
Section titled “Query Parameters ”http, browser or cron. Blank values select all types.
Page size. Clamped to 1..=100.
Row offset into the filtered result set.
Free-text search over name and URI.
success, failed or pending_failure.
active or paused.
Column to sort by. Unrecognized values fall back to the default order.
asc or desc. Ignored without sort_field.
Repeatable. A monitor matches when it carries every requested tag.
Responses
Section titled “ Responses ”One page of matching monitors
One server-filtered, server-sorted page of the unified monitor list.
object
One row of the unified monitor list.
Fields are emitted as explicit null rather than omitted when they do not
apply to the row’s type. The dashboard reads several of them positionally
(an absent method and a null method are not the same thing to it), and
bulk edit spreads the whole row back into an update request, so a missing
key is a silently blanked setting rather than a cosmetic difference.
object
http, cron or browser.
Display name. Browser checks store this as name; it is projected here
so one column renderer serves all three types.
success, failed or (HTTP and browser only) pending_failure.
active or paused.
Uptime percentage over the last 24h. HTTP monitors only, and null when the monitor has no checks in the window.
Notification groups, resolved in one batched query for the whole page.
object
object
object
object
object
object
object
object
object
object
Severity of trigger events sent through this notification. Defaults
to critical when the caller omits it.
object
object
object
object
object
How this channel’s recent deliveries went: whether the last alert reached anyone, and why not when it did not (a revoked Slack token, a bouncing inbox). Present on the read endpoints; absent on create and update responses.
object
healthy: the most recent delivery reached the provider.
degraded: it was refused, bounced, complained about, could not be
sent, or skipped for a reason the channel must fix (such as
sms_quota), so the next alert will likely not arrive either.
unknown: nothing sent in the lookback window.
A skip by design, such as heartbeat_channel_unsupported, is listed in
recent but never judged.
Newest first, at most [CHANNEL_HEALTH_RECENT].
One delivery, as a channel’s health shows it.
object
Sent | delivered | delayed | soft_bounced | failed | rejected | bounced | complained | skipped
The provider’s reason for a non-success status, URLs reduced to hosts.
For skipped, a slug such as sms_quota or tls_channel_unsupported.
Milliseconds. Browser checks store seconds; the value is converted so the Timeout column reads true for them instead of blanking.
Explicitly null for heartbeats and browser checks. The dashboard’s legacy “no method means heartbeat” heuristic still exists as a fallback, so this must be present and null rather than omitted.
True when a basic-auth password or bearer token is stored for this
monitor. The credentials themselves are write-only and are deliberately
absent from this struct, so there is nothing here for a read-only
viewer, a scoped API key, an M2M client or a read-only impersonation
session to read back. See crate::model::api::secrets.
Bulk edit spreads a row back into an update request, and the update
statement writes COALESCE($n, auth_password), so an absent key leaves
the stored credential alone. That is why these two can be dropped from
the shape outright rather than emitted as null.
Names and allowlisted metadata values; other values become secrets::REDACTED.
Sending the placeholder back on an update keeps the stored value.
Browser check cadence label (5m, 10m, 15m, 30m, 1h).
Number of monitors matching the filters, across every page. This is
what “X-Y of N” is built from; it is not the length of items.
Example
{ "items": [ { "monitor_type": "http", "not_checked_reason": "quota", "group_notifications": [ { "notifications": [ { "type": "email", "details": { "pagerduty_severity": "critical" } } ] } ], "content_type": "json", "auth_type": "basic", "http_version": "auto" } ]}Invalid monitor_type query parameter
Missing or invalid authentication
Internal server error