Skip to main content

Analytics Domain

The Analytics domain provides read-only endpoints for querying activity, utilization, and AI app usage data across users, devices, and apps. It is completely separate from the identity/CRUD resource domains -- those domains own the resource definitions, this domain owns the numbers.

Endpoint pattern

Every analytics resource exposes up to four endpoint roles:

RolePath shapeReturns
Activity/{resource}/{id}/activityDaily time-series for one resource. One data point per day, one metric per request.
List/{resource}s/{kind}Paginated table across all resources. { period, data, total_count, next_cursor }
Summary/{resource}s/{kind}/summaryFlat aggregate card counts. No pagination.
Rankings/{resource}s/{kind}/rankingsNamed top-performer slots (leader, biggest increase, biggest decrease). No pagination.

Not every resource has all four. The parent route (/{kind}) is always the list — never a container. /summary and /rankings are siblings to it.

Apps example:

GET /analytics/apps/{app_id}/activity        ← time-series for one app
GET /analytics/apps/utilization ← paginated per-app metrics table
GET /analytics/apps/utilization/summary ← cards: apps used, discovered, dropped off
GET /analytics/apps/utilization/rankings ← top app by interactions, time, users

For the full rules on each role, see the Design Guidelines.

Endpoints

Apps

EndpointMethodDescription
App ActivityGETDaily activity time-series for an app
App UtilizationGETPaginated utilization table across all client apps (unique users, active time, session count, avg daily time); supports discovered/dropped_off filter
App Utilization SummaryGETCard counts: total apps used, newly discovered, dropped off, plus dimension counts (categories, users, departments). Modified — see dashboard spec
App Utilization RankingsGETTop-ranked app by interactions, active time, and active users; includes biggest movers
App Utilization TimeseriesGETApproved — Time-series of app counts by classification (unused, unapproved, AI, other) for stacked bar chart
App Utilization by CategoryGETApproved — Categories ranked by app count and user count; supports is_approved and category_ids filters
App Utilization by UserGETApproved — Users ranked by distinct app count; supports is_approved and category_ids filters
App Utilization by DepartmentGETApproved — Departments ranked by user count and app count; supports is_approved and category_ids filters

AI Apps

AI-specific analytics filtered to apps whose catalog categories include "AI". Two list endpoints remain active because they provide usage_level (heavy/medium/light), which is not available on the generic utilization endpoints. Four endpoints are deprecated — see the AI Apps Overview for details.

EndpointMethodDescription
AI App Users SummaryGETAggregate user adoption metrics for AI apps
AI App UsersGETPaginated list of AI apps ranked by user count
New AI Tools SummaryGETCount of newly discovered AI tools in the period
New AI ToolsGETPaginated list of AI apps first seen in the period
AI By Department SummaryGETTotal AI users across all departments
AI By DepartmentGETPaginated list of departments with AI app usage metrics

Devices

EndpointMethodDescription
Device ActivityGETDaily activity time-series for a device

Users

EndpointMethodDescription
User ActivityGETDaily activity time-series for a user

Data Sources

Analytics endpoints aggregate from two tables depending on the resource:

ResourceSource TableGranularity
UsersheartbeatsOne row per heartbeat per user-device pair
DevicesheartbeatsSame table, scoped by device_id
Appsapp_usage_reportsOne row per user per app per day (partitioned by month)
AI Appsapp_usage_reportsSame table, filtered to apps with an AI catalog category

heartbeats

The desktop agent sends periodic heartbeats. Each heartbeat is tied to a user_id, device_id, and user_device_id. Key columns:

ColumnTypeDescription
total_activity_countintegerAggregate activity count (sum of all sources below)
chrome_activity_countintegerChrome extension activity
edge_activity_countintegerEdge extension activity
firefox_activity_countintegerFirefox extension activity
desktop_activity_countintegerDesktop agent activity
web_accessibility_activity_countintegerWeb accessibility activity
generated_at_utctimestampWhen the heartbeat was generated (used for date grouping)

app_usage_reports

Daily aggregated app usage per user. Partitioned by month (app_usage_reports_2026_01, etc.).

ColumnTypeDescription
total_active_msbigintActive time in milliseconds
total_session_countbigintNumber of sessions
application_iduuidThe app being measured
user_iduuidThe user
activity_datedateThe date of activity (used for grouping)

Shared Response DTO

ActivityTimeSeries

All /activity endpoints return this shape. See individual endpoint docs for which metric values are available.

{
"metric": "activity-count",
"label": "Total Activity",
"period": {
"start": "2024-01-01",
"end": "2024-01-15"
},
"data": [
{ "date": "2024-01-01", "value": 42 },
{ "date": "2024-01-02", "value": 38 },
{ "date": "2024-01-03", "value": 0 }
]
}
FieldTypeDescription
metricstringThe metric key that was requested
labelstringHuman-readable label for the metric (e.g. "Total Activity", "Daily Users")
periodobjectDate range for this data
period.startstringStart date (YYYY-MM-DD)
period.endstringEnd date (YYYY-MM-DD)
dataDailyDataPoint[]One entry per day in the range
data[].datestringDate (YYYY-MM-DD)
data[].valuenumberMetric value for that day (0 if no activity)

value is used instead of count because not all metrics are counts -- for example, active-time returns milliseconds.

Shared Patterns

Granularity

All analytics endpoints accept a granularity parameter that controls how metrics are averaged within the period. See Analytics Pattern: Granularity.

Period object in responses

All aggregate analytics endpoints that accept date range + comparison parameters echo the resolved dates back in a period object. See Response Period Object.

Filter parameters: plural IDs

All filter parameters accept comma-separated UUID lists (category_ids, department_ids, vendor_ids). See Filter Parameters: Plural IDs.

Constraints

  • Max date range (activity): 90 days. Requests exceeding this return 400.
  • Max date range (aggregate): 366 days for both primary and comparison periods.
  • Zero-fill: Days with no activity return value: 0. The response always includes every date in the requested range.
  • Timezone: All dates are in the client's configured timezone.
  • One metric per request (activity): Each request returns a single metric. To display multiple metrics (e.g. a chart with a metric selector), make parallel requests.

Extensibility

New analytics types are added as sibling sub-paths. Existing endpoints are never affected:

/analytics/apps/utilization                  ← paginated per-app metrics table
/analytics/apps/utilization/summary ← collection-level dashboard cards
/analytics/apps/utilization/rankings ← top app rankings
/analytics/apps/utilization/timeseries ← proposed: time-series by classification
/analytics/apps/utilization/categories ← proposed: categories dimension view
/analytics/apps/utilization/users ← proposed: users dimension view
/analytics/apps/utilization/departments ← proposed: departments dimension view
/analytics/apps/{app_id}/utilization ← future: per-app utilization detail
/analytics/apps/{app_id}/utilization/users ← future: per-user breakdown for an app
/analytics/devices/{device_id}/performance ← future: CPU/RAM resource usage
/analytics/apps/ai/users ← AI app user adoption
/analytics/apps/ai/recent ← newly discovered AI tools
/analytics/apps/ai/departments ← AI usage by department