App Utilization by Department
This endpoint is approved but has not been implemented yet. See the App Usage Dashboard Spec for full context.
GET /clients/{client_id}/analytics/apps/utilization/departments
Returns a paginated list of departments ranked by app or user count for the requested period. Each row contains a department reference alongside aggregate metrics (user count, app count) and optional comparison-period change percentages.
This endpoint powers the "Departments" tab in the Un-Approved Apps section of the App Usage Dashboard. For the AI-specific departments view (which includes approved_user_count and unapproved_user_count), use AI By Department. This is the general-purpose department dimension view for any filter combination.
Use Case
Use this endpoint to:
- Render a departments tab showing which departments use the most apps
- Filter to unapproved app usage per department with
is_approved=false - Filter to a specific category's department distribution with
category_ids - Compare department-level adoption between time periods
Path Parameters
| Parameter | Type | Description |
|---|---|---|
client_id | string (uuid) | Unique identifier for the client organization |
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
granularity | string | Yes | - | Aggregation granularity: daily, weekly, monthly, quarterly |
start_date | string | Yes | - | Start of period (YYYY-MM-DD) |
end_date | string | Yes | - | End of period, inclusive (YYYY-MM-DD) |
compare_start_date | string | No | - | Comparison period start (YYYY-MM-DD). Must be provided with compare_end_date. |
compare_end_date | string | No | - | Comparison period end, inclusive (YYYY-MM-DD). Must be provided with compare_start_date. |
is_approved | boolean | No | - | Filter to apps by approval status |
category_ids | string | No | - | Comma-separated catalog category UUIDs to filter apps by |
vendor_ids | string | No | - | Comma-separated catalog vendor UUIDs to filter apps by |
sort_by | string | No | user_count | Sort field: user_count, app_count, name |
sort_order | string | No | desc | Sort direction: asc, desc |
page_size | integer | No | 50 | Items per page. Max: 200 |
cursor | string | No | - | Pagination cursor from a previous response |
Comparison period
When both compare_start_date and compare_end_date are provided, change_pct fields contain the percentage change from the comparison period to the primary period. When omitted, all change_pct fields are null.
Providing only one of the two comparison parameters returns 400.
Response
| Field | Type | Description |
|---|---|---|
period | Period | Resolved date range |
data | DepartmentUtilization[] | Array of department utilization objects |
total_count | integer | Total number of departments matching the current filters |
next_cursor | string | null | Cursor for the next page. null when on the last page. |
Example Requests
Departments using unapproved apps, February 2026
curl -X GET "https://api.example.com/v2/clients/aa7cf840-9ca9-46a3-9778-9015d6580d50/analytics/apps/utilization/departments?granularity=monthly&start_date=2026-02-01&end_date=2026-02-28&is_approved=false" \
-H "Authorization: Bearer YOUR_API_TOKEN"
With month-over-month comparison
curl -X GET "https://api.example.com/v2/clients/aa7cf840-9ca9-46a3-9778-9015d6580d50/analytics/apps/utilization/departments?granularity=monthly&start_date=2026-02-01&end_date=2026-02-28&compare_start_date=2026-01-01&compare_end_date=2026-01-31&is_approved=false" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Example Responses
With comparison period
{
"period": {
"start_date": "2026-02-01",
"end_date": "2026-02-28",
"compare_start_date": "2026-01-01",
"compare_end_date": "2026-01-31"
},
"data": [
{
"department": {
"id": "e2b3c4d5-f6a7-8901-bcde-f12345678901",
"name": "Engineering",
"description": "Software development and infrastructure teams"
},
"user_count": { "value": 34, "change_pct": 8.0, "compare_value": 31 },
"app_count": { "value": 6, "change_pct": 20.0, "compare_value": 5 }
},
{
"department": {
"id": "d1a2b3c4-e5f6-7890-abcd-ef1234567890",
"name": "Product",
"description": "Product management and design"
},
"user_count": { "value": 22, "change_pct": 10.0, "compare_value": 20 },
"app_count": { "value": 5, "change_pct": 0.0, "compare_value": 5 }
},
{
"department": {
"id": "f3c4d5e6-a7b8-9012-cdef-123456789012",
"name": "Design",
"description": "Visual and product design"
},
"user_count": { "value": 18, "change_pct": -5.3, "compare_value": 19 },
"app_count": { "value": 4, "change_pct": 33.3, "compare_value": 3 }
},
{
"department": {
"id": "a4d5e6f7-b8c9-0123-defa-234567890123",
"name": "Marketing",
"description": null
},
"user_count": { "value": 15, "change_pct": 7.1, "compare_value": 14 },
"app_count": { "value": 3, "change_pct": null, "compare_value": null }
},
{
"department": {
"id": "b5e6f7a8-c9d0-1234-efab-345678901234",
"name": "Sales",
"description": "Revenue and business development"
},
"user_count": { "value": 12, "change_pct": 20.0, "compare_value": 10 },
"app_count": { "value": 2, "change_pct": 0.0, "compare_value": 2 }
}
],
"total_count": 5,
"next_cursor": null
}
Without comparison period
{
"period": {
"start_date": "2026-02-01",
"end_date": "2026-02-28",
"compare_start_date": null,
"compare_end_date": null
},
"data": [
{
"department": {
"id": "e2b3c4d5-f6a7-8901-bcde-f12345678901",
"name": "Engineering",
"description": "Software development and infrastructure teams"
},
"user_count": { "value": 34, "change_pct": null, "compare_value": null },
"app_count": { "value": 6, "change_pct": null, "compare_value": null }
}
],
"total_count": 5,
"next_cursor": "eyJsYXN0X2lkIjoiZTJiM2M0ZDUifQ"
}
Empty Result
{
"period": {
"start_date": "2026-02-01",
"end_date": "2026-02-28",
"compare_start_date": null,
"compare_end_date": null
},
"data": [],
"total_count": 0,
"next_cursor": null
}
Period
| Field | Type | Nullable | Description |
|---|---|---|---|
start_date | string | No | Start of the primary period (YYYY-MM-DD) |
end_date | string | No | End of the primary period (YYYY-MM-DD) |
compare_start_date | string | Yes | Start of comparison period. null if no comparison requested. |
compare_end_date | string | Yes | End of comparison period. null if no comparison requested. |
DepartmentUtilization
| Field | Type | Nullable | Description |
|---|---|---|---|
department | DepartmentRef | No | Department identity reference |
user_count | MetricWithDeltaDto | No | Distinct users in this department with app activity during the period (scoped to any active filters) |
app_count | MetricWithDeltaDto | No | Distinct apps used by members of this department during the period (scoped to any active filters) |
DB source:
| DTO Field | DB Aggregation |
|---|---|
department | Joined via user-department assignments |
user_count.value | COUNT(DISTINCT user_id) from app_usage_reports, grouped by department, filtered to activity_date within the period |
app_count.value | COUNT(DISTINCT application_id) from app_usage_reports, grouped by department, filtered to activity_date within the period |
*.change_pct | ((current - comparison) / comparison) * 100 using the same aggregations over the comparison date range |
*.compare_value | The same aggregation as *.value applied to the comparison date range. null when no comparison period is requested. |
Pagination
This endpoint uses cursor-based pagination.
- Omit
cursoron the first request - If
next_cursoris notnull, pass its value ascursoron the next request - Repeat until
next_cursorisnull
Constraints
- Max date range: 366 days for both primary and comparison periods. Requests exceeding this return
400. - Comparison symmetry: Both
compare_start_dateandcompare_end_datemust be provided together, or both omitted. - Timezone: All dates are in the client's configured timezone.
granularityis required. There is no default.
Error Responses
| Status | Description |
|---|---|
| 400 | Invalid parameters (bad date format, range exceeds 366 days, mismatched comparison params, missing granularity, unknown sort_by value) |
| 401 | Authentication required |
| 403 | Insufficient permissions for this client |
| 404 | Client not found |
| 500 | Server error |
Notes
- Users assigned to multiple departments are counted once per department.
- When
is_approved=falseis provided, bothuser_countandapp_countare scoped to unapproved app usage only. - When
category_idsis provided, both metrics are scoped to apps in those categories.
Related Endpoints
- AI By Department -- AI-specific department breakdown with approved/unapproved user counts
- App Utilization -- Paginated per-app metrics table
- App Utilization Categories -- Categories dimension view
- App Utilization Users -- Users dimension view
- App Utilization Summary -- Aggregate card counts