Skip to content

Vitals

GET /api/v1/sites/:id/vitals

The 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.

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.

Terminal window
curl -s -H "Authorization: Bearer tk_live_…" \
"https://tracing.tools/api/v1/sites/pk_live_a91c3f04/vitals?range=7d&dimension=path&limit=3"
{
"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.

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.

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.