Vitals
GET /api/v1/sites/:id/vitalsThe same numbers the Performance screen shows: the p75 of LCP, INP, CLS, FCP and TTFB over the range, the equivalent window before it, the change between them, the per-bucket series, and, on request, one breakdown.
Parameters
Section titled “Parameters”| Parameter | Values | Default |
|---|---|---|
range |
today, yesterday, 24h, 7d, 30d, 90d, 12m, week, month |
30d |
dimension |
path, country, device, browser, os, hostname |
none |
limit |
1 to 100, rows in the breakdown |
20 |
| any filter key | none |
Only path, country, device, browser, os and hostname filters are
applied; the vitals report carries no referrer, campaign or event, so those
keys are ignored rather than emptying the result.
The range is resolved in the site’s timezone, not yours.
Request
Section titled “Request”curl -s -H "Authorization: Bearer tk_live_…" \ "https://tracing.tools/api/v1/sites/pk_live_a91c3f04/vitals?range=7d&dimension=path&limit=3"Response
Section titled “Response”{ "site": { "id": "6f2b1e7c-9a54-4f21-8c3a-1d0b7e5f4a92", "domain": "acme.com" }, "range": { "key": "7d", "start": "2026-09-10T22:00:00.000Z", "end": "2026-09-16T17:41:12.913Z", "timezone": "Europe/Berlin", "unit": "day" }, "data": { "samples": 3184, "metrics": { "lcp": { "key": "lcp", "p75": 2410, "samples": 3184, "good": 2455, "needsImprovement": 561, "poor": 168 }, "inp": { "key": "inp", "p75": 168, "samples": 2907, "good": 2310, "needsImprovement": 490, "poor": 107 }, "cls": { "key": "cls", "p75": 0.06, "samples": 3184, "good": 2801, "needsImprovement": 300, "poor": 83 }, "fcp": { "key": "fcp", "p75": 1520, "samples": 3184, "good": 2610, "needsImprovement": 470, "poor": 104 }, "ttfb": { "key": "ttfb", "p75": 610, "samples": 3184, "good": 2744, "needsImprovement": 380, "poor": 60 } } }, "previous": { "samples": 2951, "metrics": { "lcp": { "key": "lcp", "p75": 2680, "samples": 2951, "good": 2130, "needsImprovement": 620, "poor": 201 }, "inp": { "key": "inp", "p75": 181, "samples": 2688, "good": 2094, "needsImprovement": 480, "poor": 114 }, "cls": { "key": "cls", "p75": 0.07, "samples": 2951, "good": 2560, "needsImprovement": 301, "poor": 90 }, "fcp": { "key": "fcp", "p75": 1640, "samples": 2951, "good": 2360, "needsImprovement": 470, "poor": 121 }, "ttfb": { "key": "ttfb", "p75": 655, "samples": 2951, "good": 2510, "needsImprovement": 376, "poor": 65 } } }, "delta": { "lcp": -10.074626865671641, "inp": -7.182320441988949, "cls": -14.285714285714285, "fcp": -7.317073170731707, "ttfb": -6.870229007633588 }, "series": [ { "date": "2026-09-11T00:00:00", "samples": 402, "lcp": 2510, "inp": 172, "cls": 0.06, "fcp": 1580, "ttfb": 620 }, { "date": "2026-09-12T00:00:00", "samples": 0, "lcp": null, "inp": null, "cls": null, "fcp": null, "ttfb": null }, { "date": "2026-09-13T00:00:00", "samples": 611, "lcp": 2380, "inp": 160, "cls": 0.05, "fcp": 1490, "ttfb": 590 } ], "breakdown": { "dimension": "path", "rows": [ { "name": "/", "samples": 1210, "lcp": 2190, "inp": 150, "cls": 0.04, "fcp": 1380, "ttfb": 560 }, { "name": "/pricing", "samples": 640, "lcp": 2540, "inp": 171, "cls": 0.07, "fcp": 1600, "ttfb": 630 }, { "name": "/checkout", "samples": 388, "lcp": 3320, "inp": 240, "cls": 0.11, "fcp": 1910, "ttfb": 710 } ] }}The series is abbreviated; a real response has one element per bucket.
Fields
Section titled “Fields”Timings (lcp, inp, fcp, ttfb) are in milliseconds. cls is the
unitless layout-shift score.
| Field | Meaning |
|---|---|
data.samples |
Page loads in the slice that reported at least one vital |
data.metrics.<vital>.p75 |
75th percentile across the loads that reported it; null when none did |
data.metrics.<vital>.samples |
Loads that reported this vital. INP is missing on loads with no interaction |
data.metrics.<vital>.good, needsImprovement, poor |
How those loads split by rating. Thresholds are on Performance |
previous |
The same shape for the window immediately before range, or null |
delta.<vital> |
Percentage change of the p75 against previous; null when either side has no value |
series[].date |
Bucket start in the site’s timezone, no offset suffix |
series[].samples |
Loads in the bucket |
series[].<vital> |
p75 for the bucket, null when the bucket had no loads |
breakdown.rows[].samples |
Loads behind the row; rows are ranked by it |
breakdown.rows[].<vital> |
p75 for the row, null when none of its loads reported the vital |
breakdown is only present when dimension was given. range.unit is the
bucket size the series was cut in: hour, day or month.
Errors
Section titled “Errors”| Status | Body |
|---|---|
401 |
{"error":"Missing or invalid API key"} |
404 |
{"error":"site not found"} |
An unrecognised range falls back to 30d, an unrecognised dimension is
treated as absent, and limit is clamped to 1 to 100.