---
title: "Org usage analytics."
method: GET
path: "/v1/orgs/{orgId}/analytics"
tags: ["dashboards"]
---

# Org usage analytics.

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

## Request

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

Aggregate usage, authorship, and query-performance analytics for the
organization over a rolling window. Admin or owner only (audit:read).
The `data` object shape is frozen — field names are a client contract.

## Query parameters

- `days` integer

## Response `200`

Org analytics result.

- object
  - `data` OrgAnalytics, required: Aggregate usage / authorship / query-performance analytics for a single organization over a rolling window. All field names are a frozen client contract (DVT-335).
    - `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.
    - `kpis` object, required: Scalar key-performance indicators for the window.
      - `activeUsers` integer, required: Distinct actors with at least one audit event.
      - `totalDashboards` integer, required: Current non-deleted dashboard count (point-in-time).
      - `dashboardsCreated` integer, required: Dashboards created within the window.
      - `queriesRun` integer, required: query_executions rows within the window.
      - `renders` integer, required: Distinct request_ids with purpose=dashboard_render within the window — computed identically to previousPeriod.renders so the period-over-period delta compares like to like (DVT-1240).
      - `medianQueryMs` integer, required: Median successful query duration in ms (0 when no data).
      - `p95QueryMs` integer, required: P95 successful query duration in ms (0 when no data).
      - `connectionsInUse` integer, required: Distinct warehouse connections that drove at least one query.
      - `wau` integer: DVT-1497 Pulse. Distinct HUMAN actors (audit_logs actor_type='user', actor_id not null) active in a FIXED trailing-7-day window — independent of the requested `days`. Optional; older clients ignore it.
      - `mau` integer: DVT-1497 Pulse. Same as `wau` but over a FIXED trailing-30-day window. Optional; older clients ignore it.
      - `agentsActive` integer: DVT-1497 Pulse. Distinct non-user actors (actor_type <> 'user' — the merged agent/api_key/system/render class) active within the requested `days` window. Optional; older clients ignore it.
    - `previousPeriod` object: Totals for the immediately prior window of equal length — between 2×days and days ago — powering Overview period-over-period deltas (DVT-1218). The server always emits this object; it is omitted from OrgAnalytics's top-level `required` list only for older-client compatibility, not because it can be absent.
      - `activeUsers` integer, required: Distinct audit actors in the immediately prior window of equal length — between 2×days and days ago.
      - `edits` integer, required: audit_logs rows with action IN ('create','update') in the immediately prior window of equal length — between 2×days and days ago.
      - `renders` integer, required: Distinct request_ids with purpose=dashboard_render in the immediately prior window of equal length — between 2×days and days ago.
      - `queriesRun` integer, required: query_executions rows in the immediately prior window of equal length — between 2×days and days ago.
      - `p95QueryMs` integer: DVT-1497 Pulse. P95 successful query duration in ms over this same prior window (0 when no data), computed identically to kpis.p95QueryMs so the two are directly comparable. Unlike the other previousPeriod fields, this one honors the `connectionId` filter. Optional; older clients ignore it.
    - `activityOverTime` object[], required: Day-by-day audit-event counts, human vs. agent, ascending by date.
      - `date` string, required: YYYY-MM-DD.
      - `human` integer, required: Events from actor_type='user'.
      - `agent` integer, required: Events from actor_type IN ('agent','system').
    - `editsVsViews` object[], required: Day-by-day edits vs. views series, ascending by date. Only days with at least one edit or view are present; the client zero-fills the rest. Edits = audit_logs rows with action IN ('create','update'); views = query_executions rows with purpose='dashboard_render'. Empty array when no data in the window (DVT-354).
      - `date` string, required: YYYY-MM-DD.
      - `edits` integer, required: Dashboard authoring events (create or update) on this day.
      - `views` integer, required: Dashboard render executions (purpose=dashboard_render) on this day.
    - `topAuthors` object[], required: Up to 10 most-active create/update authors in the window.
      - `actorId` string, uuid, required
      - `name` string, required: display_name, else email, else 'unknown'.
      - `actorType` string, required
      - `events` integer, required
      - `dashboardsTouched` integer, required: Distinct dashboard resource_ids the actor touched.
    - `topDashboards` object[], required: Up to 10 most-rendered dashboards in the window.
      - `dashboardId` string, uuid, required
      - `title` string, required: Dashboard title; empty string when deleted/null.
      - `renders` integer, required: Distinct request_ids with purpose=dashboard_render.
      - `lastRenderedAt` string, date-time, required
    - `slowestQueries` object[], required: Up to 15 slowest non-null-duration queries in the window, descending by duration.
      - `executionId` string, uuid, required
      - `dashboardId` string, required: Dashboard UUID or empty string when not associated.
      - `dashboardTitle` string, required: Dashboard title or empty string when null.
      - `purpose` string, required
      - `status` string, required
      - `durationMs` integer, required
      - `rowCount` integer, required
      - `startedAt` string, date-time, required
      - `querySql` string, required: Parameterized SQL statement (params bound separately — no literal PII). Empty string when not captured (older rows / non-render). DVT-374.
    - `pulseDaily` object[]: DVT-1497 Pulse. Day-by-day activity series over the requested `days` window, ascending by date. Only days with at least one event on either source are present; the client zero-fills the rest (same convention as editsVsViews). Optional array (always present, possibly empty); older clients ignore it.
      - `date` string, required: YYYY-MM-DD (UTC).
      - `human` integer, required: audit_logs events from actor_type='user' on this day.
      - `agent` integer, required: audit_logs events from actor_type<>'user' on this day — the merged agent/api_key/system/render class.
      - `edits` integer, required: audit_logs rows with action IN ('create','update') on this day.
      - `humanEdits` integer: Of `edits`, the subset from actor_type='user'. humanEdits + agentEdits == edits. Optional; older clients ignore it.
      - `agentEdits` integer: Of `edits`, the subset from actor_type<>'user' — the merged agent/api_key/system/render class. humanEdits + agentEdits == edits. Optional; older clients ignore it.
      - `renders` integer, required: Distinct request_ids with purpose=dashboard_render on this day (a render fans out to many element-query rows sharing one request_id, so this is NOT a row count). Computed identically to kpis.renders/previousPeriod.renders/editsVsViews.views. Honors the `connectionId` filter.
      - `queries` integer, required: query_executions rows (all purposes) on this day. Honors the `connectionId` filter.
      - `humanQueries` integer: Of `queries`, the subset from actor_type='user'. humanQueries + agentQueries == queries. Honors the `connectionId` filter identically to `queries`. Optional; older clients ignore it.
      - `agentQueries` integer: Of `queries`, the subset from actor_type<>'user'. humanQueries + agentQueries == queries. Honors the `connectionId` filter identically to `queries`. Optional; older clients ignore it.
    - `hourWeekday` object[]: DVT-1497 Pulse. Activity heatmap over a FIXED trailing-180-day window (independent of the requested `days`), computed from audit_logs in UTC. Only nonzero (dow, hour) cells are present. Optional array (always present, possibly empty); older clients ignore it.
      - `dow` integer, required: Day of week in UTC: 0=Sunday .. 6=Saturday.
      - `hour` integer, required: Hour of day in UTC: 0..23.
      - `events` integer, required: All audit_logs events in this cell.
      - `agentEvents` integer, required: Subset of `events` with actor_type<>'user'.
    - `needsAttention` object[]: DVT-1497 Pulse. Server-synthesized "what needs attention" list: up to 2 performance offenders plus one item each (when applicable) for failing export automation, unhealthy connections (max 2), dormant members, content hygiene, and a stale API key. Ordered bad -> warn -> info, capped at 8 items. Optional array (always present, possibly empty); older clients ignore it.
      - `severity` 'bad' | 'warn' | 'info', required
      - `kind` 'health' | 'automation' | 'people' | 'content', required: Which admin surface this item relates to.
      - `title` string, required
      - `why` string, required: Data-only supporting line — values/dates/counts, never a causal guess. Truncated to 160 characters when it embeds customer-facing error text.
      - `link` string, required: Relative admin path this item deep-links to.
  - `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)
