Forum Discussion
Feature Usage and Adoption symantic model report
- 8 months ago
Hi viswaaa,
I can't build a full solution for you, but here's something to get you started.
from sempy.fabric import FabricRestClient from urllib.parse import urlencode import pandas as pd client = FabricRestClient() # Auth tokens are acquired from the Fabric execution context. def paged_get(path: str, params: dict | None = None) -> list[dict]: """ Calls a Fabric REST API GET endpoint that returns: { "value": [...], "continuationToken": "...", "continuationUri": "..." } and keeps fetching until all pages are retrieved. """ all_rows = [] continuation = None params = dict(params or {}) while True: q = dict(params) if continuation: q["continuationToken"] = continuation url = path + (("?" + urlencode(q)) if q else "") resp = client.get(url) resp.raise_for_status() payload = resp.json() all_rows.extend(payload.get("value", [])) continuation = payload.get("continuationToken") if not continuation: break return all_rows def list_workspaces(roles: list[str] | None = None) -> list[dict]: # roles example: ["Admin","Member","Contributor","Viewer"] params = {} if roles: params["roles"] = ",".join(roles) return paged_get("/v1/workspaces", params=params) def list_reports_in_workspace(workspace_id: str, recursive: bool = True) -> list[dict]: # List Items supports filtering by item type; "Report" is a valid type. params = { "type": "Report", "recursive": str(recursive) # API expects boolean; sending "True"/"False" works well in practice } items = paged_get(f"/v1/workspaces/{workspace_id}/items", params=params) # Defensive filter in case anything unexpected slips through return [i for i in items if i.get("type") == "Report"] # --- Main --- workspaces = list_workspaces() rows = [] for ws in workspaces: ws_id = ws["id"] ws_name = ws.get("displayName") try: reports = list_reports_in_workspace(ws_id, recursive=True) for r in reports: rows.append({ "workspaceId": ws_id, "workspaceName": ws_name, "reportId": r["id"], "reportName": r.get("displayName"), "folderId": r.get("folderId"), }) except Exception as ex: # If you ever hit a permissions edge-case, keep going and log it rows.append({ "workspaceId": ws_id, "workspaceName": ws_name, "reportId": None, "reportName": f"ERROR listing reports: {ex}", "folderId": None, }) df_reports = pd.DataFrame(rows) df_reportsIf you found this helpful, consider giving some Kudos. If I answered your question or solved your problem, mark this post as the solution.
Hi viswaaa,
Okay, then you're probably going to want to get workspace details using this endpoint: https://learn.microsoft.com/en-us/rest/api/fabric/admin/workspaces/list-workspaces?tabs=HTTP
That will return workspace details.
To get reports, you can use the List Items endpoint:
https://learn.microsoft.com/en-us/rest/api/fabric/admin/items/list-items?tabs=HTTP
Both of these endpoints are in preview, so if you want to rely on fully released APIs, then it gets a bit messier, you can use getModifiedWorkspaces to get IDs of workspaces that have changed:
https://learn.microsoft.com/en-us/rest/api/power-bi/admin/workspace-info-get-modified-workspaces
(there is no nice way to get all workspace IDs without using the preview APIs)
then you can use GetGroup to get workspace details:
https://learn.microsoft.com/en-us/rest/api/power-bi/groups/get-group
and then you can use GetReportsInGroup to get the reports:
https://learn.microsoft.com/en-us/rest/api/power-bi/reports/get-reports-in-group
If you found this helpful, consider giving some Kudos. If I answered your question or solved your problem, mark this post as the solution.
- viswaaa8 months ago
Helper IV
Hi tayloramy ,
Thanks for the info.
Can you please help me how to run these API's in Power BI and automate this process.
- tayloramy8 months ago
Super User
Hi viswaaa,
I can't build a full solution for you, but here's something to get you started.
from sempy.fabric import FabricRestClient from urllib.parse import urlencode import pandas as pd client = FabricRestClient() # Auth tokens are acquired from the Fabric execution context. def paged_get(path: str, params: dict | None = None) -> list[dict]: """ Calls a Fabric REST API GET endpoint that returns: { "value": [...], "continuationToken": "...", "continuationUri": "..." } and keeps fetching until all pages are retrieved. """ all_rows = [] continuation = None params = dict(params or {}) while True: q = dict(params) if continuation: q["continuationToken"] = continuation url = path + (("?" + urlencode(q)) if q else "") resp = client.get(url) resp.raise_for_status() payload = resp.json() all_rows.extend(payload.get("value", [])) continuation = payload.get("continuationToken") if not continuation: break return all_rows def list_workspaces(roles: list[str] | None = None) -> list[dict]: # roles example: ["Admin","Member","Contributor","Viewer"] params = {} if roles: params["roles"] = ",".join(roles) return paged_get("/v1/workspaces", params=params) def list_reports_in_workspace(workspace_id: str, recursive: bool = True) -> list[dict]: # List Items supports filtering by item type; "Report" is a valid type. params = { "type": "Report", "recursive": str(recursive) # API expects boolean; sending "True"/"False" works well in practice } items = paged_get(f"/v1/workspaces/{workspace_id}/items", params=params) # Defensive filter in case anything unexpected slips through return [i for i in items if i.get("type") == "Report"] # --- Main --- workspaces = list_workspaces() rows = [] for ws in workspaces: ws_id = ws["id"] ws_name = ws.get("displayName") try: reports = list_reports_in_workspace(ws_id, recursive=True) for r in reports: rows.append({ "workspaceId": ws_id, "workspaceName": ws_name, "reportId": r["id"], "reportName": r.get("displayName"), "folderId": r.get("folderId"), }) except Exception as ex: # If you ever hit a permissions edge-case, keep going and log it rows.append({ "workspaceId": ws_id, "workspaceName": ws_name, "reportId": None, "reportName": f"ERROR listing reports: {ex}", "folderId": None, }) df_reports = pd.DataFrame(rows) df_reportsIf you found this helpful, consider giving some Kudos. If I answered your question or solved your problem, mark this post as the solution.