---
title: "Get the monitor detail page's analytics panel data for a check"
method: GET
path: "/api/v1/checks/{id}/analytics"
tags: ["Checks"]
---

# Get the monitor detail page's analytics panel data for a check

`GET /api/v1/checks/{id}/analytics`

## Request

- Base URL: `https://app.lastping.dev`
- URL: `https://app.lastping.dev/api/v1/checks/{id}/analytics`
- Auth: API key in header `X-Api-Key`

The response shape **forks entirely on `monitor_type`**, matching
the dashboard detail page's own fork: an `http` monitor has no
run-duration baseline (it has no "run" at all — just probes), and a
`heartbeat`/`ci` monitor has no probe-derived uptime, so the two
kinds never carry each other's fields.

- `kind: "http"` — 90-day probe-derived uptime (`uptime_90d`, null
  when the monitor has no probe results at all in the window — a
  real gap, never coerced to a percentage) and up to 30 recent
  latency samples, oldest first.
- `kind: "runs"` — the run-duration baseline (`baseline`: the
  archived one when the monitor has an archived day, else a `live`
  one from its measured runs in the last 30 days once there are at
  least 5; null before either exists) and a
  week-over-week trend sentence (`trend`, null unless both the
  last-7-days and prior-7-days windows have at least 3 measured runs
  each — below that a percentage change is noise dressed as a fact).

404 if the check does not exist in the authenticated project (no
existence oracle).

**Console stability note.** This response is shaped by a console screen:
the fields are the ones that screen draws, in the grouping it draws them
in. It stays published because reading it is a reasonable thing to
automate, and no field will be removed or change meaning without a
version. Fields may be ADDED as the screen grows, so treat unknown keys
as normal rather than as an error.

## Response `200`

Analytics for this check, shaped by monitor_type.

- union
  - AnalyticsHttp: The `GET /api/v1/checks/{id}/analytics` shape for an `http` monitor.
    - `kind` 'http', required
    - `uptime_90d` string, nullable, required: Percentage over the trailing 90 days, formatted to two decimal places. Null when the monitor has recorded no probe results at all in the window — a real gap, never coerced to "0.00%" or "100.00%".
    - `latency` object[], required: Up to 30 most recent probe samples, oldest first.
      - `at` string, date-time, required
      - `ms` integer: Omitted (not null, not zero) when this probe recorded no latency at all — e.g. a connection that never completed.
      - `up` boolean, required
  - AnalyticsRuns: The `GET /api/v1/checks/{id}/analytics` shape for a `heartbeat`/`ci` monitor.
    - `kind` 'runs', required
    - `baseline` object, nullable, required: What a normal run of this monitor costs. Null when the monitor has no archived day and fewer than 5 measured runs in the last 30 days.
      - `typical_ms` integer, required
      - `days` integer, required: How many archived days the baseline was computed over; 0 when `source` is `live`.
      - `source` 'archived' | 'live', required: `archived`: the median of the monitor's archived daily medians (up to its last 30 archived days). `live`: the monitor has no archived day yet, so this is the median duration of its measured runs in the last 30 days, of which there are `runs` (at least 5). An archived baseline wins whenever one exists.
      - `runs` integer, required: How many measured runs a `live` baseline was computed from; 0 when `source` is `archived`.
    - `trend` object, nullable, required: Null unless both the last-7-days and the prior-7-days windows have at least 3 measured runs each — below that, a percentage change is noise dressed as a fact.
      - `sentence` string, required
      - `current_ms` integer, required
      - `prior_ms` integer, required

## Other responses

- `400`: id is not a valid UUID.
- `401`: Missing or invalid API key.
- `404`: Check not found in this project (`MONITOR_NOT_FOUND`).
- `429`: Too many requests. The per-principal fixed-window rate limit has been exceeded. Retry after the number of seconds indicated by the `Retry-After` response header. The problem body's `code` is `RATE_LIMITED`. It names this limiter specifically, so a client can tell it apart from the application-level throttles that also answer 429 with their own codes and their own, much longer, `Retry-After` values (`TEST_PING_RATE_LIMITED`, `TOO_MANY_ATTEMPTS`). Back off globally on `RATE_LIMITED`; back off on the one operation for the others. The principal is the API key for a key-authenticated request and the USER for a browser session, so every tab one person has open shares one budget.

---

[API](https://skmtc.dev/lastping/apis/lastping-management-api.md) · [All operations](https://skmtc.dev/lastping/apis/lastping-management-api/llms.txt) · [OpenAPI document](https://skmtc.dev/lastping/apis/lastping-management-api/revisions/bbc6eda91c46?raw)
