Skip to main content

GET /api/vitals

Returns average Core Web Vitals scores across all $web_vital events for the given domain and optional date range. Each row represents one metric with its average value over the requested window.
Web vitals are automatically captured by the Iris SDK’s vitals.ts module via the web-vitals library. Each browser reports LCP, INP, and CLS once per page load as $web_vital events with the metric name and value stored in the p (properties) field.

How vitals are stored

Each $web_vital event carries a p (properties) object with the following keys:
Property keyDescription
$nameMetric name: LCP, INP, or CLS
$valNumeric metric value (milliseconds for LCP/INP, unitless score for CLS)
$ratingBrowser-assigned rating: good, needs-improvement, or poor
$idBrowser-generated unique ID for the measurement
The /api/vitals endpoint uses json_extract(properties, '$.$name') and AVG(CAST(json_extract(properties, '$.$val') AS REAL)) to compute averages per metric.

Query parameters

domain
string
required
The domain to query (e.g. example.com). Must match the d field sent in event payloads exactly.
from
string
Start of the date range, inclusive. ISO 8601 date string (YYYY-MM-DD). If omitted, results cover all time up to to.
to
string
End of the date range, inclusive. ISO 8601 date string (YYYY-MM-DD). If omitted, results cover all time from from.

Response

Returns a JSON array — one entry per vital metric that has data. If no $web_vital events exist for the domain, an empty array is returned.
name
string
Metric name: LCP, INP, or CLS.
value
number
Average value of the metric across all events in the window. LCP and INP are in milliseconds; CLS is a unitless decimal.
The rating field (good / needs-improvement / poor) is captured per-event by the browser and stored in each event’s properties, but the /api/vitals response only returns the average numeric value — it does not aggregate ratings. Use the value to compute the rating against standard thresholds (LCP ≤ 2500ms = good, INP ≤ 200ms = good, CLS ≤ 0.1 = good).
Response shape
[
  { "name": "LCP", "value": 1823.4 },
  { "name": "INP", "value": 112.7  },
  { "name": "CLS", "value": 0.08   }
]
StatusMeaning
200 OKQuery succeeded (empty array if no vitals data)
400 Bad Requestdomain query parameter is missing
500 Internal Server ErrorDatabase query failed

Examples

curl "https://your-iris-host/api/vitals?domain=example.com&from=2025-01-01&to=2025-01-31"

Build docs developers (and LLMs) love