---
title: "Org dashboard-grain content analytics (usage, staleness, connection health)."
method: GET
path: "/v1/orgs/{orgId}/analytics/content"
tags: ["dashboards"]
---

# Org dashboard-grain content analytics (usage, staleness, connection health).

`GET /v1/orgs/{orgId}/analytics/content`

## Request

- Base URL: `http://localhost:8080`
- URL: `http://localhost:8080/v1/orgs/{orgId}/analytics/content`
- Auth: one of:
  - API key in cookie `dvt_session`
  - HTTP bearer

Which dashboards are used or stale, and whether connections are healthy — a
dashboard-grain sibling to `GET /v1/orgs/{orgId}/analytics/performance`
(element-grain) (DVT-1217). Admin or owner only (audit:read). The `data`
object shape is frozen — field names are a client contract.

Query-derived numbers (`dashboards[].renders/runs/errorCount`,
`connections[]`, and the all-time last-render signal folded into
`staleness`/`dashboards[].lastViewedAt`) see at most 365 days of
`query_executions` retention (QUERY_TELEMETRY_RETENTION_DAYS, default
365) — "never rendered" means "no render on record" within that window,
not "never rendered, ever." `dashboard_views` (the `viewsSource=events`
signal) is likewise retained 365 days.

`viewsSource` is `"events"` when this org has at least one `dashboard_views`
row in the window (checked before `actorType`/`dashboardId` narrowing),
else `"derived"` (view/viewer counts are approximated from
`query_executions` dashboard-render rows instead).

The `staleness` and `connections` sections honor **only** the `days`
filter — narrowing by `actorType`/`connectionId`/`dashboardId` would make
"stale" or "unhealthy" a lie for a dashboard/connection that is actually
busy outside the narrowed slice. `dashboards[].views`/`viewers` honor
`actorType` + `dashboardId` but never `connectionId` (`dashboard_views` has
no connection concept); `dashboards[].renders/runs/errorCount` honor all
three filters.

## Query parameters

- `days` integer
- `connectionId` string, uuid
- `dashboardId` string, uuid
- `actorType` 'user' | 'api_key' | 'agent'

## Response `200`

Org content-analytics result.

- object
  - `data` OrgAnalyticsContent, required: Dashboard-grain content analytics for a single organization over a rolling window (DVT-1217) — which dashboards are used or stale, and whether connections are healthy. All field names are a frozen client contract.
    - `rangeDays` integer, required: The requested window in calendar days (echo of the clamped `days` param).
    - `generatedAt` string, date-time, required: RFC3339 UTC timestamp when this result was assembled.
    - `viewsSource` 'events' | 'derived', required: `"events"` when this org has at least one `dashboard_views` row in the window (checked before `actorType`/`dashboardId` narrowing); else `"derived"` (view/viewer counts are approximated from `query_executions` dashboard-render rows instead).
    - `dashboards` ContentDashboard[], required: Up to 50 of the org's live dashboards with at least one render or view in the window, descending by renders then views.
      - `dashboardId` string, required: Dashboard UUID.
      - `title` string, required: Dashboard title, or empty string when untitled.
      - `renders` integer, required: Distinct dashboard-render request_ids in the window, honoring all three filters.
      - `runs` integer, required: Total dashboard-render query_executions rows in the window (the errorCount denominator), honoring all three filters.
      - `errorCount` integer, required: Of `runs`, those with status IN ('error','timeout').
      - `views` integer, required: dashboard_views count in the window; honors actorType + dashboardId, never connectionId (no connection concept).
      - `viewers` integer, required: Distinct viewing actors in the window — from dashboard_views when viewsSource='events', else from query_executions.
      - `lastViewedAt` string, date-time, nullable, required: The later of the last dashboard_views row and the last query_executions render, null-safe; null when neither is on record. On the leaderboard every row has in-window activity, so window and all-time coincide; inventory rows are always all-time.
      - `lastEditedAt` string, date-time, nullable, required: The dashboard's latest audit_logs create/update event timestamp (all-time, not window-scoped), or null when none is on record.
      - `lastEditedBy` string, required: Latest editor's display_name, else email, else 'unknown'; empty string when no edit history.
      - `lastEditedByType` string, required: Latest edit's actor_type; empty string when no edit history.
      - `createdAt` string, date-time, required: The dashboard's creation timestamp.
      - `favorites` integer: DVT-1499: user_favorites count for this dashboard, all time (additive; not part of the original DVT-1217 contract).
      - `openComments` integer: DVT-1499: dashboard_comments top-level threads with resolved_at IS NULL, all time (live rows only).
      - `totalComments` integer: DVT-1499: dashboard_comments top-level threads regardless of resolution, all time (live rows only).
      - `lastEditMethod` 'human' | 'agent' | 'system' | '': DVT-1499/DVT-1522: how the latest audit_logs create/update event was made — 'human' (actor_type='user'), 'agent' (any other non-system actor_type), 'system', or "" when no edit history exists. Independent of `lastEditedByType`, which reports the raw actor_type only.
      - `lifecycle` 'healthy' | 'stale' | 'never' | 'zombie': DVT-1499: 'healthy' (active in the requested window), 'stale' (all-time activity on record, none in-window), 'never' (no render or view ever on record), or 'zombie' (never rendered/viewed, but edited within the last 14 days — mirrors the needsAttentionContentHygiene zombie definition). Deliberately disjoint from `staleness.staleCount`/`neverCount` below, which overlap (a 'never' dashboard trivially has zero window activity too) — this field does not replace `staleness`.
      - `viewsDaily14` integer[]: DVT-1499: dashboard_views count per day for the last 14 fixed UTC calendar days (today last), always exactly 14 entries, zero-filled where absent. Independent of the requested `days` window.
      - `folder` string: DVT-1499: this dashboard's folder name, or the synthetic literal `"Unfiled"` when it has no folder_id — same resolution used by `folders[].folder` and `shelfMap[].folder` below, so all three surfaces agree.
    - `folders` object[]: DVT-1499: per-folder rollups over the requested window (additive; not part of the original DVT-1217 contract). Unfoldered dashboards roll up under the literal folder name "Unfiled". Sorted alphabetically by folder name.
      - `folder` string, required: Folder name, or the literal "Unfiled" for unfoldered dashboards.
      - `dashboards` integer, required: Count of live dashboards in this folder.
      - `views` integer, required: Summed dashboard_views in the window across this folder's dashboards.
      - `edits` integer, required: Summed audit_logs create/update events in the window across this folder's dashboards.
      - `staleShare` number, required: Of this folder's dashboards, the share (0..1) with lifecycle IN (stale, never, zombie) — i.e. at-risk. 0 when the folder has no dashboards.
      - `agentShare` number, required: DVT-1522: of this folder's `edits`, the share (0..1) attributed to a non-user actor_type (agent). 0 when `edits` is 0.
    - `shelfMap` object[]: DVT-1499: a server-limited subset of the org's live dashboards for a "shelf" visualization — the union of the top decile by window views and every at-risk dashboard (lifecycle IN stale, never, zombie), so the client never has to fetch or filter the full dashboard set itself. Additive; not part of the original DVT-1217 contract. Descending by window views, ties broken by dashboardId.
      - `dashboardId` string, required: Dashboard UUID.
      - `title` string, required: Dashboard title, or empty string when untitled.
      - `folder` string, required: Folder name, or "Unfiled" when unfoldered.
      - `views` integer, required: dashboard_views count in the requested window.
      - `daysSinceEdit` integer, required: Days since the latest audit_logs create/update event; falls back to the dashboard's createdAt when no edit exists on record (so this is always populated).
      - `daysSinceView` integer, nullable, required: Days since the later of the last render or last view on record; null only when neither has ever happened (lifecycle='never').
      - `lifecycle` 'healthy' | 'stale' | 'never' | 'zombie', required: Same taxonomy as `dashboards[].lifecycle` above.
    - `staleness` object, required: Org-wide dashboard staleness, honoring ONLY the `days` filter (see the endpoint description for why).
      - `totalLive` integer, required: Count of the org's live (non-deleted) dashboards.
      - `staleCount` integer, required: Of totalLive, those with zero renders AND zero views in the window.
      - `neverCount` integer, required: Of totalLive, those with no render or view EVER on record (subject to query_executions' and dashboard_views' retention — both default 365 days).
      - `items` object[], required: The stale set, oldest-last-viewed first (nulls first), up to 50.
        - `dashboardId` string, required: Dashboard UUID.
        - `title` string, required: Dashboard title, or empty string when untitled.
        - `lastViewedAt` string, date-time, nullable, required: All-time last render or view on record; null when never (within retention).
        - `createdAt` string, date-time, required: The dashboard's creation timestamp.
    - `connections` object[], required: Per-connection query health in the window, honoring ONLY the `days` filter, descending by runs.
      - `connectionId` string, required: Connection (data source) UUID.
      - `name` string, required: Connection name; resolved even for a since-soft-deleted connection so history keeps its name.
      - `type` string, required: Connection type (e.g. 'postgres', 'snowflake').
      - `runs` integer, required: Query executions against this connection in the window.
      - `errorCount` integer, required: Of runs, those with status IN ('error','timeout').
      - `p95Ms` number, required: P95 duration in ms across this connection's runs in the window (0 when no data).
  - `meta` Meta, required: Response metadata.
    - `requestId` string, required: Correlates with the X-Request-Id header.
    - `total` integer: Item count, present on collection responses.
    - `nextCursor` string, nullable: Opaque keyset-pagination cursor, present on paginated responses (e.g. GET /v1/dashboards) when more rows exist beyond this page. Pass it back as the `cursor` query param to fetch the next page; absent or null on the last page.
    - `roleResolveDegraded` boolean: Snowflake mode only (DVT-2260), on GET /v1/dashboards: present and true when the caller's live Snowflake role resolution failed or was unavailable — role-shared dashboards may be missing from this page. Omitted (not merely false) whenever resolution succeeded or the role-share arm does not apply (off snowflake mode, an org admin/owner, or off the ingress listener).

## Other responses

- `401`: Missing, invalid, or expired session.
- `403`: The caller's role does not permit this action.
- `404`: Resource does not exist.

---

[API](https://skmtc.dev/dvt/apis/dvt-rest-api.md) · [All operations](https://skmtc.dev/dvt/apis/dvt-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/dvt/apis/dvt-rest-api/revisions/00016f504165?raw)
