---
title: "Org content inventory — every live dashboard, paginated."
method: GET
path: "/v1/orgs/{orgId}/analytics/content/inventory"
tags: ["dashboards"]
---

# Org content inventory — every live dashboard, paginated.

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

## Request

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

The full dashboard inventory behind the admin Content surface (DVT-5383).
Unlike `GET /v1/orgs/{orgId}/analytics/content` — whose `dashboards`
leaderboard is capped at 50 and is unchanged — this lists **every live
(non-deleted) dashboard in the org**, including ones with no activity.
Admin or owner only (audit:read); own-org only.

Each item carries the same fields as a leaderboard row (`ContentDashboard`,
flattened) with the same semantics: render/view metrics (`renders`, `runs`,
`errorCount`, `views`, `viewers`) are windowed by `days`. `lastViewedAt` is the
exception: on inventory rows it is the all-time most recent view or render
(null only when none is on record), so a `stale` row still carries it.
`lastEditedAt`/`lifecycle`/`favorites`/comments are as on the leaderboard.
Only `days` narrows the metrics — there is no connection/actor narrowing
of the numbers. It adds `folderId`, `ownerId`/`ownerName`, `purpose`
(the manifest `meta.purpose`, else the dashboard description, else `""`),
and `connections` (the distinct live connections the dashboard's current
panels read from, resolved from each panel's `data.sourceId`; a panel source that
resolves to no connection, such as an env or demo source, is omitted, and
panels bound only via `metricRef` contribute no connection). `viewsDaily14` is populated for the
returned page.

`total` counts rows after filters and before paging. Filters combine with
AND. `sort` orders by the chosen key; timestamps that are null always sort
**last** whichever `order` is requested; `title`/`owner` compare
case-insensitively; `sort=views` breaks ties on `renders` (same
direction); remaining ties break on `dashboardId` ascending, so paging is
stable. An `offset` past the end returns empty `items` with the correct
`total`. Invalid `sort`, `order`, `lifecycle`, `limit` or `offset` are
rejected with 400.

## Query parameters

- `days` integer
- `sort` 'views' | 'lastViewedAt' | 'lastEditedAt' | 'title' | 'owner'
- `order` 'asc' | 'desc'
- `folderId` string
- `ownerId` string
- `connectionId` string
- `lifecycle` 'healthy' | 'stale' | 'never' | 'zombie'
- `limit` integer
- `offset` integer

## Response `200`

One page of the org's content inventory.

- object
  - `data` ContentInventoryResult, required
    - `rangeDays` integer, required: The metrics window actually applied (days, clamped to 1-365).
    - `generatedAt` string, date-time, required: When the inventory was computed.
    - `viewsSource` 'events' | 'derived', required: Same meaning as on `OrgAnalyticsContent.viewsSource`.
    - `total` integer, required: Rows matching the filters
    - `limit` integer, required: The page size applied.
    - `offset` integer, required: The offset applied.
    - `items` ContentInventoryItem[], required
      - `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.
      - `folderId` string, nullable, required: The dashboard's folder id, or null when unfiled.
      - `ownerId` string, required: Owner user id.
      - `ownerName` string, required: Owner's display name, else email, else 'system'.
      - `purpose` string, required: The manifest `meta.purpose`, else the dashboard description, else an empty string.
      - `connections` InventoryConnection[], required: Distinct live connections the dashboard's current panels read from, sorted by name. Always present; unresolved sources are omitted.
        - `connectionId` string, required: The resolved data_sources row id.
        - `name` string, required: The connection's name.
        - `sourceId` string, required: The spelling the panel spec used to reference it (connection id or name); first one wins when a dashboard uses both.
      - `certification` Certification: A dashboard's derived certification standing (DVT-5223), computed at read time — dashboards carry no tier column. `tier` is the EFFECTIVE tier (highest-ranked live grant, else draft). `state` and the certified* fields describe the highest-ranked ACTIVE grant, which may be stale or expired; the effective* fields describe the grant that determined `tier`. For headless render actors only `tier` and `state` are returned.
        - `tier` 'draft' | 'published' | 'certified' | 'canonical', required
        - `state` 'live' | 'stale' | 'expired': State of the highest-ranked active grant; absent when there is none.
        - `certifiedTier` 'published' | 'certified' | 'canonical'
        - `domain` string
        - `certifiedBy` string
        - `certifiedAt` string, date-time
        - `certifiedRevisionId` string, uuid
        - `certifiedVersion` integer
        - `editsSince` integer: Revisions written since the certified one.
        - `grantedVia` string
        - `expiresAt` string, date-time
        - `queryRole` string
        - `effectiveDomain` string
        - `effectiveGrantedBy` string
        - `effectiveGrantedAt` string, date-time
        - `effectiveExpiresAt` string, date-time
  - `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

- `400`: Malformed request.
- `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)
