Be smarter with every change
One-Click, Designed for Everyone
ImpactIQ backs up every model, report and dataflow you can reach, extracts their metadata down to the visual level, and loads it all into the Power BI Governance Model so you can see what depends on what before you change it.
v3 keeps the one-click, interactive experience of v2 and adds what an organisation needs to run it unattended: a headless entry point, checkpoints that let an interrupted run resume where it stopped, sign-in options that work on a schedule without a service principal, an Azure DevOps pipeline, more data in the same workbooks, and endpoint tables for the commercial, GCC, GCC High, DoD and China clouds.
- Everything within the script is limited to your access within the Power BI and/or Fabric environment.
- All computer requirements are at the user level and do not require admin privileges.
- No app registration, no service principal, no Azure VM. A Pro or PPU licensed user account is all it signs in as.
Have specific Reports and/or Models downloaded you want to analyze? Don't have direct access to the Workspace but have the PBIX? Check out Impact IQ's local edition here: https://github.com/BeSmarterWithData/ImpactIQ-Local
Other Versions: Tenant Admin Edition, Semantic Link Labs Edition, Service Principal Edition
- What it does
- What changed in v3
- Quick start (interactive, 5 minutes)
- Getting started: full rollout walkthroughs
- Before you start (every option)
- Option A: interactive runs on a workstation
- Option B: Windows Task Scheduler (no Azure DevOps)
- Option C: Azure DevOps with a self-hosted Windows agent (recommended)
- Option D: Azure DevOps with a Microsoft-hosted agent and device-code sign-in
- Option E: Azure DevOps with a Microsoft-hosted agent and an MFA-exempt account
- Connecting the Power BI Governance Model
- Running it week after week
- Where the files go
- Clouds and endpoints
- Command-line reference
- Documentation
- Features
This provides a quick and automated way to identify where and how specific fields, measures, and tables are used across Power BI reports in all workspaces down to the visual level. It also backs up and breaks down the details of your models, reports, and dataflows for easy review, giving you an all-in-one Power BI & Fabric Governance solution.
- Impact Analysis: Fully understand the downstream impact of data model changes with visual-level lineage, ensuring you don't accidentally break visuals or dashboards, even when multiple reports connect to a model in a different workspace.
- Used and Unused Objects: Identify which tables, columns, and measures are actively used and where. Equally as important, see what isn't used and can be safely removed from your model to save space and complexity.
- Comprehensive Environment Overview: Gain a clear, detailed view of your entire Power BI environment, including complete breakdowns of your models, reports, and dataflows and their dependencies.
- Backup Solution: Automatically backs up every model, report, and dataflow for safekeeping.
- User-Friendly Output: the final output is presented in a Power BI Report & Model, making everything easy to explore, analyze, and share with your team.
- Multi-Tenant Selection: if your account can access multiple Microsoft tenants, a popup lets you choose which tenant receives all Power BI and Fabric API calls (
-TenantIdfor scheduled runs). - Runs on a schedule: the same extraction runs headless from Task Scheduler or Azure DevOps, resumes after any interruption and signs in as a user without a service principal.
Everything v2 produced is still produced, with the same names, so an existing Power BI Governance Model.pbit
keeps working. What is new:
| Area | v2 | v3 |
|---|---|---|
| Entry point | one 3,740-line interactive script | ImpactIQ.ps1 plus fourteen modules under Config\Modules\; Final PS Script.txt is a thin launcher for the interactive experience |
| Where it runs from | hard-coded C:\Power BI Backups, data mixed with the script |
the folder you downloaded it to; backups and workbooks go to Outputs\ under it and can be moved with -BackupFolder / -OutputFolder |
| Headless | not possible (dialogs, browser sign-in, Read-Host) |
-NonInteractive plus a parameter or IMPACTIQ_* variable for every former prompt; no scope given means the run stops instead of scanning the tenant |
| Interruptions | start over | every workspace, model, report, model-detail CSV and dataflow is checkpointed the moment it finishes; re-running skips what succeeded and retries what failed; -TimeBudgetMinutes pauses cleanly before a job cap and resumes on the next run |
| Sign-in | browser every 55 minutes | silent token refresh; DeviceCode with an encrypted refresh-token cache, Credential, AzContext, AccessToken, and the original Interactive |
| Robustness | silent failures, no retries | one HTTP wrapper with retry and back-off (429 Retry-After, 5xx, network), timeouts and captured output for Tabular Editor and pbi-tools, per-item failure records, a Failures sheet, exit codes 0 / 2 / 3 / 1 |
| Multi-tenant accounts | (added upstream after the fork) | ported: interactive runs list the tenants the account can reach and let you pick one; headless runs take -TenantId / IMPACTIQ_TENANT_ID |
| Clouds | endpoint table with two wrong hosts | verified tables for Public, GCC, GCC High, DoD, China (and the retired Germany cloud); aliases GCC, GCCHigh, DoD; every REST, OAuth, XMLA, Fabric and portal URL follows -Environment |
| Fabric absent (GCC) | retries and errors per call | detected once per run (token refused or host unreachable), then skipped without a request; the Fabric-only sheets stay empty and everything else is unaffected |
| Model detail | Tabular Editor 2 over XMLA only | Tabular Editor, or the built-in .bim parser, or DAX INFO.VIEW.* over executeQueries (-ModelDetailMethod Auto|TabularEditor|Bim|Dax|Both) |
| Data | 17 sheets | plus Dashboards, DashboardTiles, Capacities, WorkspaceUsers, DatasetUsers, DatasetParameters, DatasetDQRefreshSchedule, RunSummary, Failures, InventoryErrors, ReportExports; optional -IncludeUsageMetrics and -IncludeAdminApis |
| Scheduling | none | pipelines/azure-pipelines.yml (state restored from the previous run, artifacts, optional commit of the workbooks for a gateway-free refresh) |
| Quality | none | parser, PSScriptAnalyzer (5.1 and 7 compatibility rules) and a 582-test Pester suite; docs/Validation-Report.md lists the v2 defects that were fixed |
The v2 experience: dialogs, browser sign-in, pickers, and the workbooks in the Outputs folder when it finishes.
- Download this repository (Code > Download ZIP, or
git clone) and extract it into any folder, for exampleC:\ImpactIQ. Keep the layout:ImpactIQ.ps1,Final PS Script.txt,Config\,Power BI Governance Model.pbit.The one-click batch file published with v2 downloads the repository it was built for into
C:\Power BI Backups. It still works with v3 (the scripts run from wherever they are), but to get the v3 code, download this repository. - Run the launcher. Either rename
Final PS Script.txttoFinal PS Script.ps1and run it, or open PowerShell in the folder and paste the file's contents. PowerShell may offer to install theImportExceland Power BI modules for your user; no admin rights are needed. - Answer the prompts: environment (
Publicafter 60 seconds the first time;USGovfor GCC - the environment you pick is remembered inConfig\ImpactIQ.Settings.jsonand offered first from then on), the tenant if your account can reach more than one (the current one after 60 seconds), sign in, choose whether to run against workspaces, reports or models, then pick them.ImpactIQ.batin the same folder does the same from a double-click (ImpactIQ.bat --helplists its switches). - Wait. The console shows each stage and ends with a per-stage summary, the four workbook paths and the log file. If the run is interrupted, run the launcher again: finished items are skipped.
- Open
Power BI Governance Model.pbit, setBase Directoryto theOutputsfolder (for exampleC:\ImpactIQ\Outputs), let it refresh, save as.pbix.
📂 All backups and the four workbooks land in Outputs\ under the folder you ran it from. The code, Config\,
State\ and Logs\ stay outside it. To put the data elsewhere, set
IMPACTIQ_BACKUP_FOLDER and/or IMPACTIQ_OUTPUT_FOLDER before running the launcher (or pass -BackupFolder /
-OutputFolder to ImpactIQ.ps1).
Pick the option that matches where the run can live and how the identity can be kept alive between runs. The decision in one line: any Windows machine that stays on → Option C (or B without Azure DevOps); no machine at all → Option D; an MFA-exempt service account that security accepts → Option E.
| Runs where | Signs in how | Time cap | Needs | Best for | |
|---|---|---|---|---|---|
| A | your workstation, by hand | browser | none | nothing extra | a single owner, on demand |
| B | a Windows box, Task Scheduler | device code once, DPAPI cache | none | a box that stays on | one owner, nightly, no Azure DevOps |
| C | Azure DevOps, self-hosted agent on a Windows box | device code once, DPAPI cache (or AzContext) | none | the free agent installed as a service | teams; the recommended default |
| D | Azure DevOps, Microsoft-hosted windows-latest |
device code once, AES-encrypted cache carried between runs | 60 min free / 360 min with one paid parallel job | one secret variable; a paid parallel job for big tenants | no Windows machine available |
| E | Azure DevOps, Microsoft-hosted | username and password (ROPC) | same as D | an MFA- and Conditional-Access-exempt, cloud-only account | only with security sign-off |
- An account to run as. Pro or PPU license. Workspace Viewer gives the inventory; Contributor (or
Member/Admin) is needed for model backups over XMLA, report downloads, DAX expressions and dataflow contents.
Give it access to every workspace you want documented. Keep it out of the Fabric administrator role unless you
want
-IncludeAdminApis. - Tenant and capacity settings (Power BI admin portal): Download reports on (report backups), Allow XMLA
endpoints on and the capacity's XMLA Endpoint set to Read or Read Write (model backups on dedicated capacity),
Semantic Model Execute Queries REST API on (the DAX fallback and usage metrics). Missing settings do not stop
the run; the affected items are recorded in the
Failuressheet. - The machine (Options A, B, C): Windows 10/11 or Server 2016+, Windows PowerShell 5.1 (built in) or
PowerShell 7. Tabular Editor 2 and pbi-tools are included under
Config\and need no installation; Power BI Desktop on the machine lets pbi-tools read models embedded in Pro-workspace PBIX files. Outbound HTTPS to the Power BI endpoints of your cloud and, for tool updates, togithub.com(or use-SkipToolUpdate). - The cloud. Decide the
-Environmentvalue:Public(commercial),USGov(GCC),USGovHigh(GCC High),USGovMil(DoD),China. AliasesGCC,GCCHigh,DoDwork too. Every URL the tool uses follows this value and the resolved hosts are printed at the top of each run (see Clouds and endpoints). - Get the files. Download this repository into one folder on the machine that will run it (or into the Azure
Repos project for Options C, D, E). That folder is the base folder: it holds
Config\,State\,Logs\and, by default, the backups and the workbooks. - Do one interactive run first (Option A) against a small workspace. It confirms the account, the settings and the tools before anything is scheduled, and it shows you what the outputs look like.
- Download the repository into a folder, for example
C:\ImpactIQ. - Run
Final PS Script.txt(rename to.ps1, or paste it into a PowerShell window opened in that folder). The launcher findsImpactIQ.ps1next to itself. - Choose the environment, the tenant if your account belongs to several, sign in in the browser, choose the run mode and the workspaces, reports or models.
- When it finishes, open
Power BI Governance Model.pbit, pointBase DirectoryatC:\ImpactIQ\Outputs, refresh, save as.pbix. - Re-run whenever you want fresh data. A run interrupted the same day resumes;
-ForceonImpactIQ.ps1starts the day over.
Want the same without the launcher? ImpactIQ.ps1 -AuthMode Interactive -Environment USGov opens the same dialogs;
add -WorkspaceName "Finance*" to skip the picker.
Runs nightly on a workstation or a server as a user who signed in once. Nothing leaves the machine.
- Download the repository into a folder the scheduled user can write to, for example
C:\ImpactIQ. - Decide the scheduled identity: a service account with the licenses and roles from Before you start, or your own account. The bootstrap in step 3 must run as that identity: the token cache is protected with Windows DPAPI for that user on that machine.
- Bootstrap the sign-in once, in a PowerShell window running as the scheduled user (use
runasfor a service account):The console printspowershell -NoProfile -ExecutionPolicy Bypass -File "C:\ImpactIQ\ImpactIQ.ps1" -NonInteractive -Environment USGov -AuthMode DeviceCode -Stages Inventory -WorkspaceName "Finance"
DEVICE CODE SIGN-IN REQUIRED ... https://microsoft.com/devicelogin ... code XXXXXXXXX. Complete it within 15 minutes. The refresh token is now cached inState\auth\token-cache.json. - Run the same command again: it must not ask for a code. If it does, the bootstrap ran as a different user.
- Create the task (Task Scheduler > Create Task): run as the same user, Run whether user is logged on or not,
Do not store password unchecked, trigger daily at a quiet hour. Action:
Add
Program: powershell.exe Arguments: -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "C:\ImpactIQ\ImpactIQ.ps1" -NonInteractive -Environment USGov -AuthMode DeviceCode -AllWorkspaces -IncludeMyWorkspace Start in: C:\ImpactIQ-BackupFolder "D:\PBI Backups"or-OutputFolder "\\server\share\ImpactIQ"to move the data; add-ModelDetailMethod Daxif the machine cannot run Tabular Editor. - Check the result: the task's Last Run Result is the exit code (
0ok,2finished with item failures,3paused by a time budget,1fatal). Details are inLogs\ImpactIQ_<timestamp>.logand theFailuressheet. - Connect the template: open the
.pbiton the machine (or on any machine that can read the output folder), setBase Directoryto theOutputsfolder, refresh, publish. For a scheduled refresh in the Service, see Connecting the Power BI Governance Model. - Every ~90 days (or after a password change or a Conditional Access change) the log says
invalid_grant: repeat step 3.
Any domain-joined Windows machine that stays on can host the free self-hosted agent. You get run history, artifacts, a Summary tab with the stage table, no job time cap, native Tabular Editor and pbi-tools, and no secret stored in Azure DevOps.
- Put the repository in Azure Repos (import this repository or push a clone). The repository root is the base
folder; the pipeline passes it as
-BaseFolder $(Build.SourcesDirectory). - Create the agent pool and install the agent on the Windows box, as an administrator:
# Project settings > Agent pools > Add pool "ImpactIQ" (self-hosted) > New agent > download the zip mkdir C:\azagent; cd C:\azagent; Expand-Archive ~\Downloads\vsts-agent-win-x64-*.zip . .\config.cmd --unattended --url https://dev.azure.com/<org> --auth pat --token <one-time PAT with Agent Pools (read, manage)> ` --pool ImpactIQ --agent $env:COMPUTERNAME --runAsService --windowsLogonAccount 'DOMAIN\svc-impactiq' --windowsLogonPassword '<pwd>'
svc-impactiqis the account from Before you start; it owns the DPAPI token cache and the module install. - Install ImportExcel once as that account (
Install-Module ImportExcel -Scope CurrentUser) if the box cannot reach the PowerShell Gallery during runs; otherwise the pipeline installs it. - Create the pipeline: Pipelines > New pipeline > Azure Repos Git > this repo > Existing Azure Pipelines YAML
file >
/pipelines/azure-pipelines.yml> Save. In the YAML (or the run dialog) setpool: { name: ImpactIQ },timeoutInMinutes: 0,restoreState: false(the agent workspace persists, so an older artifact must never overwrite it). - Bootstrap the sign-in through a manual run: Run pipeline >
authModeDeviceCode,environmentUSGov,workspaceNamesa small pattern such asFinance*,stagesInventory,Assemble. Open the run, expand Run ImpactIQ, complete the device code from the log within 15 minutes. Because the job runs assvc-impactiq, the DPAPI cache is created for the right account. Optional: store a Teams/Slack incoming webhook as the secret variableIMPACTIQ_DEVICECODE_WEBHOOKand the code is posted there too. - Run it once more by hand with the full scope (
workspaceNames*,stagesempty,extraArgs-IncludeMyWorkspace). It must not ask for a code. Check the Summary tab and theimpactiq-outputsartifact. - Turn on the schedule. The YAML schedules weekdays at 06:00 UTC with
always: true; edit the cron line to taste. Keep the interval longer than a run, or keep one agent in the pool so a second run queues. - Get the workbooks into Power BI: set
commitOutputs: trueso each run pushes the four workbooks to thedatabranch, then follow Connecting the Power BI Governance Model. On a self-hosted agent you can instead copy them to a folder the template reads (sharePointSyncPath, or-OutputFolderthroughextraArgs). - Re-bootstrap (step 5) when the log says
invalid_grant: roughly every 90 idle days, after a password change or a Conditional Access change.
Prefer an Az PowerShell login on the box? Run Connect-AzAccount -UseDeviceAuthentication and
Enable-AzContextAutosave -Scope CurrentUser once as the agent account and use authMode AzContext
(GCC uses the default AzureCloud environment; GCC High and DoD need -Environment AzureUSGovernment).
Zero infrastructure. A human completes the device code once; the refresh token is encrypted with a key you keep in
Azure DevOps and travels between runs inside the impactiq-state artifact.
- Put the repository in Azure Repos (as in Option C step 1).
- Buy one Microsoft-hosted parallel job (Organization settings > Parallel jobs) unless the tenant is small.
The free tier caps a job at 60 minutes; a paid job allows 360. ImpactIQ chains runs beyond that, but every run
must end on its own, so
timeBudgetMinutesis required:55on the free tier,350with a paid job. - Create the cache key and store it as a secret pipeline variable
IMPACTIQ_TOKEN_CACHE_KEY(Edit > Variables, lock icon), or in a variable group named in thevariableGroupparameter:Optional secret[Convert]::ToBase64String((1..48 | ForEach-Object { Get-Random -Maximum 256 }) -as [byte[]])
IMPACTIQ_DEVICECODE_WEBHOOK(Teams/Slack incoming webhook) andIMPACTIQ_TENANT_IDfor guest accounts. - Set run retention (Project settings > Pipelines > Settings > Days to keep runs) to more than the longest gap between two scheduled runs: the state and the token cache are restored from the previous run's artifact.
- Create the pipeline from
/pipelines/azure-pipelines.yml(Option C step 4) and keep the defaultpool: vmImage: windows-latest,timeoutInMinutes: 360,restoreState: true. - Bootstrap the sign-in through a manual run:
authModeDeviceCode,environmentUSGov,timeBudgetMinutes55or350,workspaceNamesa small pattern,stagesInventory,Assemble. Complete the device code from the Run ImpactIQ step log (or the webhook message) within 15 minutes. The run publishes the encrypted cache insideimpactiq-state; the Stage artifacts log saysToken cache included. - Run once more by hand with the full scope; it must not ask for a code. A large tenant ends with exit
3(Paused, orange run) and partial workbooks; the next run resumes it. - Turn on the schedule (Option C step 7). Each scheduled run restores the previous state, refreshes the token
silently, continues or starts a fresh day, and publishes
impactiq-state,impactiq-outputs,impactiq-logs(andimpactiq-backupswhenpublishBackups: true). - Get the workbooks into Power BI with
commitOutputs: trueand the Azure Repos pattern below. Hosted agents have no OneDrive client, so SharePoint sync is not an option here. - Watch for
invalid_grant/new device-code flowin the log: repeat step 6. Watch for runs Canceled at the cap: that meanstimeBudgetMinutesis missing or too high, and the next run cannot restore the cancelled run's state.
Things that break this option: a Conditional Access named-location policy (hosted agents use public Azure IP ranges), a tenant setting that blocks public internet access, and agency rules that forbid hosted agents processing GCC data. In those cases use Option C.
Fully unattended with nothing to re-bootstrap, at the price of an account that is exempt from MFA and Conditional Access. Microsoft is retiring the password grant; expect this to stop working one day.
- Steps 1, 2, 4 and 5 of Option D.
- Create a cloud-only service account (password-hash sync or pass-through auth; federated accounts cannot use the password grant), license it, give it the workspace roles, and have security exclude it from MFA and Conditional Access.
- Store
IMPACTIQ_USERNAMEandIMPACTIQ_PASSWORDas secret pipeline variables. - Run the pipeline by hand with
authModeCredential.AADSTS50076,50079,53003or65001in the log mean the account is still MFA- or CA-bound; there is no workaround inside the tool, switch to Option C or D. - Schedule it and connect the template as in Option D.
Power BI Governance Model.pbit reads the four workbooks through the parameters UseWeb, Base Directory,
Base Model File, Base Report File, Base Environment File and Base Dataflow File. The same model is also
kept as a Power BI Project under PBI\ (BIGovernanceReport.pbip, TMDL) so the queries can be reviewed and
diffed; there Base Directory is a query in the Base Directory group rather than a parameter - edit its
else branch to point at the Outputs folder.
Blank cells: Export-Excel writes an empty string as an empty cell, which Power Query reads as null, so a
table, column or relationship row has a null Expression, and a measure the account may only view has one too
(DAX path). Every Text.* call in the model on such a column is null-guarded (tests\Pbip.Tests.ps1 checks
this); keep the guard when you add steps.
- Local files (Options A, B):
UseWeb = false,Base Directory= theOutputsfolder (or your-OutputFolder). Refresh in Desktop. The Service can refresh a local folder only through an on-premises data gateway installed on that machine. - Azure Repos with a read-only PAT (Options C, D, E; no gateway): set
commitOutputs: trueso the pipeline pushesoutputs\*.xlsxto thedatabranch. One-time: give<Project> Build Service (<Org>)Contribute and Create branch on the repo, create an org-scoped PAT with Code (Read) only, and change the template's queries toWeb.Contents("https://dev.azure.com/<org>/", [RelativePath = ..., Query = ...])as shown in docs/Azure-DevOps.md section 6.1. The first argument must stay static, that is what lets the Service refresh it as a cloud source. Credentials: Basic, password = the PAT. Schedule the dataset refresh after the pipeline's usual end time and rotate the PAT before it expires. - SharePoint / OneDrive:
UseWeb = true,Base Directory= the library folder URL (sharepoint.usin GCC), Organizational account. Getting the files there without a service principal needs a self-hosted agent running interactively with the OneDrive client (sharePointSyncPath). See docs/Azure-DevOps.md sections 6.2 and 7.
- Exit codes:
0clean;2finished with item failures (open theFailuressheet or the pipeline Summary tab; the next run retries them);3paused by the time budget (the next run continues);1fatal (sign-in, no scope, inventory failure; the log says which). - Resume rules: the same day resumes automatically; an unfinished run from the last three days is picked up by
-Resume Auto;-Forcewipes today's state and backup folders;-Stages Assemble -Resume Alwaysrebuilds the workbooks from the last run without any API call. - Refresh token: 90 days of inactivity, a password change, an admin revoke sessions or a new Conditional
Access policy end it. The log says
invalid_grant; redo the bootstrap step of your option. - Throttling:
429storms mean fewer workspaces per run,-MaxParallelExtracts 1, or keeping-IncludeAdminApisout of business hours; the tool already honoursRetry-After. - Tool updates: Tabular Editor 2 and pbi-tools are refreshed from GitHub at the start of each run unless
-SkipToolUpdate/IMPACTIQ_OFFLINE=1. - Two runs at once against the same base folder are not supported. Keep the schedule interval longer than a run.
- Windows validation: the automated tests run on Linux with mocked APIs;
docs/Validation-Report.mdsection 4 lists what to confirm on a Windows box the first time (5.1 runtime, the C# extractor scripts, pbi-tools, DPAPI).
<base folder> (the folder ImpactIQ.ps1 runs from; -BaseFolder / IMPACTIQ_BASE_FOLDER)
ImpactIQ.ps1, Final PS Script.txt, Power BI Governance Model.pbit
Config\ csx scripts, Blank Model.bim, TabularEditor\, PBI Tools\, Modules\, SheetContract.json
State\runs\<yyyy-MM-dd>\ manifest.json, per-item checkpoints, inventory JSON, DAX and dataflow extracts, tool logs
State\auth\token-cache.json encrypted refresh token (DeviceCode)
Logs\ImpactIQ_<timestamp>.log
Outputs\ everything a run produces (set Base Directory in the .pbit to this folder)
Model Backups\<yyyy-MM-dd>\ <Workspace> ~ <Model>.bim, .csv } -BackupFolder / IMPACTIQ_BACKUP_FOLDER
Report Backups\<yyyy-MM-dd>\ <Workspace> ~ <Report>.pbix|.rdl, *.txt } moves these three
Dataflow Backups\<yyyy-MM-dd>\ <Workspace> ~ <Dataflow>.txt|.pq }
Power BI Environment Detail.xlsx, Report Detail.xlsx, } -OutputFolder / IMPACTIQ_OUTPUT_FOLDER
Model Detail.xlsx, Dataflow Detail.xlsx } moves these four
Config\, State\ and Logs\ always stay in the base folder; everything a run produces goes under Outputs\. A
relative -BackupFolder Data is created under the base folder; an absolute path or a UNC share works too. Keep the same folders between the runs of one day: the
checkpoints record where each file was written.
-Environment (or IMPACTIQ_ENVIRONMENT) selects one row; every REST, sign-in, token, XMLA, Fabric and portal URL
comes from it, and the run prints the resolved hosts in its first lines.
-Environment |
Portal | REST API | Sign-in authority | XMLA | Fabric API |
|---|---|---|---|---|---|
Public (aliases Commercial, Global) |
app.powerbi.com | api.powerbi.com | login.microsoftonline.com | powerbi://api.powerbi.com | api.fabric.microsoft.com |
USGov (alias GCC) |
app.powerbigov.us | api.powerbigov.us | login.microsoftonline.com | powerbi://api.powerbigov.us | not offered; detected and skipped |
USGovHigh (alias GCCHigh) |
app.high.powerbigov.us | api.high.powerbigov.us | login.microsoftonline.us | powerbi://api.high.powerbigov.us | unverified; -FabricApiPrefixOverride |
USGovMil (alias DoD) |
app.mil.powerbigov.us | api.mil.powerbigov.us | login.microsoftonline.us | powerbi://api.mil.powerbigov.us | unverified; -FabricApiPrefixOverride |
China |
app.powerbi.cn | api.powerbi.cn | login.chinacloudapi.cn | powerbi://api.powerbi.cn | api.fabric.microsoft.cn |
Germany (retired cloud, kept for compatibility) |
app.powerbi.de | api.powerbi.de | login.microsoftonline.de | powerbi://api.powerbi.de | api.fabric.microsoft.de |
GCC tenants sign in through commercial Entra ID (login.microsoftonline.com); only the Power BI hosts change. GCC High
and DoD use login.microsoftonline.us and, for AzContext, the AzureUSGovernment environment.
XMLA token audience. The token handed to Tabular Editor for XMLA exports is minted for the environment's Power BI
resource (GCC: https://analysis.usgovcloudapi.net/powerbi/api). If the XMLA endpoint answers Authentication
failed for all authenticators although the workspace is on a dedicated capacity, the first such failure of a run
tries the other combinations once (the commercial audience https://analysis.windows.net/powerbi/api, and the
Password= form without User ID=) and uses the accepted one for the remaining models, logging the
-XmlaTokenResource value to pin. tools\Test-IQXmlaAccess.ps1 -Environment USGov -WorkspaceName X -DatasetName Y
runs the same probe against one model in about two minutes without a full run. When no variant is accepted, the
remaining causes are outside the tool: the capacity's XMLA Endpoint setting (Read or Read Write), the tenant
setting Allow XMLA endpoints and Analyze in Excel with on-premises semantic models, and Build permission on the
model. The service's own usage-metrics models are skipped up front (XMLA is never granted on them). Where Fabric is not
offered, the first refused token or unreachable host marks Fabric unavailable for the run and the Fabric-only sheets
stay empty; nothing else is affected. Token resources and the full table are in
docs/Auth-Options.md section 3.
The most used parameters of ImpactIQ.ps1; every one has an environment-variable twin for schedulers that cannot
pass arguments (full list in docs/Headless-and-Resume.md).
| Parameter | Variable | Meaning |
|---|---|---|
-BaseFolder |
IMPACTIQ_BASE_FOLDER |
deployment folder; default: where the script runs from |
-BackupFolder, -OutputFolder |
IMPACTIQ_BACKUP_FOLDER, IMPACTIQ_OUTPUT_FOLDER |
move the backups / the workbooks; default: Outputs\ under the base folder |
-Environment |
IMPACTIQ_ENVIRONMENT |
Public, USGov/GCC, USGovHigh/GCCHigh, USGovMil/DoD, China |
-AuthMode |
(see variables below) | Auto, Interactive, DeviceCode, Credential, AzContext, AccessToken |
-TokenCacheKey |
IMPACTIQ_TOKEN_CACHE_KEY |
AES key for the refresh-token cache on hosted agents (DPAPI on Windows without it) |
-DeviceCodeWebhookUrl |
IMPACTIQ_DEVICECODE_WEBHOOK |
Teams/Slack webhook that receives the device code |
-Credential |
IMPACTIQ_USERNAME, IMPACTIQ_PASSWORD |
Credential mode (MFA-exempt accounts only) |
-NonInteractive |
automatic under TF_BUILD / CI |
no dialogs, no browser; no scope = stop |
-AllWorkspaces, -WorkspaceName, -WorkspaceId, -IncludeMyWorkspace |
scope in Workspaces mode (-WorkspaceName takes -like wildcards) |
|
-RunMode Reports -ReportId ..., -RunMode Models -DatasetId ... |
scope by report or model; connected objects are added automatically | |
-ExcludeWorkspaceId, -ExcludeWorkspaceName |
workspaces never scanned, whatever selects them (ids, or -like name patterns) |
|
-NoQuarantine |
ignore Config\ReportExportQuarantine.csv and State\report-memory.json for this run (see below) |
|
-NoKeepAwake |
do not stop Windows from sleeping during the run (on by default) | |
-NoWebUiExportFallback, -WebUiClusterHost |
turn off (or pin the cluster host for) the web-UI export used when the Export API refuses a large-storage-format report | |
-SettingsPath |
IMPACTIQ_SETTINGS_PATH |
settings file; default Config\ImpactIQ.Settings.json (see below) |
-XmlaTokenResource, -NoXmlaProbe |
IMPACTIQ_XMLA_RESOURCE |
pin the token audience Tabular Editor uses for XMLA exports / do not probe other audiences after an authentication failure (see Clouds and endpoints) |
-Stages, -SkipStages |
Inventory, ModelBackup, ReportBackup, ReportDetail, ModelDetail, Dataflows, Extras, Assemble |
|
-Resume Auto|Always|Never, -Force, -RefreshInventory |
resume rules | |
-TimeBudgetMinutes |
stop cleanly N minutes after start, exit 3, resume next run |
|
-ModelDetailMethod |
Auto, TabularEditor, Bim, Dax, Both |
|
-IncludeUsageMetrics, -IncludeAdminApis, -ActivityDays |
optional extra sheets | |
-SkipToolUpdate |
IMPACTIQ_OFFLINE=1 |
no Tabular Editor / pbi-tools downloads |
-Verbose |
IMPACTIQ_DEBUG=1 |
echo Debug lines (always in the log file) |
Config\ImpactIQ.Settings.json holds defaults for any parameter you do not want to type every time. Keys are the
parameter names; precedence is parameter, then environment variable, then the settings file, then the built-in
default. Copy Config\ImpactIQ.Settings.example.json to start:
{ "Environment": "USGov", "WorkspaceName": ["Finance*", "HR"], "ExcludeWorkspaceName": ["*Sandbox*"], "MaxRetries": 7 }Lists take JSON arrays, switches take true/false. BaseFolder, SettingsPath, Credential, TokenCacheKey,
Force and RunId are never read from the file; an unknown key or a value outside a parameter's allowed set is
reported and ignored. In an interactive run Environment only pre-selects the environment dialog (so you can still
change clouds), and the environment you pick is written back. A scope in the file (WorkspaceName, WorkspaceId,
ReportId, ...) skips the interactive pickers, exactly like the same parameters on the command line.
ImpactIQ.bat wraps all of this for a double-click: --no-prompts (no dialogs; scope and cloud from the settings
file, variables or extra parameters), --resume, --fresh, --environment NAME, --settings FILE, --help;
anything else is passed to ImpactIQ.ps1 unchanged.
Two files remember what the service will never give you, so later runs do not spend the calls:
Config\ReportExportQuarantine.csvlists reports that are skipped by the ReportBackup stage. ColumnsReportId, ReportName, WorkspaceName, Reason, IsActive;ReportNameandWorkspaceNametake-likewildcards, an emptyWorkspaceNamematches every workspace. It ships with one row that excludes the service's own*Usage Metrics Report*reports, and the tool appends a row itself when the Export API refuses a report for good (401/403ModelExportActionDenied, or no PBIX behind the item). SetIsActivetofalseor delete the row to retry.State\report-memory.jsonremembers reports whose PBIX holds no embedded model (pbi-tools exit code -8: live connection or service-authored report), so the extraction is not repeated. Delete the file to forget.
When the Export API refuses an IncludeModel download, the report is retried as LiveConnect (layout without the
model), which keeps ReportDetail working; ModelDetail then reads that model over DAX.
When the Export API refuses a report because its model uses the large semantic model storage format (HTTP 400
PremiumFiles) and Fabric getDefinition is not available either (GCC), ImpactIQ retries through the endpoint the
Power BI portal itself uses for Download this file: https://<report cluster>/export/v202402/reports/<id>/pbix,
polled until it hands out a download URL. The cluster host comes from the report URL's redirect
(wabi-<region>-redirect.analysis.<cloud>); -WebUiClusterHost pins it. This is not a documented API, so it is used
only after that exact refusal and -NoWebUiExportFallback turns it off. Exports made this way are recorded with
method WebUI.
Examples:
# everything the account can see, GCC, unattended, resumes an unfinished run automatically
.\ImpactIQ.ps1 -NonInteractive -Environment USGov -AuthMode DeviceCode -AllWorkspaces -IncludeMyWorkspace
# two workspace families, backups on a share, workbooks where the template reads them
.\ImpactIQ.ps1 -NonInteractive -Environment GCC -WorkspaceName 'Finance*','HR' -BackupFolder '\\files\PBI Backups' -OutputFolder 'D:\Governance'
# specific reports (their models and model workspaces are added automatically)
.\ImpactIQ.ps1 -NonInteractive -Environment Public -RunMode Reports -ReportId <guid>,<guid>
# rebuild the four workbooks from the latest run without any API call
.\ImpactIQ.ps1 -NonInteractive -Resume Always -Stages Assemble
# run the quality gate (parser, PSScriptAnalyzer, Pester; no tenant needed)
pwsh -NoProfile -File .\tests\Invoke-Tests.ps1| Page | Read it when |
|---|---|
| docs/Automation.md | you want the decision matrix and the five-minute setups behind the walkthroughs above |
| docs/Auth-Options.md | you need to decide how a scheduled run signs in, or you are on a GCC / sovereign tenant |
| docs/Azure-DevOps.md | pipeline parameters, secrets, hosted vs self-hosted, artifacts and resume, Web.Contents for the template, troubleshooting |
| docs/Headless-and-Resume.md | every parameter and variable, the state layout, resume rules, exit codes, the time budget |
| docs/Data-Coverage.md | which sheet comes from which API, what permission it needs, what the optional flags add, what is empty in GCC |
| docs/Validation-Report.md | the v2 audit findings, what v3 fixed, and what still needs a Windows run to confirm |
| tests/README.md | running the Pester suite on Windows PowerShell 5.1 or PowerShell 7 |
⚙️ PowerShell may prompt to install required modules. No admin access is needed; they install at the user level (
ImportExcel;MicrosoftPowerBIMgmtonly for the interactive browser sign-in).
🧰 This setup uses the portable version of Tabular Editor 2 (v2.27.2). You don't need it preinstalled. It runs locally from the folder with no differences. https://github.com/TabularEditor/TabularEditor (MIT License)
🧠 Model backups use XMLA (for PPU, Premium, Fabric). For Pro workspaces,
pbi-toolsextracts the BIM from the PBIX. Includespbi-tools v1.2: https://github.com/pbi-tools/pbi-tools (AGPL 3.0 License) Without either,-ModelDetailMethod Daxdocuments the model over the REST API.
🚨 Using Tabular Editor 3? Tabular Editor 2 is still included and required for this because TE3 doesn't support command line execution.
🧩 Model refresh error in Power BI Desktop? If you see: "Query XXXXXX references other queries or steps..."
Update your Power BI Desktop privacy settings: File → Options and settings → Options → Privacy Then select either:
- "Combine data according to each file's Privacy Level settings" or
- "Always ignore Privacy Level settings"
- Leverages Power BI REST API to gather information about Power BI workspaces, datasets, reports, report pages, apps, dashboards, tiles, users, parameters, refresh schedules and capacities.
- Exports the extracted metadata into a structured Excel workbook with separate worksheets for each entity.
- You must have at least read access within workspaces. 'My Workspace' also included.
-
- Saves exported models in a structured folder hierarchy based on workspace and dataset names.
- Leverages Tabular Editor 2 and C# to extract the metadata and output within an Excel File; the built-in
.bimparser or DAXINFO.VIEW.*queries take over where Tabular Editor cannot run. - All backups are saved with the following format: Workspace Name ~ Model Name.
- You must have edit rights on the related model. Works with all Pro, Premium-Per-User, Premium, and Fabric Capacity workspaces. 'My Workspace' also included. Both XMLA and non-XMLA models.
- Backs up Power BI and Paginated Reports from Power BI workspaces, cleaning report names and determining file types (
.pbixor.rdl) for export. - Leverages Tabular Editor 2 and C# to extract the Visual Object Layer metadata and output within an Excel File (credit to @m-kovalsky for initial work on this)
- Paginated Reports are only backed up (no metadata extraction).
- All backups are saved with the following format: Workspace Name ~ Report Name.
- You must have edit rights on the related report. Works with all Pro, Premium-Per-User, Premium, and Fabric Capacity workspaces. 'My Workspace' also included.
-
- Extracts dataflows from Power BI workspaces, formatting and organizing their contents, including query details.
- Leverages PowerShell to parse and extract the metadata and output within an Excel File.
- All backups are saved with the following format: Workspace Name ~ Dataflow Name.
- Must have edit rights on the related dataflow. 'Ownership' of the Dataflow is not required. Works with all Pro, Premium Capacity, Fabric Capacity workspaces. 'My Workspace' also included.
-
- Leverages Power BI REST API to gather all model connection details.
- Exports the extracted metadata into the same structured excel workbook as the Power BI Environment Information Extract
- You must have read permissions on the related model.
- Leverages Power BI REST API to gather all model refresh history (limited to the same history shown in the Service).
- Exports the extracted metadata into the same structured excel workbook as the Power BI Environment Detail Extract
- You must have read permissions on the related model.
- Leverages Power BI REST API to gather all model refresh schedule settings including enabled status, time zone, schedule days, and times (import and DirectQuery schedules).
- Exports the extracted metadata into the same structured excel workbook as the Power BI Environment Detail Extract
- You must have read permissions on the related model.
- Leverages Power BI REST API to gather all Dataflow connection details.
- Exports the extracted metadata into the same structured excel workbook as the Power BI Environment Detail Extract
- You must have read permissions on the related Dataflow.
- Leverages Power BI REST API to gather all Dataflow refresh history (limited to the same history shown in the Service).
- Exports the extracted metadata into the same structured excel workbook as the Power BI Environment Detail Extract
- You must have read permissions on the related Dataflow.
- Combines extracts into a Semantic Model to allow easy exploring, impact analysis, and governance of all Power BI Reports, Models, and Dataflows across all Workspaces
- Works for anyone who runs the script and has at least 1 model and report. Dataflow not required.
- Public example (limited due to no filter pane): https://app.powerbi.com/view?r=eyJrIjoiNmMxYWQ2ZTItZDM4ZS00MGM1LTlhMDQtN2I1OTMwMzI0OTg2IiwidCI6ImUyY2Y4N2QyLTYxMjktNGExYS1iZTczLTEzOGQyY2Y5OGJlMiJ9
- Tokens are refreshed silently before they expire; the v2 rule of signing in again every 55 minutes is gone.
- The run defaults to what you select. Headless,
-AllWorkspacesscans everything;-WorkspaceName,-WorkspaceId,-ReportIdor-DatasetIdnarrow it; with nothing selected a headless run stops rather than scanning the tenant by accident. - For the best user experience, the final Power BI Governance Model output is from the perspective of the Report. This means that when looking at a Workspace where Reports have the Model sitting in a different Workspace (i.e. multiple reports connected to a model in a different workspace), the Model detail will still be viewable. This ensures you get a comprehensive view of any report. This does not work both ways: when viewing a Workspace with only Models and no Reports, it will only show the Model detail since there are no Reports within that Workspace. If you do not want this perspective and prefer that Model detail only show in the Workspaces they are in, then set the All-Pages filter "Model in Workspace Flag" to TRUE.
- For backing up Reports & extracting the metadata, this mirrors what you can do at powerbi.com. This means that if you cannot download the report online, then the script will also not be able to download it. For Models, this works differently and if it's within a Premium, PPU, or Fabric capacity, even XMLA-only models can be backed up and extracted by leveraging the XMLA endpoint connection.
.. ..