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.
Authorization
Section titled “Authorization”All observability reads require the observability:read scope. write is not a
thing here — observability is read-only over the API.
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 the404-vs-403split. - 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.
Site and environment insights
Section titled “Site and environment insights”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 |
Rolling windows vs calendar windows
Section titled “Rolling windows vs calendar windows”summary, timeseries, and pages accept either window form:
days— a rolling look-back window, default30.from/to— an explicit RFC 3339 calendar window.fromis inclusive and wins overdayswhen both are supplied;tois 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.
Filter parameters
Section titled “Filter parameters”| 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) |
Account-scoped reads
Section titled “Account-scoped reads”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.
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"client := forge.New(os.Getenv("FORGE_TOKEN"))
summary, err := client.Insights.Summary(ctx, "site_01J7Q2", &forge.InsightsOptions{Days: 30})# uses the default site from your mf configmf insights summary --days 30{ "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:
mf insights summary --from 2026-06-01T00:00:00Z --to 2026-07-01T00:00:00ZWorked 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.
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"logs, err := client.Observability.TailLogs(ctx, &forge.TailLogsOptions{ Hours: 6, Limit: 200, Severity: "ERROR",})mf obs logs --hours 6 --severity ERROR --limit 200{ "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.