Skip to content

Observability

The observability resource exposes the same insights you see in the dashboard — Core Web Vitals summaries, timeseries, page breakdowns, logs, traces, resource metrics, and the per-request ledger — as read-only API endpoints. Every insights view exists twice, per site and per environment; a set of rollups is account-scoped. Everything here is gated by a single scope, observability:read, and row-level reads respect the same PII hard-cut the UI does.

For the data model behind these reads — what a trace, a request row, or web vitals mean — start with observability overview. This page is the API reference for fetching that data programmatically.

All observability reads require the observability:read scope. write is not a thing here — observability is read-only over the API.

observability:read

Tenancy is enforced two ways depending on the route:

  • Site- and env-scoped reads load the resource first, so an out-of-scope site or environment returns 404 (existence hiding). See errors for the 404-vs-403 split.
  • Account-scoped reads (/v1/logs, /v1/traces, /v1/metrics, /v1/usage/storage) are loaderless — there is no resource in the path to load, so tenancy is resolved inside the handler from your principal. A key’s resource constraint is honored here too: if the key is pinned to a site, these rollups are intersected down to only what that key may see.

Every view below lives at GET /v1/sites/{siteID}/insights/… and has an identical environment twin at GET /v1/sites/{siteID}/environments/{envID}/insights/…. These reads are windowed, not cursor-paginated — you bound them with a time window and a limit rather than walking a cursor.

Path (…/insights/) Returns Window
summary Core Web Vitals rollup — RUM percentiles per metric + server timing days or from/to
timeseries one metric over time (p75/p90/p95 per bucket) days or from/to
pages per-page breakdown with samples, p75, and a rating days or from/to
logs application log lines hours
logs/volume log counts bucketed over time, by severity hours
traces request trace spans (sampled per site/plan) hours
traces/{traceID} one trace, span by span
resources container CPU/memory/network + app request/error/latency series hours
requests the per-request ledger hours
requests/volume request totals and errors bucketed over time hours

summary, timeseries, and pages accept either window form:

  • days — a rolling look-back window, default 30.
  • from / to — an explicit RFC 3339 calendar window. from is inclusive and wins over days when both are supplied; to is exclusive and defaults to now. Calendar windows make a report reproducible — “the month of June” returns the same numbers next week.

The row-level views (logs, traces, requests, resources) take an hours look-back instead.

View Parameters
timeseries, pages metric — the Core Web Vital to chart (LCP default, FCP, CLS, INP, TTFB)
logs hours (default 24, max 720) · limit (default 1000, max 5000) · severity (OTel severity_text, e.g. ERROR) · container · q (free-text over the body) · trace_id (correlate one request’s logs)
logs/volume hours · severity
traces hours · status=error (failed traces only) · min_duration_ms · service · limit (default 200, max 2000)
requests hours (default 24, max 4320) · method · status (a status or status class) · q (free-text over the path) · limit (default 500, max 2000)
resources hours (default 6, max 360)

These roll telemetry up across everything your key can see, with no site in the path.

Method + path Returns
GET /v1/logs recent log lines across your sites (hours, limit, severity)
GET /v1/logs/volume log counts bucketed over time (hours, severity)
GET /v1/metrics a metric series across your sites — name is required (hours, limit)
GET /v1/traces recent trace spans across your sites (hours, limit)
GET /v1/usage/storage storage usage per site — pass latest=true for a current-usage snapshot instead of the 30-day series
GET /v1/teams/{teamID}/insights/summary the team’s Core Web Vitals rollup

Worked example — a Core Web Vitals summary

Section titled “Worked example — a Core Web Vitals summary”

Fetch the RUM rollup for a site over the last 30 days.

GET the insights summary
curl "https://api.managed.dev/v1/sites/site_01J7Q2/insights/summary?days=30" \
-H "Authorization: Bearer mfk_live_9aF2…" \
-H "Forge-Version: 2026-06-23"
Response
{
"data": {
"rum": [
{ "metric": "LCP", "p75": 1840, "p90": 2620, "p95": 3110, "p99": 5040, "samples": 48210 },
{ "metric": "CLS", "p75": 0.02, "p90": 0.05, "p95": 0.09, "p99": 0.21, "samples": 48210 },
{ "metric": "INP", "p75": 96, "p90": 180, "p95": 240, "p99": 410, "samples": 47105 },
{ "metric": "TTFB", "p75": 210, "p90": 340, "p95": 460, "p99": 890, "samples": 48210 }
],
"server": { "p75_ttfb_ms": 88, "p95_ttfb_ms": 240, "cache_hit_pct": 93.4, "samples": 512400 },
"days": 30
},
"request_id": "req_01J9AB"
}

rum is an array of per-metric summaries — one entry per Core Web Vital, each with p75/p90/p95/p99 and its samples count. For a reproducible monthly report, swap days for a calendar window:

The month of June, exactly
mf insights summary --from 2026-06-01T00:00:00Z --to 2026-07-01T00:00:00Z

Worked example — pull recent errors across every site

Section titled “Worked example — pull recent errors across every site”

The account-wide log tail is the fastest way to answer “is anything broken right now?” without naming a site.

Errors across all sites, last 6 hours
curl "https://api.managed.dev/v1/logs?hours=6&severity=ERROR&limit=200" \
-H "Authorization: Bearer mfk_live_9aF2…" \
-H "Forge-Version: 2026-06-23"
Response
{
"data": {
"hours": 6,
"lines": [
{
"ts": "2026-07-04T09:11:03.221Z",
"site_id": "site_01J7Q2",
"severity_text": "ERROR",
"body": "db timeout after 5000ms",
"container": "app",
"service_name": "frankenphp"
}
]
},
"request_id": "req_01J9AC"
}

To zoom in from an account-wide line, take its site_id to GET /v1/sites/{siteID}/insights/logs and correlate with ?trace_id= — the site-level view carries the trace_id and structured attributes the rollup omits.