-
Notifications
You must be signed in to change notification settings - Fork 0
Get PBIWorkspaceUsageReport
Get-PBIWorkspaceUsageReport.ps1 generates a comprehensive Power BI workspace and report usage report. It inventories all reports across all workspaces (including personal workspaces), correlates them with Power BI Activity Log data for the last 30 days by default (up to 90 days for Fabric/Premium capacities), and produces a detailed usage analysis showing view counts and unique users per report. Supports both Service Principal and interactive user authentication. Outputs in CSV or JSON format.
- Full Workspace Inventory - Enumerates all shared and personal workspaces using Power BI Admin APIs
-
Activity Log Correlation - Matches reports with
ViewReportevents from the Power BI Activity Log - Usage Metrics - View counts and unique user lists per report for configurable time periods
- User Detail Report - Per-user view counts per report for granular access analysis
- Stale Report Identification - Reports with zero views are surfaced for potential cleanup
- CSV and JSON Export - Choose output format; JSON uses proper arrays for user lists
- Pre-Flight Validation - Validates PowerShell version, output directory, and write permissions before starting
-
Dual Authentication Modes - Service Principal (client credentials) for automated/pipeline use, or interactive browser login via
-UseInteractiveAuthfor ad-hoc runs
- PowerShell 5.1 or later (validated at runtime)
The script calls Power BI /admin/ endpoints. Three things must all be in place:
Add the following API permissions to the app registration in Entra ID and grant admin consent:
| API | Permission | Type |
|---|---|---|
| Power BI Service | Tenant.Read.All |
Application |
The person configuring the Fabric tenant settings must hold the Fabric Administrator (or Global Administrator) role in Entra ID.
Without this role, the Fabric Admin Portal tenant settings will not be accessible or editable.
To assign the role:
Entra ID β Roles and administrators β Fabric Administrator β Add assignment
Once you have the Fabric Administrator role, navigate to:
https://app.powerbi.com/admin-portal/tenantSettings
Scroll to the Admin API settings section and configure:
- Setting: "Service principals can access read-only admin APIs"
- Toggle: Enabled
- Apply to: Specific security groups
- Action: Add the security group that contains your app registration's service principal
β οΈ Common confusion: "Service principals can call Fabric public APIs" (under Developer settings) is a different setting that covers regular endpoints only. The/admin/endpoints used by this script require the Admin API settings toggle above.
- Register an App in Entra ID
- Create a client secret
- Grant
Tenant.Read.All(Power BI Service) with admin consent - Add the service principal to the security group allowed in the Admin API settings above
- No Microsoft Graph API permissions are needed β only Power BI REST API access
Use this for ad-hoc runs or while Service Principal permissions are still propagating.
Requirements:
- The
MicrosoftPowerBIMgmtPowerShell module:Install-Module MicrosoftPowerBIMgmt -Scope CurrentUser - Sign in with a Power BI Administrator or Fabric Administrator account
-
TenantIdis still required;ClientIdandClientSecretare not used
βΉοΈ The same Admin API settings (above) apply β the signed-in user account must have Power BI Admin access to the tenant.
- Write permissions to the
OutputPathdirectory (validated at runtime)
Type: String
Required: Yes
Description: Azure AD / Entra ID Tenant ID.
Type: String
Required: Yes (Service Principal auth only)
Description: App Registration (Service Principal) Client ID. Not used when -UseInteractiveAuth is specified.
Type: String
Required: Yes (Service Principal auth only)
Description: App Registration Client Secret. For production use, retrieve from Azure Key Vault rather than hardcoding. Not used when -UseInteractiveAuth is specified.
Type: Switch
Required: No
Description: Use interactive browser login instead of a service principal client secret. Requires the MicrosoftPowerBIMgmt module. When specified, ClientId and ClientSecret are not needed. TenantId is still required.
Type: String
Required: No
Default: . (current directory)
Description: Directory where all output files will be written. The directory will be created if it doesn't exist. Write permissions are validated before execution begins.
Type: String
Required: No
Default: csv
Valid Values: csv, json
Description: Output file format. JSON includes proper arrays for user lists and pretty-printed formatting.
Type: Integer
Required: No
Default: 30
Valid Range: 1β90
Description: Number of days of Power BI activity history to retrieve. Standard Power BI audit log retains 30 days; tenants with Fabric or Premium capacity may retain up to 90 days. Requesting dates outside the tenant's retention window returns a 400 error (skipped automatically per day).
.\Get-PBIWorkspaceUsageReport.ps1 `
-TenantId "12345678-1234-1234-1234-123456789012" `
-UseInteractiveAuth `
-OutputPath "C:\Reports\PBI" `
-OutputFormat "json"Opens a browser login prompt. Use a Power BI Administrator account. No app registration needed.
.\Get-PBIWorkspaceUsageReport.ps1 `
-TenantId "12345678-1234-1234-1234-123456789012" `
-ClientId "abcdefab-1234-1234-1234-abcdefabcdef" `
-ClientSecret "your-client-secret".\Get-PBIWorkspaceUsageReport.ps1 `
-TenantId "12345678-1234-1234-1234-123456789012" `
-UseInteractiveAuth `
-OutputPath "C:\Reports\PowerBI" `
-ActivityDays 90
β οΈ Only use-ActivityDaysvalues above 30 if the tenant has Fabric or Premium capacity with extended audit retention. Standard tenants will see per-day failures for dates beyond 30 days (skipped automatically).
# Run report
.\Get-PBIWorkspaceUsageReport.ps1 `
-TenantId "12345678-1234-1234-1234-123456789012" `
-UseInteractiveAuth `
-OutputPath "C:\Reports\PowerBI"
# Filter stale reports from the usage CSV
$usage = Import-Csv "C:\Reports\PowerBI\PBI_Report_Usage_*.csv"
$stale = $usage | Where-Object { [int]$_.TotalViews_90d -eq 0 }
Write-Host "Stale reports (0 views in last 30 days): $($stale.Count)"
$stale | Select-Object ReportName, WorkspaceName, WorkspaceType | Format-TableAll output files include a timestamp suffix (YYYYMMDD_HHmmss) to prevent overwrites.
Full inventory of all reports across all workspaces.
| Column | Description |
|---|---|
| ReportId | Power BI Report GUID |
| ReportName | Display name of the report |
| WorkspaceId | Power BI Workspace GUID |
| WorkspaceName | Display name of the workspace |
| WorkspaceType |
Shared or Personal
|
Per-report usage aggregation sorted by most-viewed.
| Column | Description |
|---|---|
| ReportId | Power BI Report GUID |
| ReportName | Display name of the report |
| WorkspaceName | Workspace containing the report |
| WorkspaceType |
Shared or Personal
|
| TotalViews_90d | Total ViewReport events in the activity window |
| UniqueUsers_90d | Count of distinct users who viewed |
| UserList_90d | Semicolon-delimited list of user IDs (CSV) or JSON array (JSON format) |
| DatasetId | Power BI Dataset GUID backing the report |
| ReportWebUrl | Direct URL to open the report in Power BI Service |
Per-user, per-report view counts.
| Column | Description |
|---|---|
| ReportId | Power BI Report GUID |
| ReportName | Display name of the report |
| UserId | Azure AD User UPN or Object ID |
| ViewCount_90d | Number of times this user viewed the report |
| LastViewed | Timestamp of the user's most recent view event |
| WorkspaceName | Workspace containing the report |
| WorkspaceType |
Shared or Personal
|
Human-readable summary including:
- Total reports, shared vs. personal breakdown
- Reports with and without usage
- Total view events and unique users
- Top 10 most-viewed reports
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Power BI Workspace Usage Report - Phase 1
Managed Solution
Output Format: CSV
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
[INVENTORY] Report Inventory Summary:
Total Reports : 412
Shared Workspace : 387
Personal Workspace : 25
β
[EXPORT] Report inventory -> C:\Reports\PowerBI\PBI_Report_Inventory_20260313_143052.csv
...
β
[DONE] All reports generated successfully.
Root Cause:
The script calls /admin/ endpoints. Tenant.Read.All being granted and the "Service principals can call Fabric public APIs" setting being enabled is not sufficient β the Admin API setting is controlled by a separate toggle.
Resolution steps:
Step 1 β Verify you have Fabric Admin access to configure tenant settings:
The person making changes must hold the Fabric Administrator (or Global Administrator) role.
Entra ID β Roles and administrators β Fabric Administrator β Add assignment
Step 2 β Enable Admin API access in the Fabric Admin Portal:
Navigate to: https://app.powerbi.com/admin-portal/tenantSettings
Scroll to Admin API settings and configure:
- Enable: "Service principals can access read-only admin APIs"
- Set Apply to: Specific security groups
- Add the security group containing your app registration's service principal
β οΈ Common confusion: "Service principals can call Fabric public APIs" (Developer settings) covers regular/public endpoints only β it does not grant access to/admin/endpoints used by this script.
Cause: Insufficient Power BI admin permissions.
Solution: Verify the service principal has Tenant.Read.All in Power BI and admin API access is enabled.
Cause:
- Standard Power BI audit log retains only 30 days of data. Requesting dates older than 30 days returns 400 errors (the script skips those days automatically and reports a count at the end)
- Tenant may have activity logging disabled
Solution:
- Use the default
ActivityDays 30or explicitly pass-ActivityDays 30for standard tenants - Only use higher values (up to 90) if the tenant has Fabric or Premium capacity with extended retention
- Verify Power BI activity logging is enabled in the Power BI Admin Portal
Cause: Running on PowerShell 5.0 or earlier.
Solution:
# Check your version
$PSVersionTable.PSVersion
# Upgrade to PowerShell 5.1 or install PowerShell 7Cause: Account doesn't have write access to the output directory.
Solution: Specify a writable directory:
-OutputPath "$env:USERPROFILE\Documents\PBI_Reports"- ActivityDays: Shorter periods reduce API calls significantly. Start with 30 days to validate.
- Large Tenants: Tenants with 1000+ reports and many users may take 20β30 minutes to complete.
-
Rate Limiting: Built-in
$ProgressPreference = "SilentlyContinue"speeds up API calls. The Power BI Activity API is paginated hourly and may take time on large tenants.
- Get-EnterpriseAppUsage - Similar usage pattern for Azure AD app registrations
- v1.0 - Initial release - Core inventory and usage correlation
- v1.1 (2026-03-12) - Added pre-flight validation, improved error handling and authentication, Export-Data with verbose logging, and wrapped main auth in try/catch
-
v1.2.0 (2026-03-20) - Added
-UseInteractiveAuthswitch for interactive login viaMicrosoftPowerBIMgmtmodule; switched activity event collection toGet-PowerBIActivityEventcmdlet with client-sideViewReportfiltering; changed defaultActivityDaysfrom 90 to 30 to match standard Power BI audit retention
- Overview
- Start-LyncCsvExporter
- Get-ComprehensiveLyncReport
- Get-LyncHealthReport
- Get-LyncInfrastructureReport
- Get-LyncServiceStatus
- Get-LyncUserRegistrationReport
- Export-ADLyncTeamsMigrationData
- New-Office365Accounts
- Sync-ContactsFromCsv
- Set-EmailToSharedAccount
- Set-SMTPForward
- Invoke-UserSignOutAndBlock
- Security Assessment Scripts (coming soon)
- Azure Automation (documentation pending)
- Get-GraphToken
- Get-GraphHeaders
- Get-AzureResourcePaging
- Get-EnterpriseAppUsage
- Get-ExchangeErrorsGraph
- Get-PBIWorkspaceUsageReport
- Intune Management (documentation pending)