
Picture this: your organization has grown from a handful of analysts sharing Excel files to a sprawling Power BI tenant with 400 datasets, 1,200 reports, and roughly nobody who can confidently answer the question "which sales dataset should I actually be using?" Finance uses Sales_Final_v3, Marketing built their pipeline funnel on Revenue_Actuals_2022_FIXED, and the executive dashboard pulls from something called SalesData_DO_NOT_DELETE. Every dataset tells a slightly different story, and quarterly business reviews have devolved into arguments about whose numbers are right rather than what to do about them.
This is the enterprise data trust problem, and it's more common than most organizations care to admit. Power BI's endorsement framework — comprising Promoted and Certified tiers, backed by sensitivity labels, workspace governance, and lineage tracking — gives you the technical scaffolding to solve it. But the scaffolding is only as good as the process you build around it. Most implementations get the clicks right and the governance wrong. In this lesson, we're going to build both: a coherent certification workflow that turns Power BI's endorsement features into a living, maintainable enterprise data catalog.
By the end of this lesson you will have designed and implemented a full-lifecycle dataset certification program, wired it into your organizational processes, and know how to maintain it at scale without it collapsing under its own administrative weight.
What you'll learn:
This lesson assumes you are working at an expert level. You should be comfortable with:
MicrosoftPowerBIMgmt moduleYou will need a Power BI Premium or Fabric capacity (or at least PPU licenses) for several features discussed here. Where a feature is capacity-gated, we'll note it explicitly.
Before you design a workflow, you need to understand what Power BI endorsement actually is at a technical level — not just "a green badge."
Power BI supports two distinct endorsement tiers that apply to datasets (now called semantic models in Fabric), dataflows, datamarts, and reports:
Promoted is self-service. Any workspace Admin or Member can promote their own artifact. It signals "this is worth paying attention to" without implying organizational validation. Think of it as a content creator saying "I stand behind this." There is no gating mechanism other than workspace role.
Certified is a governance control. It requires a Power BI administrator to explicitly grant certification rights to specific users or Entra ID security groups via the Admin Portal. When a user with certification rights marks a dataset as Certified, that status is stored as metadata on the artifact and is surfaced across discovery surfaces — search results, dataset hub, lineage view, and the Power BI REST API.
Here's what the certification metadata actually looks like when you query the Scanner API (more on that later):
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Enterprise Sales - Certified",
"endorsementDetails": {
"endorsement": "Certified",
"certifiedBy": "Rebecca Thornton"
},
"configuredBy": "data-engineering@contoso.com",
"isEffectiveIdentityRequired": false,
"targetStorageMode": "Import"
}
The certifiedBy field captures the display name of the user who clicked Certify — which is why you should never grant certification rights to individual named employees who might leave. Use security groups instead. We'll return to this when we discuss the permission model.
One architectural detail that bites people: endorsement is applied at the artifact level, not the workspace level. A workspace can contain both Certified and uncertified datasets. This is intentional — you want to be able to certify selectively — but it means workspace organization alone is not a substitute for endorsement. Some organizations create a "Certified" workspace and assume that implies certification of contents. It does not.
Endorsement answers "Is this trustworthy?" Sensitivity labels (from Microsoft Purview Information Protection) answer "How sensitive is this data?" They are orthogonal. A dataset can be Certified and labeled Highly Confidential. A dataset can be Promoted and Public. You should implement both, but they serve different governance purposes and have different administrative ownership — typically the data governance team owns endorsement while the information security team owns sensitivity labels.
The practical implication: your certification workflow should include a checkpoint for verifying that the appropriate sensitivity label is applied before certification is granted. Don't certify a dataset that contains PII but has no sensitivity label — that's a governance gap you've now officially blessed.
The biggest mistake organizations make is opening the Admin Portal, granting certification rights to a few senior analysts, and calling it a governance program. Six months later, you have 80 certified datasets — many of which haven't been refreshed in four months, several of which conflict with each other — and the certification badge has lost all meaning.
Certification only works if it's scarce and maintained. Here's a workflow architecture that scales to large organizations.
Dataset Owner: The team (not an individual) responsible for the dataset's accuracy, refresh schedule, and fitness for purpose. This should be mapped to an Entra ID group, not a person's name. The Dataset Owner initiates certification requests and is accountable for ongoing quality.
Domain Data Steward: A subject matter authority for a specific data domain (Finance, Operations, Customer, etc.) who validates that the dataset correctly represents the business concepts it claims to represent. They are not reviewing code — they are reviewing business logic and data definitions.
Data Governance Council (or equivalent): A cross-functional group that has final certification authority. In Power BI terms, members of this group (or the group itself) hold the certification rights granted by the tenant admin. They review the Domain Data Steward's sign-off and apply the Certified badge.
This separation of concerns matters. It prevents the person who built the dataset from also certifying it, which would be the governance equivalent of an author peer-reviewing their own paper.
Every dataset should pass through these gates before certification is granted. Document this as a formal checklist that travels with the certification request:
Gate 1: Technical Completeness
Gate 2: Business Validation
Gate 3: Governance Review
Warning: Do not skip Gate 2 just because the technical gates look clean. A technically perfect dataset with a wrong business definition is arguably worse than a messy uncertified dataset — because now you've put an official stamp of approval on incorrect numbers.
While certification is artifact-level, your workspace architecture should still support your governance model. A pattern that works well at scale:
Development Workspaces ([Domain]-Dev): Where datasets are built and iterated. No certification happens here.
Validated Workspaces ([Domain]-Validated): Where datasets that have passed Gates 1 and 2 are published pending final certification. Contains Promoted datasets awaiting upgrade to Certified.
Certified Workspaces ([Domain]-Certified): Holds only Certified datasets. Access controls here should be tighter — typically the workspace is Viewer-accessible for the broader organization but only the Dataset Owner group has Contributor rights.
Deprecated Workspaces ([Domain]-Deprecated): Certified datasets that have been superseded but cannot be immediately deleted due to downstream dependencies. These are un-certified and clearly labeled in their descriptions.
This workspace topology ensures consumers know where to look and gives your lineage tracking a predictable structure.
With your governance design in hand, let's implement it. Start in the Power BI Admin Portal.
Navigate to the Admin Portal and go to Tenant settings. Scroll to the Endorsement and discovery section. You'll find the following settings:
Certification: This is the key control. You can restrict certification to specific security groups. Create an Entra ID security group named something like PBI-CertificationAuthority and add only the members of your Data Governance Council to it. This group name will also appear in the dataset hub when users see who certified a dataset, so make it human-readable.
Featured content: Allows workspace admins to feature content on the Power BI home. This is separate from certification — don't conflate featured with certified.
Promote content: You can restrict who can promote content. For most organizations, leaving this open to workspace Admins and Members is appropriate — it's a low-stakes endorsement. If your organization has had problems with content sprawl, you can restrict it to specific groups.
Admin Portal → Tenant settings → Endorsement and discovery
├── Certification
│ └── Enabled for: Specific security groups
│ └── PBI-CertificationAuthority
└── Promote content
└── Enabled for: The entire organization
Tip: Create the
PBI-CertificationAuthoritysecurity group with a clear description explaining its purpose. Onboard new members through a formal process rather than ad-hoc addition. Consider making the group owner the head of your data governance function, not an IT admin.
Clicking through the Power BI UI to certify individual datasets works fine for small catalogs. At enterprise scale, you need programmatic control. The Power BI REST API exposes endorsement management through the UpdateArtifactAsFeaturedContentRequest pattern, but more usefully, the SetDatasetFeaturedContent and metadata update endpoints.
Let me walk you through the relevant API pattern for managing endorsement programmatically.
First, set up a service principal for your governance automation. In Entra ID, create an app registration named PBI-GovernanceAutomation. Grant it the following API permissions (Application permissions, not Delegated):
Tenant.Read.All — for Scanner API accessDataset.ReadWrite.All — for endorsement updatesAdd the service principal to your Power BI Admin Portal under Developer settings → Allow service principals to use Power BI APIs.
Warning: Do not add the service principal directly to the
PBI-CertificationAuthoritysecurity group. Programmatic certification via API should be a separate controlled surface from human certification decisions. Use the API to report and audit certification status, and to remove stale certifications via automated governance — but human review should still precede the initial certification click.
The Scanner API (also called the Admin API's workspace scan endpoints) lets you pull endorsement metadata for all artifacts across your tenant. This is the foundation of your data catalog.
# Connect to Power BI with service principal
$tenantId = "your-tenant-id"
$clientId = "your-app-registration-client-id"
$clientSecret = "your-client-secret" # Use Key Vault in production
$tokenEndpoint = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
$body = @{
grant_type = "client_credentials"
client_id = $clientId
client_secret = $clientSecret
scope = "https://analysis.windows.net/powerbi/api/.default"
}
$tokenResponse = Invoke-RestMethod -Method Post -Uri $tokenEndpoint -Body $body
$accessToken = $tokenResponse.access_token
$headers = @{
Authorization = "Bearer $accessToken"
"Content-Type" = "application/json"
}
# Initiate a modified workspace scan (get all workspaces with dataset details)
$scanRequestBody = @{
workspaces = @() # Empty array = scan all workspaces
} | ConvertTo-Json
# Step 1: Trigger the scan
$scanResponse = Invoke-RestMethod `
-Method Post `
-Uri "https://api.powerbi.com/v1.0/myorg/admin/workspaces/getInfo?datasetExpressions=true&datasourceDetails=true&getArtifactUsers=true&lineage=true" `
-Headers $headers `
-Body $scanRequestBody
$scanId = $scanResponse.id
Write-Host "Scan initiated with ID: $scanId"
# Step 2: Poll for completion
do {
Start-Sleep -Seconds 10
$statusResponse = Invoke-RestMethod `
-Uri "https://api.powerbi.com/v1.0/myorg/admin/workspaces/scanStatus/$scanId" `
-Headers $headers
Write-Host "Scan status: $($statusResponse.status)"
} while ($statusResponse.status -ne "Succeeded")
# Step 3: Retrieve scan results
$scanResult = Invoke-RestMethod `
-Uri "https://api.powerbi.com/v1.0/myorg/admin/workspaces/scanResult/$scanId" `
-Headers $headers
Now extract endorsement information from the scan results:
# Build a flat catalog of all datasets with endorsement details
$datasetCatalog = @()
foreach ($workspace in $scanResult.workspaces) {
if ($workspace.datasets) {
foreach ($dataset in $workspace.datasets) {
$endorsement = if ($dataset.endorsementDetails) {
$dataset.endorsementDetails.endorsement
} else { "None" }
$certifiedBy = if ($dataset.endorsementDetails -and
$dataset.endorsementDetails.endorsement -eq "Certified") {
$dataset.endorsementDetails.certifiedBy
} else { $null }
$lastRefresh = if ($dataset.refreshSchedule) {
$dataset.refreshSchedule.days
} else { "No schedule" }
$datasetCatalog += [PSCustomObject]@{
WorkspaceId = $workspace.id
WorkspaceName = $workspace.name
DatasetId = $dataset.id
DatasetName = $dataset.name
Endorsement = $endorsement
CertifiedBy = $certifiedBy
ConfiguredBy = $dataset.configuredBy
SensitivityLabel = $dataset.sensitivityLabel.labelName
TargetStorageMode = $dataset.targetStorageMode
LastModified = $dataset.modifiedDateTime
Description = $dataset.description
}
}
}
}
# Export the catalog
$datasetCatalog | Export-Csv -Path ".\DatasetCatalog_$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation
# Summary statistics
Write-Host "Total datasets: $($datasetCatalog.Count)"
Write-Host "Certified: $(($datasetCatalog | Where-Object Endorsement -eq 'Certified').Count)"
Write-Host "Promoted: $(($datasetCatalog | Where-Object Endorsement -eq 'Promoted').Count)"
Write-Host "Datasets missing description: $(($datasetCatalog | Where-Object { -not $_.Description }).Count)"
One of the most important automation tasks is detecting certifications that may have gone stale. A dataset certified 18 months ago might have had its data source change, its business logic modified, or its owner leave the organization. Build a script that flags these for review:
# Define staleness thresholds
$certificationMaxAgeMonths = 12 # Certifications older than 12 months need renewal
$refreshFailureThreshold = 3 # More than 3 consecutive refresh failures = flag
# Query certified datasets
$certifiedDatasets = $datasetCatalog | Where-Object { $_.Endorsement -eq "Certified" }
$staleFlags = @()
foreach ($dataset in $certifiedDatasets) {
$issues = @()
# Check certification age
if ($dataset.LastModified) {
$lastModified = [datetime]$dataset.LastModified
$monthsOld = ((Get-Date) - $lastModified).Days / 30
if ($monthsOld -gt $certificationMaxAgeMonths) {
$issues += "Certification may be stale: last modified $([math]::Round($monthsOld, 0)) months ago"
}
}
# Check for missing sensitivity label on non-trivial datasets
if (-not $dataset.SensitivityLabel) {
$issues += "No sensitivity label applied"
}
# Check for missing description
if (-not $dataset.Description -or $dataset.Description.Length -lt 50) {
$issues += "Description missing or too short (less than 50 characters)"
}
# Check for missing certifiedBy — this indicates the cert was set via API
# without a named certifier, which is a governance red flag
if (-not $dataset.CertifiedBy) {
$issues += "CertifiedBy field is empty — certification may have bypassed approval workflow"
}
if ($issues.Count -gt 0) {
$staleFlags += [PSCustomObject]@{
DatasetId = $dataset.DatasetId
DatasetName = $dataset.DatasetName
WorkspaceName = $dataset.WorkspaceName
Owner = $dataset.ConfiguredBy
Issues = ($issues -join "; ")
}
}
}
Write-Host "`nDatasets requiring certification review: $($staleFlags.Count)"
$staleFlags | Format-Table -AutoSize
This script becomes the input to your governance review process — run it monthly, send the output to the Data Governance Council, and use it to drive renewal conversations with Dataset Owners.
The Scanner API output you're generating is exactly the right raw material for a Power BI report that is your enterprise data catalog. This is an elegant architectural choice — you're using Power BI to document itself.
Create a dedicated dataset in your Governance workspace with these logical tables (shown here as Power Query M pseudocode to illustrate the structure):
// Table: DatasetInventory
// Source: Scanner API results stored in Azure Data Lake or SharePoint
let
Source = AzureDataLake.Contents("https://yourcontoso.dfs.core.windows.net"),
CatalogFiles = Source{[Name="governance"]}[Content],
LatestScan = Table.SelectRows(CatalogFiles, each Date.IsInCurrentMonth([Date])),
ParsedJSON = Table.TransformColumns(LatestScan, {{"Content", Json.Document}}),
ExpandedWorkspaces = Table.ExpandRecordColumn(ParsedJSON, "Content", {"workspaces"}),
// ... further expansion of datasets, endorsement details, etc.
FinalTable = Table.SelectColumns(Expanded, {
"WorkspaceId", "WorkspaceName", "DatasetId", "DatasetName",
"Endorsement", "CertifiedBy", "ConfiguredBy", "SensitivityLabel",
"Description", "LastModified", "TargetStorageMode"
})
in
FinalTable
The catalog report should have these pages:
Certified Datasets Hub: The primary consumer-facing page. Shows all Certified datasets with their domain, owner, description, and a link to the workspace. This is the first place anyone should go when looking for an authoritative dataset. Use card visuals for total certified count, broken down by domain, and a table with filtered search capability.
Endorsement Health Dashboard: Internal governance view showing certification age distribution, stale certification flags, missing metadata percentages, and trend over time (are certifications increasing? Are renewals happening?).
Lineage Summary: A table showing certified datasets and their direct downstream report consumers, powered by the lineage data in the Scanner API response. This is critical for impact analysis — before un-certifying a dataset, you need to know how many reports will be affected.
Deprecation Tracker: Datasets marked for deprecation with their planned sunset dates, migration targets (the certified dataset that replaces them), and current usage metrics.
Tip: Store the Scanner API output as JSON files in Azure Data Lake, one file per scan run with a date partition. This gives you a historical record of your governance posture over time, which becomes valuable when you need to demonstrate compliance improvement to leadership or auditors.
Certification is only half the lifecycle. The other half — and the half most organizations completely ignore — is the deprecation workflow. Without it, your certified catalog gets bloated and the trust signal degrades.
The deprecation process should be triggered when:
Step 1: Identify and document the replacement. The Dataset Owner must identify the certified dataset that consumers should migrate to. This becomes the MigrationTarget field in your catalog.
Step 2: Add a deprecation notice to the dataset description. Prefix the description with [DEPRECATED - Migrate to: DatasetName by YYYY-MM-DD]. This surfaces in the dataset hub and any tool that shows descriptions.
Step 3: Notify all downstream report owners. Use the lineage data from your Scanner API catalog to identify every report built on the deprecated dataset. Generate an email or Teams notification to each report owner with the migration deadline and the replacement dataset details.
Step 4: Remove certification. The Data Governance Council removes the Certified endorsement. The dataset remains visible but loses the trust badge.
Step 5: Move to the Deprecated workspace. Publish a snapshot version to the Deprecated workspace (keeping it accessible for reports that haven't migrated yet) and remove it from the Certified workspace.
Step 6: Monitor migration progress. Your catalog report should track the percentage of downstream reports that have migrated away from the deprecated dataset. Set a hard sunset date and enforce it.
Step 7: Permanent deletion. After the sunset date, with appropriate backup procedures, delete the deprecated dataset and trigger a Scanner API scan to update the catalog.
Programmatically removing certification looks like this via the API:
# Remove certification from a dataset (downgrade to Promoted or None)
# Note: This requires the caller to have certification rights
$datasetId = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
$workspaceId = "workspace-guid-here"
$endorsementBody = @{
endorsementDetails = @{
endorsement = "None" # Options: "None", "Promoted", "Certified"
}
} | ConvertTo-Json
# Use the dataset update endpoint
$updateUri = "https://api.powerbi.com/v1.0/myorg/groups/$workspaceId/datasets/$datasetId"
# Note: Direct endorsement update via REST API requires using the Admin endpoint
# or the user must have certification rights in the tenant
$adminUpdateUri = "https://api.powerbi.com/v1.0/myorg/admin/datasets/$datasetId/endorsement"
Invoke-RestMethod `
-Method Patch `
-Uri $adminUpdateUri `
-Headers $headers `
-Body $endorsementBody
Write-Host "Certification removed from dataset: $datasetId"
Warning: The REST API endpoint for updating endorsement via the Admin path (
/admin/datasets/{datasetId}/endorsement) is available but should be used carefully. Changes made via the API bypass the UI confirmation dialog and leave an audit trail only in the Power BI Activity Log — make sure your governance automation logs these operations to your own audit system as well.
All this governance work is wasted if consumers can't find and use certified datasets. Power BI has several built-in discovery surfaces you should actively configure.
In Power BI Service, the Dataset Hub (accessible from the left navigation) shows datasets across workspaces the user has access to, with endorsement badges prominently displayed. Make sure your Certified workspace grants Viewer access to the appropriate broad audience — if users can't see the workspace, they won't discover its datasets.
There's an important architectural note here: a dataset in a Premium/Fabric workspace can be accessed by users who have Build permission on the dataset, even without direct workspace membership. Use this to your advantage. For your Certified workspace, consider:
If your organization uses a data catalog tool (Purview Data Catalog, Collibra, Alation), the Power BI Scanner API output you're generating is the feed for that integration. Power BI has native integration with Microsoft Purview — certified datasets are automatically discoverable in the Purview Data Catalog without additional configuration, as long as you've set up the Power BI scan in Purview.
In the Purview Data Catalog, configure the Power BI connector:
Microsoft Purview → Data Map → Sources → Register → Power BI
├── Select your Power BI tenant
├── Configure scan: Full scan initially, incremental thereafter
├── Map to Collection: Data Assets > Power BI
└── Schedule: Weekly full scan, daily incremental
Once registered, Purview will automatically classify Power BI assets, apply business glossary terms, and make them discoverable alongside your other data assets. Certified datasets surface with their endorsement status in Purview's asset view.
Governance programs without measurement tend to drift. Build the following monitoring into your operations.
The Power BI Activity Log captures every certification and promotion event. Use this to audit who certified what, when, and to detect anomalies (like a certification being granted and then immediately revoked — a sign of a process problem).
# Pull certification-related activity events for the past 30 days
Connect-PowerBIServiceAccount # Or use service principal auth
$startDate = (Get-Date).AddDays(-30).ToString("yyyy-MM-dd")
$endDate = (Get-Date).ToString("yyyy-MM-dd")
# Relevant activity event types for endorsement governance
$relevantActivities = @(
"SetScheduledRefresh",
"UpdateArtifactEndorsement", # Covers all endorsement changes
"CreateArtifact",
"DeleteArtifact"
)
$activityLog = @()
# Activity log requires looping by date (API returns one day at a time)
$current = [datetime]$startDate
$end = [datetime]$endDate
while ($current -le $end) {
$dateStr = $current.ToString("yyyy-MM-dd")
$dayActivities = Get-PowerBIActivityEvent `
-StartDateTime "${dateStr}T00:00:00" `
-EndDateTime "${dateStr}T23:59:59" |
ConvertFrom-Json
$endorsementEvents = $dayActivities | Where-Object {
$_.Activity -eq "UpdateArtifactEndorsement"
}
$activityLog += $endorsementEvents
$current = $current.AddDays(1)
}
# Analyze endorsement changes
$activityLog | Select-Object `
CreationTime, UserId, ArtifactName, WorkSpaceName, `
@{N='Action'; E={$_.ArtifactKind}}, `
@{N='Details'; E={$_.ArtifactId}} |
Format-Table -AutoSize
Write-Host "Total endorsement events in period: $($activityLog.Count)"
Track these metrics on a monthly cadence and present them to your Data Governance Council:
This exercise builds a functional certification governance toolkit for a hypothetical organization, Contoso Manufacturing.
Scenario: Contoso Manufacturing has 3 data domains (Finance, Operations, Customer Success) and needs to implement a certification program from scratch. They have an existing Power BI tenant with approximately 150 datasets, none of which are currently certified.
Part 1: Governance Setup (30 minutes)
In your Power BI Admin Portal (use a dev tenant if you don't want to affect production), navigate to Tenant Settings and enable Certification restricted to a security group. Create a mock group called PBI-CertificationAuthority in your directory and add yourself.
Create four workspaces following the naming convention: Finance-Dev, Finance-Validated, Finance-Certified, and Finance-Deprecated. Configure workspace access appropriately (you as Admin in all; add a second test user as Member in Certified).
Publish a dataset to Finance-Dev. Promote it to Finance-Validated. Verify that it appears with the Promoted badge in the Dataset Hub.
Part 2: API Exploration (45 minutes)
Register an Entra ID application for PBI-GovernanceAutomation. Grant it Tenant.Read.All permissions and have an admin grant consent. Configure it in the Admin Portal under Developer settings.
Run the Scanner API script from this lesson (use the polling version) against your dev tenant. Export the results to CSV. Verify that your newly promoted dataset appears with its endorsement status.
Manually certify your dataset through the UI (in the dataset settings, under Endorsement and Discovery). Re-run the Scanner API query and verify the Certified status and certifiedBy field appear in the output.
Part 3: Health Monitoring (30 minutes)
Adapt the stale certification detection script to flag your newly certified dataset if it doesn't have a sensitivity label applied. Run it and confirm the flag appears.
Apply a sensitivity label to the dataset (even a test label if Purview isn't fully configured). Re-run the script and confirm the flag disappears.
Export your full catalog to CSV and open it in Power BI Desktop. Build a simple 3-visual report: a card showing total certified datasets, a bar chart of datasets by endorsement tier, and a table of datasets missing descriptions. Publish this to your Finance-Certified workspace as the seed of your governance dashboard.
Part 4: Process Design (30 minutes)
Mistake: Granting certification rights to individual named users instead of security groups.
When that person leaves or changes roles, either certifications stop happening or you have to track down the tenant admin to update the setting. Always use security groups, and treat the membership of those groups as a governance artifact in itself.
Mistake: Certifying datasets without consuming them first.
It sounds obvious, but governance councils under time pressure sometimes certify based on the Gate 1 technical checklist without a Domain Data Steward actually running queries against the dataset and validating outputs against a source of truth. Require at minimum three specific measures to be validated with documented expected vs. actual values.
Mistake: The Scanner API scan timing out or returning incomplete results.
The scan is asynchronous and large tenants with thousands of workspaces can take 10-15 minutes to complete. Make your polling interval generous (30 seconds minimum, not 5 seconds) and always check the status field before attempting to retrieve results. Also note that the Scanner API has a rate limit — you shouldn't be triggering more than one full scan per day.
# Robust polling with timeout
$maxWaitMinutes = 20
$pollIntervalSeconds = 30
$startTime = Get-Date
do {
Start-Sleep -Seconds $pollIntervalSeconds
$statusResponse = Invoke-RestMethod -Uri "..." -Headers $headers
$elapsedMinutes = ((Get-Date) - $startTime).TotalMinutes
if ($elapsedMinutes -gt $maxWaitMinutes) {
Write-Error "Scan timed out after $maxWaitMinutes minutes"
break
}
Write-Host "Status: $($statusResponse.status) | Elapsed: $([math]::Round($elapsedMinutes, 1)) minutes"
} while ($statusResponse.status -notin @("Succeeded", "Failed"))
Mistake: Using the certification badge as the primary access control mechanism.
Certification is a trust signal, not a security control. A non-certified dataset can still contain sensitive data. Do not rely on "it's not certified so it must be okay to share widely." Sensitivity labels are your security control — certification tells you whether to trust the data quality, not whether you're authorized to access it.
Mistake: No deprecation workflow means certifications accumulate indefinitely.
After 18 months, when you have 200 certified datasets and consumers are back to asking "which one should I use?", you'll realize that additive certification without active lifecycle management recreates exactly the problem you were trying to solve. Build the deprecation workflow before you start certifying, not after the mess is already made.
Troubleshooting: Dataset Hub not showing certified datasets for users.
This is almost always a permissions issue. The user needs at least Viewer access to the workspace containing the certified dataset, OR the dataset needs to have Build permissions granted to the user directly (or via a security group). Check the dataset's permissions in the workspace and compare against the user's group memberships.
Troubleshooting: certifiedBy field appearing blank in Scanner API output.
This happens when certification was set via the Admin REST API (/admin/datasets/{id}/endorsement) rather than through the UI. The API endpoint doesn't populate the certifiedBy field from the calling user's identity in the same way the UI does. This is an important audit gap — if you're using the API to set certifications as part of automation, you need to log the approval separately in your own audit system. Treat blank certifiedBy as a governance flag.
Troubleshooting: Scanner API returning 403 Forbidden.
Your service principal needs to be explicitly enabled in the Admin Portal under Developer settings → Allow service principals to use Power BI APIs AND Allow service principals to use read-only Power BI admin APIs. Both settings must be enabled. Also verify that Tenant.Read.All admin consent has been granted in Entra ID — delegated consent is not sufficient; it must be application (admin) consent.
You've built something more than a feature configuration — you've designed an operating model for data trust at enterprise scale. Let's ground what we've covered:
The Power BI endorsement system gives you two trust tiers (Promoted and Certified) with Certified being the governance-gated tier that requires deliberate design to remain meaningful. You've seen that the technical capability is almost trivially simple to enable — the work is in the governance wrapper around it.
Your certification workflow now has three explicit gates (technical, business, governance), clear role separation between Dataset Owners, Domain Data Stewards, and the Certification Authority, and a workspace topology that makes the journey of a dataset from development to certified production visible and predictable.
The Scanner API gives you the programmatic foundation to build a living data catalog rather than a static documentation exercise that goes stale the moment it's published. Your stale certification detector and activity log mining give you the ongoing operational visibility to keep the program honest.
Critically, you have a deprecation workflow — the unsexy but essential counterpart to certification that prevents the trusted catalog from becoming a new version of the chaos you started with.
Where to go next:
The natural progression from here is Microsoft Purview integration at depth — specifically, how to use business glossary terms from Purview as authoritative definitions that link to your certified Power BI datasets, creating a true bidirectional enterprise data catalog. This takes what you've built and connects it to your broader data governance ecosystem.
You should also explore Row-Level Security and Object-Level Security in the context of certified datasets — certified status implies a security model was deliberately designed, and understanding how to design, test, and document RLS/OLS is the next layer of rigor in enterprise dataset management.
Finally, with Microsoft Fabric's evolution of the semantic model concept, understanding how OneLake and Fabric Domain workspaces interact with the endorsement model is increasingly important. The governance patterns you've learned here translate directly, but the workspace hierarchy and permission model have important differences that affect your catalog architecture.
Learning Path: Enterprise Power BI