# Reading a monitor's results and incidents

Every check HostTracker runs is recorded. This page shows where to read that history in the app, how it is
stored, and how an integration or AI assistant reads the same data through the API to build a summary or report.

## In the app

Open a monitor's statistics page (**Monitors** -> the monitor -> statistics, address `/sites/stats/{id}`). It shows:

- **Uptime and response-time** figures and charts for the period you select.
- **Latest incidents** - the monitor's [incidents](/incidents/what-is-an-incident/) from the last 12 months, each with
  its state (**Resolved** or **Ongoing**), cause, start and duration.
- **Recent checks** - the check log, one row per logged event, newest first. Page through it with **Newer** and
  **Older**. Switch to **Outages** to see only the outages in the selected period.

Clicking an outage opens its panel: **Started**, **Duration**, **Checks**, **Locations** and **Errors**, an **Error
breakdown**, the **Timeline** (**Detected**, **Confirmed down**, **Confirmed up**, **Recovered**), the
[**Snapshot**](/incidents/snapshots/) when one was captured, and a **Note** you can write.

For every monitor at once, use the uptime report (`/sites/uptime`) and its **Incidents** tab - see
[The account-wide uptime report](/reports/uptime-reports/).

## How results are stored

A row in the check log is a **logged event**, not always a single check:

- Consecutive checks with the same outcome are grouped into one row: within **60 minutes** by default, or within
  **5 minutes** when the monitor keeps a **full log** (`fullLog: true`, on plans that include it).
- A grouped row keeps the **latest** check's measurements and error, and counts the checks it covers (`checkCount`).
- A state change (up to down, down to up) and a maintenance change always start a new row, so transitions are never
  hidden inside a group.

That keeps long histories compact. Uptime and incident figures are computed from state changes, so they are exact
whatever the grouping.

## Read it with the API

All of these need `monitor:read`. Times are Unix seconds.

### Results (the check log)

`GET /monitor/{monitorId}/result` - one monitor, newest first. `GET /monitor/result` - across monitors (filter with
`monitor=`, `url=` or `q=`).

| Parameter | Meaning |
|---|---|
| `from`, `to` | The time window. **At most 30 days** per request; without `monitor=` on the account-wide list, at most 24 hours. A wider window answers `422 invalid_range` with `maxSpan` in seconds. |
| `state` | `up`, `down` (any-of). |
| `location` | Location ids (any-of). |
| `expand` | `metrics` (measurements and assertion results), `recheck` (what each location saw), `monitor`, `count`. |
| `sort` | Account-wide list only: `time` (default, newest first) or `monitor`. |

A result row carries `id`, `monitorId`, `at`, `durationSec`, `state`, `checkNumber`, `checkCount`, `location`,
`underMaintenance`, `error` (`type`, `code`, `message`, `description`, `codename`), `hasSnapshot`, `snapshotUrl`, and
with `expand=metrics`: `metrics`, `assertFails`, `assertEv`, `policyViolations`. `GET /monitor/{monitorId}/result/{id}`
returns one result in full detail (with `metrics` and `recheck` by default).

MCP: `list_monitor_results` (`monitorId`, `from`, `to`, `state`, `location`, `expand`).

### Incidents

`GET /monitor/incident` (whole account or a selection) and `GET /monitor/{monitorId}/incident`.

| Parameter | Meaning |
|---|---|
| `monitor`, `url` (+ `like=true`), `q` | Which monitors (account-wide list only). |
| `from`, `to` | The time window. Not capped. |
| `state` | `open`, `resolved`. |
| `severity` | `minor` (under 5 min), `major` (5-60 min), `critical` (1 hour or more). |
| `sort` | `time` (default, newest first) or `monitor`. |
| `expand` | `recheck` - the recheck that confirmed the outage: `detectedBy`, `confirmations[]` (error and locations), `unconfirmed[]` (locations that still saw it up); `monitor`; `count` (`{total, matched}`). |

`GET /monitor/incident/{id}` adds the `timeline` of check events that opened and closed it.
`GET /monitor/incident/{id}/check` lists **every failing check recorded inside the incident** (the full log), with
`expand=metrics` for measurements; it is available on plans that include the full event log and otherwise answers
`403 package_limit`.

MCP: `list_incidents` (`monitor`, `state`, `severity`, `from`, `to`), `get_incident` (`id`, `expand`).

### Up/down spans

`GET /monitor/{monitorId}/span?from=...&to=...` returns the monitor's timeline as spans: `from`, `to`, `up`,
`eventCount`, and for a down span its `incidentId` and `comment`. It is the quickest way to draw an availability
timeline.

### Uptime summary

`GET /monitor/result/summary` computes uptime, SLA and response time over a window:

| Parameter | Meaning |
|---|---|
| `monitor` | Monitor ids. Required unless `groupBy=account`. |
| `from`, `to` | The window. Always send both. |
| `bucket` | `none` (default, one total), `hour`, `day`, `week`, `month` (a series). |
| `groupBy` | `monitor` (default, a row per monitor) or `account` (one combined row; at most 30 days). |
| `sla` | An SLA target for this request, overriding each monitor's own. |
| `metrics` | `responseTime`, `dns`, `connect`, `tls`, `ttfb`, `transfer`. |
| `expand` | `incidentCounts` adds `incidents{opened, restored}`. |

A row carries `upSec`, `downSec`, `totalSec`, `maintenance{upSec, downSec}`, `downSpans`,
`checks{total, up, down, maintenanceUp, maintenanceDown}`, **`uptimePercent`**, `slaTarget`, `slaMet`,
`errorBudgetSecRemaining` and the requested `metrics`. Use `uptimePercent` as given rather than recomputing it - see
[Uptime percentage and SLA](/incidents/uptime-sla/).

MCP: `get_uptime_summary` (`monitor`, `from`, `to`, `bucket`, `groupBy`, `sla`, `metrics`).

## Build a summary for a period

A recipe for "how did my monitors do last month" - by hand, in a script or from an AI assistant:

1. **List the monitors** in scope: `GET /monitor?tag=prod` (or `list_monitors`).
2. **Get the figures**: `GET /monitor/result/summary?monitor=ID1,ID2&from=START&to=END&expand=incidentCounts&metrics=responseTime`
   - uptime %, downtime seconds, SLA met or not, incident counts and average response time per monitor.
3. **List the incidents**: `GET /monitor/incident?monitor=ID1,ID2&from=START&to=END&sort=time` - start, duration,
   severity, cause (`cause.codename`) and your comment for each.
4. **Explain the big ones**: `GET /monitor/incident/{id}?expand=recheck` shows which locations confirmed the outage
   and what they saw; `GET /monitor/incident/{id}/check` lists every failing check.
5. **Add context**: `GET /maintenance?from=START&to=END` for planned work in the period, and your status page
   announcements (`GET /statuspage/{id}/incident`).

Present durations in human units and quote uptime to the precision the summary gives. For a formatted document to
send to someone, generate a report instead: `POST /monitor/report` (a job; MCP `generate_report`) - see
[Uptime reports](/reports/uptime-reports/).

## Related

- [What is an incident](/incidents/what-is-an-incident/)
- [Uptime percentage and SLA](/incidents/uptime-sla/)
- [Page snapshots](/incidents/snapshots/)
- [Short outages recorded as long downtime](/troubleshooting/short-outages/)
