Skip to content
Back to Blog
12 min read

Fabric Governance as Automation: Building on the Admin, Scanner, and REST APIs

The Fabric admin portal is one interface over the governance model — not the model itself. Every toggle, workspace listing, and scan result it renders is backed by REST and admin APIs that a service principal can call directly. Governance automation should therefore treat the portal as a human-readable view and operate on the same underlying endpoints: the Power BI/Fabric admin APIs, the scanner (WorkspaceInfo) APIs, and ARM for capacity. This article shows how to build governance-as-automation on those APIs, with least-privilege identity separation as a first-class design constraint.

Fabric tenant estate workspaces · items · capacities domains · owners · sensitivity Git manifest INTENDED STATE Actual state inventory · scan · capacity FUAM Lakehouse Drift detection actual vs intended → CONTROL CATALOGUE Remediation SCOPED UPDATE SPN tightly bounded · audited read-only SPN diff
Figure 1. Governance as a reconciliation loop. A read-only service principal reads the Fabric estate through the admin, scanner (WorkspaceInfo), and ARM APIs into an actual-state store (here, a FUAM Lakehouse); a Git manifest defines intended state; drift detection yields a control catalogue; and remediation runs through a separately scoped update service principal. Icons: official Microsoft Fabric icons.

Service principal model

Fabric gates programmatic admin access behind tenant settings that map to Entra security groups. There are two distinct toggles under Admin API settings, and treating them as one is the first governance mistake to avoid.

The first is Service principals can access read-only admin APIs. A service principal must be a member of an allowed security group; membership grants read-only access to all information available through admin APIs, current and future — user names and emails, semantic model and report detailed metadata included. This is a broad grant, so the group backing it should contain only inventory and scanning identities.

The second is Service principals can access admin APIs used for updates, a separate toggle scoped to a separate security group. It applies to Fabric admin APIs that mutate state — the documented example is the Restore Workspace API (per the enablement docs). Note the naming: the portal heading reads “Service principals can access read-only admin APIs,” but the same page’s notes and older enterprise articles still use the legacy label “Allow service principals to use read-only admin APIs.” They are the same setting.

Each toggle is configured with a Specific security groups radio button and an explicit group added under it. Fabric admin rights are required to change either setting, and — importantly — an app used for service principal authentication against read-only admin APIs must not have any admin-consent-required Power BI permissions set on it in the Azure portal. Both service-principal settings’ notes add that each is also required to run Fabric data risk assessments in Microsoft Purview DSPM for AI.

The design principle follows directly: create two distinct Entra security groups, one per toggle, and put different service principals in each. A read-only inventory/scanner SPN never belongs in the update group. An update-capable SPN — which can restore (and by extension manipulate) workspaces tenant-wide — is a far larger blast radius and should be tightly scoped, separately credentialed, and used only by the specific remediation jobs that need it. The read-only grant is already broad (“all information … current and future”); the update grant is the one that changes the world.

Separately, calling Fabric APIs (as opposed to the Power BI admin surface) via the CLI requires the Allow service principals to use Fabric APIs tenant switch. Keep this distinct from the two admin-API toggles above.

Metadata scanning (Scanner API)

The scanner APIs — collectively the WorkspaceInfo APIs — are the tenant-wide metadata extraction surface. They require no special license, work across non-Premium workspaces, and support both public and sovereign clouds. There are four: GetModifiedWorkspaces, PostWorkspaceInfo, GetScanStatus, and GetScanResult. The scan flow chains them.

Step 1 — Enumerate

Call GetModifiedWorkspaces with no modifiedSince to get every workspace ID; with modifiedSince (constrained to a window of 30 minutes to 30 days prior, ISO 8601 UTC) to get only changed workspaces for incremental scans.

GET https://api.powerbi.com/v1.0/myorg/admin/workspaces/modified?excludePersonalWorkspaces=True
Authorization: Bearer <token>

Step 2 — Trigger

Divide the IDs into chunks and call PostWorkspaceInfo. The workspaces array supports 1 to 100 workspace IDs per call — so batch in groups of at most 100. The five boolean query params control depth: lineage, datasourceDetails, datasetSchema (tables, columns, measures), datasetExpressions (DAX and Mashup/M queries), and getArtifactUsers.

POST https://api.powerbi.com/v1.0/myorg/admin/workspaces/getInfo?lineage=true&datasourceDetails=true&datasetSchema=true&datasetExpressions=true&getArtifactUsers=true
Authorization: Bearer <token>
Content-Type: application/json

{
  "workspaces": [
    "b2f2b2e0-0000-0000-0000-000000000001",
    "b2f2b2e0-0000-0000-0000-000000000002"
  ]
}

The call returns 202 Accepted with a ScanRequest { "id": "<scanId>", "createdDateTime": "...", "status": "NotStarted" }. Critically, datasetSchema and datasetExpressions only return data if metadata scanning is fully enabled at the tenant level — set them true against a tenant without the enhance settings and the fields come back empty.

Step 3 — Poll

Poll GetScanStatus (recommended interval 30–60 seconds) until status is Succeeded.

GET https://api.powerbi.com/v1.0/myorg/admin/workspaces/scanStatus/<scanId>

Step 4 — Read

Call GetScanResult only after a successful status; the result remains available for 24 hours. The top-level WorkspaceInfoResponse contains workspaces, datasourceInstances, and misconfiguredDatasourceInstances. Each WorkspaceInfo carries reports, dashboards, datasets, dataflows, datamarts, users, tags, plus capacity and storage-format info. A WorkspaceInfoDataset exposes tables (with columns, measures, and an M source), expressions, RLS roles, endorsementDetails, and a sensitivityLabel with its labelId.

The two enhance settings

Table and column names appear in GetScanResult only when Enhance admin APIs responses with detailed metadata is on; DAX and mashup expressions appear only when Enhance admin APIs responses with DAX and mashup expressions is on. Both carry the same dependency note: for the setting to apply to a service principal, the read-only admin API setting must also be enabled. Enabling metadata scanning end-to-end is also a prerequisite for Fabric data risk assessments in Microsoft Purview DSPM for AI.

Governance use and limits

With detailed metadata and expressions enabled, the scan result is a tenant-wide index of where sensitive data lives: locate semantic models whose column names or DAX measures reference PII, read each model’s sensitivityLabel, and feed the inventory to Purview DSPM. This is the automation-native path to the same signal the portal surfaces.

Mind the gaps. Subartifact metadata is not returned for semantic models over 1 GB in shared (non-Premium) workspaces; Premium/Fabric-capacity workspaces have no such size cap. Models not refreshed or republished return name and lineage but no subartifact detail, and unsupported dataset types report the reason in a schemaRetrievalError field. Rate limits are real (all figures below as of July 2026 and subject to Microsoft revision): getInfo is capped at 500 requests/hour and 16 simultaneous, scanStatus at 10,000/hour, scanResult at 500/hour, and modified at 30/hour — wait for a succeed/failed status before issuing the next getInfo.

Inventory automation

Beyond the scanner, the admin REST surface gives you the actual-state inventory to reconcile against intended state. Two Fabric admin endpoints are the backbone.

List Workspaces returns every workspace with both capacityId and domainId in a single call, so capacity assignment and domain assignment are enumerable together. It supports filtering by capacityId, name, state (active/deleted), and type (personal, workspace, adminworkspace), and paginates up to 10,000 records per request via continuation token.

GET https://api.fabric.microsoft.com/v1/admin/workspaces?type=Workspace&state=active

List Items returns all active Fabric and Power BI items tenant-wide, each carrying workspaceId, capacityId, and creatorPrincipal — the owner. That ownership signal is the core of drift detection.

GET https://api.fabric.microsoft.com/v1/admin/items?type=SemanticModel&state=active

For domain reconciliation, List Domains returns every domain with its parentDomainId hierarchy, and List Domain Workspaces returns which workspaces are assigned to a given domain — letting you cross-check the workspace-level domainId against the domain-level assignment. Note that List Domains is a release version of a preview API; the preview form is deprecated on March 31, 2026, and callers must pass preview=false.

The older Power BI admin surface remains the workhorse for expanded ownership and content auditing. GetGroupsAsAdmin returns workspaces org-wide and can $expand users, reports, datasets, dashboards, dataflows, and workbooks inline; each AdminGroup exposes capacityId, isOnDedicatedCapacity, and pipelineId (deployment-pipeline linkage). It is heavily rate-limited — 50 requests/hour or 15/minute per tenant — so page deliberately.

Drift detection is the join. Pull actual state from these endpoints, compare against a Git-defined intended state (a manifest of expected workspaces, their capacities, domains, and owners), and emit deltas: workspaces present in the tenant but absent from the manifest, capacity or domain assignments that disagree with the manifest, or items owned by a creatorPrincipal outside the approved set. List Workspaces and List Items are Preview/pre-GA and rate-limited, so drift scripts must paginate and back off on 429/Retry-After.

Fabric CLI / REST usage

The Fabric CLI (fab) makes authenticated requests to Fabric REST APIs for automation. Its api command takes an endpoint and an -A/--audience flag selecting the base URL: fabricapi.fabric.microsoft.com (default), powerbiapi.powerbi.com, azuremanagement.azure.com (ARM), and storage → OneLake DFS. Other flags: -X (method), -i (JSON body, inline or file), -P (query params), -q (JMESPath filter), and --show_headers.

Authenticating without a signed-in user

In CI (for example GitHub Actions), prefer an OIDC federated token over a stored secret:

# Federated credential (no secret at rest)
fab auth login -u <client_id> --federated-token <token> --tenant <tenant_id>

# Certificate
fab auth login -u <client_id> --certificate /path/to/cert.pem --tenant <tenant_id>

# Managed identity (user-assigned)
fab auth login --identity -u <client_id>

Inventory and capacity calls

# List all workspaces
fab api workspaces

# Filter to true workspaces via JMESPath
fab api workspaces -q "value[?type=='Workspace']"

# Tenant-wide admin item scan, filtered by type and name
fab api "admin/items" -P "type=SemanticModel" -q "itemEntities[?contains(name, 'Sales')]"

Capacity listing via ARM — the azure audience against the Microsoft.Fabric provider requires the api-version query param:

fab api -A azure \
  subscriptions/<sub-id>/providers/Microsoft.Fabric/capacities?api-version=2023-11-01

The core Fabric surface also lists capacities directly at GET https://api.fabric.microsoft.com/v1/capacities (scope Capacity.Read.All). The Power BI audience remains available for workspace detail:

fab api -A powerbi groups
fab api -A powerbi groups/<workspaceId>

Scheduling governance scans

The scan flow above is what you schedule — a recurring job (Fabric Pipeline/Notebook, or an external scheduler) that runs GetModifiedWorkspaces incrementally with modifiedSince set to the last run, chunks into 100-workspace batches, triggers getInfo, polls, and persists each GetScanResult within its 24-hour availability window. Raw REST for the trigger, if you are not using the CLI:

curl -X POST \
  "https://api.powerbi.com/v1.0/myorg/admin/workspaces/getInfo?datasetSchema=true&datasetExpressions=true" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"workspaces": ["b2f2b2e0-0000-0000-0000-000000000001"]}'

Governance control catalogue

Each control is a scheduled join between an API-collected signal and the Git-defined manifest. Detection is automated; remediation is separated by whether it needs the read-only or update identity.

Control Data source / API Detection logic Remediation
Workspace not in manifest List Workspaces Workspace ID present in tenant, absent from Git manifest Alert governance owner; register or schedule removal (update SPN)
Workspace on wrong capacity List Workspaces (capacityId) capacityId ≠ manifest expected capacity Flag for reassignment; ticket to capacity owner
Semantic model DAX exposing PII GetScanResult + datasetExpressions Measure expression / column name matches PII patterns; sensitivityLabel missing Apply sensitivity label; feed to Purview DSPM
Orphaned / unused item GetUnusedArtifactsAsAdmin lastAccessedDateTime > 30 days Notify owner; archive or delete on policy
Guest / external user with access GetGroupsAsAdmin $expand=users User principal is external/guest, not on allowlist Review and remove access
Missing sensitivity label GetScanResult (sensitivityLabel.labelId) labelId absent on a dataset in scope Apply label via sensitivity labeling
Workspace in wrong domain List Domain Workspaces domainId ≠ manifest domain Reassign domain; alert domain admin

Closing the loop

Drift detection is a three-way reconciliation: actual state collected from the admin, scanner, and ARM APIs; intended state defined in Git; and usage/audit context from monitoring. The APIs above supply actual state on a schedule. The Git manifest is authoritative for what should exist. The delta is your control output.

Context comes from Fabric’s monitoring surfaces. The built-in admin monitoring workspace provides out-of-the-box reports on user activity, sharing, and capacity performance — but it is read-only, refreshes once daily, and can silently stop refreshing if the installing admin loses admin rights or relies on PIM without active elevation during the refresh window. Treat it as a convenience view, not a monitoring pipeline. For audit history, Get Activity Events returns tenant activity, but each call must fall within a single UTC day inside the last 28 days, so long-range pulls chunk day-by-day. All Fabric user activities are also logged to the Purview audit log.

For a holistic pipeline, FUAM (Fabric Unified Admin Monitoring) is an open-source solution accelerator in Microsoft’s public fabric-toolbox repo — explicitly not an official Microsoft product. It is built entirely with Fabric capabilities: Pipelines and Notebooks extract tenant settings, delegated tenant settings, activities, workspaces, capacities, capacity metrics, tenant metadata via the Scanner API, capacity refreshables, and Git connections into a Lakehouse, transform with PySpark, and serve Power BI reports over the SQL endpoint. That data model is precisely the cross-reference substrate this article’s controls need — actual inventory, capacity, and scanner metadata unified in one place to diff against intended state.

Least privilege and security boundary

The identity design is not incidental to governance automation — it is the governance boundary, because an update-capable admin SPN is one of the most powerful principals in the tenant.

Separate read from update

Maintain two Entra security groups mapped to the two admin-API toggles, and two service principals. The inventory/scanner SPN lives only in the read-only group; it can read all admin metadata but cannot mutate. The remediation SPN lives only in the update group. Never collapse them: the read-only grant already covers “all information … current and future,” and the update grant can restore and manipulate workspaces tenant-wide. Keeping them apart bounds the blast radius of a compromised inventory credential to disclosure rather than modification.

Credential storage

Prefer OIDC federated credentials (workload identity) so no secret sits at rest — the CLI’s --federated-token path supports exactly this in CI. Where a secret or certificate is unavoidable, store it in Key Vault and reference it at runtime; certificates are preferable to client secrets. Managed identity is available for Azure-hosted jobs. Remember the hard constraint: an app authenticating a service principal against read-only admin APIs must have no admin-consent-required Power BI permissions configured in Azure, and scanner calls under service principal auth send no Tenant.Read.All/Tenant.ReadWrite.All scope at all — those scopes apply only to delegated admin tokens.

Blast radius, network, and audit controls

Scope the update SPN to only the specific remediation jobs that require it, and gate those jobs behind change control. Because every Fabric user (and service principal) activity is captured in the Purview audit log and via Get Activity Events, treat the update SPN’s actions as high-signal events: alert on any activity it performs outside a scheduled remediation window. Run automation from controlled network egress, page through admin APIs with continuation tokens, and back off on 429/Retry-After — rate limits are low enough (GetGroupsAsAdmin at 50/hour, modified at 30/hour) that a poorly-bounded script both fails and looks like abuse. The portal will show you the same posture; automation, built on the same APIs with these boundaries, enforces it continuously.

References

Verified against Microsoft Learn (retrieved July 2026), the Microsoft Fabric CLI docs, and Microsoft’s fabric-toolbox (FUAM). Preview APIs (List Workspaces/Items, List Domains) and rate limits are subject to change — re-check before relying on them.

  1. Admin API settings — service principals & metadata (Microsoft Learn) · Enable service principals to use admin APIs
  2. Metadata scanning overview · PostWorkspaceInfo · GetScanStatus · GetScanResult · GetModifiedWorkspaces
  3. List Workspaces · List Items · List Domains · List Domain Workspaces
  4. GetGroupsAsAdmin · GetUnusedArtifactsAsAdmin · Get Activity Events
  5. Fabric CLI — api command · auth · auth examples
  6. Governance & compliance overview · Admin monitoring workspace · Purview + Fabric
  7. FUAM — Fabric Unified Admin Monitoring (microsoft/fabric-toolbox)
  8. Microsoft Fabric icons (official)
Michael John Peña

Michael John Peña

Senior Data Engineer based in Sydney. Writing about data, cloud, and technology.