Don't miss your chance to take the Fabric Data Engineer (DP-700) exam on us!
Learn moreThe FabCon + SQLCon recap series starts April 14th at 8am Pacific. If you’re tracking where AI is going inside Fabric, this first session is a can't miss. Register now
Hello,
I am facing a persistent 401 Unauthorized error when calling the Power BI Admin API (Scanner API), specifically on the endpoint GET https://api.powerbi.com/v1.0/myorg/admin/groups.
Here is my setup and the troubleshooting steps I've already taken:
1. Azure Configuration (App Registration):
Service Principal created.
API Permissions: Power BI Service > Tenant.Read.All (Type: Application).
Admin Consent: Successfully granted (Status shows green "Granted" in Azure Portal)
2. Token Analysis (via jwt.ms):
My Python script successfully retrieves an Access Token (via https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token).
Decoding the token on jwt.ms confirms the role is present: "roles": [ "Tenant.Read.All", "Tenant.ReadWrite.All"]
This confirms the token is valid and carries the correct Azure permissions.
3. Power BI Configuration (Admin Portal): Under Tenant Settings > Developer settings:
"Allow service principals to use Power BI APIs" is set to ENABLED.
To rule out Security Group issues, I temporarily set this to "Apply to: The entire organization".
"Enhance admin APIs responses with detailed metadata" is set to ENABLED.
The Issue: Despite this setup, the API call returns: Status Code: 401 Unauthorized
I have waited over 30 minutes for permission propagation with no luck. The Tenant ID used in the script matches the App Registration Tenant ID exactly.
I tried to add my Security group btw, but the Admin portal don't recognize or even accept it, i can't add it here, but i specifically created a Security Group for my script. Someone know why ? I think it's there the problem but i'm not sure, it's why i created this topic.
Has anyone experienced this scenario where a valid Token (with roles) is rejected by the Admin API? Is there a known excessive sync delay or a hidden setting I am missing?
Any help would be appreciated.
Solved! Go to Solution.
Let me see if I can explain it better this time. Let's start with the tech issue for the api and then the requirement.
The API is divided in two groups of requests. The indiviuals ones that need a delegated permission (groups, reports, datasets, etc) and the Admin (you only need the read-only permission at fabric admin portal). In addition, when using service principal you shouldn't ever use tenantReadWrite. It will break it for admin. You can have an app registration for just admin like this:
As long as you have the read-only admin api at fabric portal, it will work. The tenant read permission will break the admin request.
Now, regarding the requirement. You can't query metadata directly to a dataset. You have two alternatives. From one hand you can use the admin scanner api that is kind of complex but can look in the entire organization tenant. On the other hand, simplepbi has requests for getting measures, tables, etc. The way the library has built its way to that info is using the fabric api to read the files behind a semantic model details, look for the table tmdl file or model.bim file from web, loop, find, read and show. It's very tricky to build, but it can be done if you have some coding skills. I know this because I have built simplepbi. Example: https://blog.ladataweb.com.ar/post/760691380372881408/simplepbi-get-tablas-medidas-columnas-o-roles
I hope that helps,
P/S I'm working on a tool for getting a nice picture of the measure lineage of a semantic model. But it's a developer tool that works for developer at desktop, if you want more info ping me on private.
Happy to help!
Hi. I'm not sure why you can't add a security group to a tenant settings, that's something I would rise a ticket to support. I'm writting to clarify something. In order to use the scanner api, you don't need the permissions you are setting in there if you will use a service principal authentication. You just need to register the app in azure and make sure this setting is allowed for the app:
Don't allow tenant read all and grant concent. That's only for login with credentials. The scanner api specify the following for that setting: "Relevant only when authenticating via a standard delegated admin access token. Must not be present when authentication via a service principal is used."
If then you want to create workspaces, then you can add the permission groups.readwrite for the registered app.
I hope that helps,
Happy to help!
Hi. Thank you for your help, i want to pull every metadata of our models and PBI reports to create a little Data Catalog.
In Python, my access_token function returned correctly my Token :
url = f"https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token"
payload = {
'grant_type': 'client_credentials',
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'scope': 'https://analysis.windows.net/powerbi/api/.default'
}But when i'm trying to pull my workspaces datas with this API request :
headers = {
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
}
print("Récupération de la liste des workspaces...")
groups_url = "https://api.powerbi.com/v1.0/myorg/admin/groups?top=5000"
groups_res = requests.get(groups_url, headers=headers)I get a 401 Error, I have enabled the following switches in Tenant Settings > Developer Settings :
- "Allow service principals to use Power BI APIs"
- "Allow service principals to use read-only Power BI admin APIs"
- "Enhance admin APIs responses with detailed metadata"
- "Enhance admin APIs responses with DAX and Mashup expressions"
Despite the Security Group problem, maybe yeah i don't need all these permissions ?
Thank you.
Hi. Make sure you have removed the permissions from the app registration. The tenant read all you have shown in the first post with a picture. Microsoft says at docs "...tenant read write... Must not be present when authentication via a service principal is used."
The fabric settings are ok. You need "Allow service principals to use the Fabric/PowerBi API". I don't know how you have enabled the "Allow service principals to use the read-only Power Bi/Fabric Admin APIs" because it forces you to enable by security group and it won't let you use it for the whole organization. The last two enhace admin api are for the scanner api specifically, they shouldn't impact on get groups.
Regards
Happy to help!
Hi!
Yeah i forgot that little thing, I created an app registration and a Security group and it doesn't work... But I re-created the app and security group in ENTRA.Microsoft, so now i can add this group to my tenant settings. My tenant settings, now from app.fabric and not app.powerbi, i have access on both of them, so i have enabled in each admin portal the tenant settings 🙂
I can't use the admin URL API so i changed the URL
I steel have an error, if I put the Service Principal as Member in each workspace i have, I can find the workspaces, read reports etc, but can't select measures because I "don't have the permission to write" :
# L'URL magique pour interroger le modèle
query_url = f"https://api.powerbi.com/v1.0/myorg/groups/{group_id}/datasets/{dataset_id}/executeQueries"
# La requête DAX.
# Important : Elle DOIT commencer par EVALUATE.
# SELECTCOLUMNS permet de nettoyer le résultat pour ne garder que ce qu'on veut.
dax_code = """
EVALUATE
SELECTCOLUMNS(
INFO.MEASURES(),
"MeasureName", [Name],
"Description", [Description],
"Expression", [Expression]
)
"""
But I had the delegated options of RedWrite informations so I don't know why my query doesn't work, I feel like I'm making progress, but not the way I want; I'd like the admin URLs to work...
If with these informations, you now know why i'm blocked, it would be wonderful if u can help me ! ❤️
(and sorry btw for my non-perfect english, improving everydays !)
Hi. Assuming you have made the changes I suggested like removing the permission TenantReadWrite from the App Registration and added the a security group to the fabric setting "Allow service principals to use the read-only Power Bi/Fabric Admin APIs". Then let me show you something. For service principal I'm loging like this with python:
POWER_BI_RESOURCE_ENDPOINT = "https://analysis.windows.net/powerbi/api"
MICROSOFT_OAUTH2_API_ENDPOINT = "https://login.microsoftonline.com/" + tenant_id + "/oauth2/token/"
try:
url = MICROSOFT_OAUTH2_API_ENDPOINT #is this different?
body = {
"grant_type":"client_credentials",
"client_id":power_bi_client_id,
"client_secret":power_bi_secret,
"resource":POWER_BI_RESOURCE_ENDPOINT
}
headers = {
"Content-Type": "application/x-www-form-urlencoded"
}
r = requests.post(url = url, data = body, headers = headers)
access_token = r.json().get('access_token')
self.token = access_token
except requests.exceptions.HTTPError as ex:
print(ex)
As you can see, I'm not using a scope, just resource. Getting the token is crucial to make the token work with the permission it has. That should be enough to make Admin requests. If you are not sure about the way the loggin works, you can use MSAL microsoft library (it's available for many languages). If you use python you can also use SimplePBI (non oficial wrapper to make it easy to handle API with python)
In addition, the request for using a dax query to info.measures won't ever work. That's not possible. The limitations of the dax query to model request describe that info functions are not allowed for anyone. It doesn't matter if you are admin or not.
If your objetive is the scanner api, then continue trying to get admin work. If it's getting roles, I recommend using SimplePBI that has built requests that are not at the API like getting the roles of a semantic model.
I hope that make sense
P/S the delegated permission only make sense if you want to use a request that's not at Admin category, for example getting the reports inside a works the service principal is part. Non admin requests are dependant on the permission the service principal has at workspaces
Happy to help!
Hi!
Alright, i think i get lost, I need to understand what i does wrong so I restart the projet :
I want to create a free "DIY Data Catalog" of my reports that contains the Lineage and metadata of each field, DAX measures included of course. So first point : we can't take the datas from our dax queries with the API ? Or I missunderstood ur last message ? It's "only" why i want to use the APIs, because i don't want to copy/paste each queries into my Table haha
Asking Gemini, it said that i could do that, with App Registration and Sevice Principal, so i now re-created, thanks to your corrections, a new app registration and security group :
I don't know if i have to make the group and app registration in Azure AD or Entra.Mircosoft, do you know the difference ?
I do it in entra now :
i revoked every permissions, in order to only have the application and delegated Tenant.Read.All
For the permissions in my Fabric Admin portal :
i now can see the Security Group thanks to entra.microsoft, it's actually the only differnce i see with Azure AD...
I don't know if "another settings put enable" can cancel this permission, so others permissions linked to API-things are enabled for a subset of the organization 🙂
Now, in Python with your corrections :
i added your modifications, i had for my acess token :
It's already worked, but wanted to have the same as u to see if there is a difference.
I use this to get the DAX queries informations : # L'URL magique pour interroger le modèle query_url = f"https://api.powerbi.com/v1.0/myorg/groups/{group_id}/datasets/{dataset_id}/executeQueries" # La requête DAX. # Important : Elle DOIT commencer par EVALUATE. # SELECTCOLUMNS permet de nettoyer le résultat pour ne garder que ce qu'on veut. dax_code = """ EVALUATE SELECTCOLUMNS( INFO.MEASURES(), "MeasureName", [Name], "Description", [Description], "Expression", [Expression] ) """ payload = { "queries": [{ "query": dax_code }], "serializerSettings": {"incudeNulls": True} } try: # Envoi de la requête res = requests.post(query_url, headers=headers, json=payload) # CAS 1 : SUCCÈS (Le dataset répond et contient des données) if res.status_code == 200: try: # L'API renvoie une structure imbriquée : results -> tables -> rows rows = res.json()['results'][0]['tables'][0]['rows'] measures = [] for row in rows: # L'API renvoie les clés souvent avec des crochets, ex: "[MeasureName]" # On nettoie pour avoir un dictionnaire propre. measures.append({ 'MeasureName': row.get('[MeasureName]') or row.get('MeasureName'), 'Description': row.get('[Description]') or row.get('Description'), 'DAX_Expression': row.get('[Expression]') or row.get('Expression') }) return measures except Exception as e: print(f"⚠️ Erreur de lecture du JSON sur le dataset {dataset_id} : {e}") return [] # CAS 2 : ÉCHEC (Erreur 400, 401, 403...) else: [error etc]
And finally in my terminal when i execute the script :
❌ ERREUR DAX sur Dataset a470dbcc-[ID OF DATASET] :
└─ Code: 400
└─ Réponse: {"error":{"code":"DatasetExecuteQueriesError","pbi.error":{"code":"DatasetExecuteQueriesError","parameters":{},"details":[{"code":"DetailsMessage","detail":{"type":1,"value":"Failed to execute the DAX query."}},{"code":"AnalysisServicesErrorCode","detail":{"type":1,"value":"3239575574"}}]}}}
At first, it seems like it's because my reports are projections of themselves, so the script was reaching for a pointer, and not a dataset. But i verrified and the datasets are published from my locals PBIXs, so this error is non-sense ;-;
Finally, i got my Excel with 4 pages :
- Reports (it worked)
- Datasets (it worked)
- Sources (it worked)
- Measures_DAX (blank sheet)
In my opinion, my SP is only a "Reader", so i can't execute my query to extract dax measures.
@ibarrau
If your objetive is the scanner api, then continue trying to get admin work. If it's getting roles, I recommend using SimplePBI that has built requests that are not at the API like getting the roles of a semantic model.
If i understood correctly, i can get the dax measures, i just need my SP to be considered "Admin" right ?
There is a way to extract DAX measures informations, using the API ?
SimplePBI :
I can use it maybe, but i imagine it's not a python prog problem, but more a permission/API/URL one ? I hope so.
@ibarrau
Let me see if I can explain it better this time. Let's start with the tech issue for the api and then the requirement.
The API is divided in two groups of requests. The indiviuals ones that need a delegated permission (groups, reports, datasets, etc) and the Admin (you only need the read-only permission at fabric admin portal). In addition, when using service principal you shouldn't ever use tenantReadWrite. It will break it for admin. You can have an app registration for just admin like this:
As long as you have the read-only admin api at fabric portal, it will work. The tenant read permission will break the admin request.
Now, regarding the requirement. You can't query metadata directly to a dataset. You have two alternatives. From one hand you can use the admin scanner api that is kind of complex but can look in the entire organization tenant. On the other hand, simplepbi has requests for getting measures, tables, etc. The way the library has built its way to that info is using the fabric api to read the files behind a semantic model details, look for the table tmdl file or model.bim file from web, loop, find, read and show. It's very tricky to build, but it can be done if you have some coding skills. I know this because I have built simplepbi. Example: https://blog.ladataweb.com.ar/post/760691380372881408/simplepbi-get-tablas-medidas-columnas-o-roles
I hope that helps,
P/S I'm working on a tool for getting a nice picture of the measure lineage of a semantic model. But it's a developer tool that works for developer at desktop, if you want more info ping me on private.
Happy to help!
I finally understood !
I just deleted all the permissions of the APP, and keep the tenant settings and it worked !
Thank you !
Hello,
Sorry i didn't respond, i will check simpleBI and ask my Administration if i can use unofficial librairies 🙂 Thank you !
If you have recently started exploring Fabric, we'd love to hear how it's going. Your feedback can help with product improvements.
A new Power BI DataViz World Championship is coming this June! Don't miss out on submitting your entry.
Share feedback directly with Fabric product managers, participate in targeted research studies and influence the Fabric roadmap.