Forum Discussion
Using Power BI API in C#
- 7 months ago
Hi bigmac025 ,
Thanks for the update and for sharing the decoded token details.
To clarify the point around roles and permissions, the documentation is referring to delegated Power BI permissions when it states that admin-consent required permissions must not be present for service principal authentication. In an app-only setup, the app registration should not have any delegated Power BI permissions configured.
This does not conflict with assigning a Power BI Admin or Fabric Admin tenant role to the service principal. Tenant roles are evaluated by the Power BI service at runtime and are separate from Azure AD delegated permissions. Admin REST APIs such as GetGroupsAsAdminAsync() are authorized based on tenant-level configuration, not on delegated scopes in the token.
So to address both points together, including AmosHersch 's comment, the presence of Tenant.Read.All or Tenant.ReadWrite.All in an app-only token does not cause the 401 and does not need to be removed. Those scopes are relevant only for delegated admin user tokens and are ignored when using service principal authentication.
Since the token itself is valid, a 401 from GetGroupsAsAdminAsync() still points to tenant-level authorization. Please recheck that service principal access is enabled in the Power BI Admin portal and that the service principal or its security group is allowed, that the service principal has a Power BI Admin or Fabric Admin tenant role, and that no delegated Power BI permissions are configured on the app registration.
Once these are in place, the updated code using GetGroupsAsAdminAsync() and GetReportsAsAdminAsync() should work as expected.
Hope this helps. Please reach out for further assistance.
Thank you.
Thank you Ahmed-Elfeel and v-veshwara-msft for you help.
I followed the information you sent me. After reviewing, I couldn't find anything wrong so I went to this page: https://learn.microsoft.com/en-us/rest/api/power-bi/admin/groups-get-groups-as-admin?tryIt=true&source=docs#code-try-0
I copied the Bearer Token from the page and then pasted it into my C# app and got this message:
Non-admin groups: 2
Found 238 workspaces.
Status: 401 Unauthorized
Response content:
X-PowerBI-Error-Info: GroupNotAccessible
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Frame-Options: deny
X-Content-Type-Options: nosniff
Access-Control-Expose-Headers: RequestId,X-PowerBI-Error-Info
request-redirected: true
home-cluster-uri: https://wabi-germany-west-central-primary-redirect.analysis.windows.net/
RequestId: 49a16e45-e847-4323-a0b1-04f97ae4111f
Date: Thu, 08 Jan 2026 00:43:37 GMT
Content-Length: 0
You can see that worked and it returned 238 workspaces.
That leads me to believe that I am getting the wrong token when I call my API my getToken Method.
Here is my code for getting the token:
class API
{
public async Task<string> getPowerBIAccessToken()
{
var tenantId = "removed";
var clientId = "removed";
var clientSecret = "removed";
// The Power BI API scope
var scopes = new[] { "https://analysis.windows.net/powerbi/api/.default" };
var app = ConfidentialClientApplicationBuilder.Create(clientId)
.WithClientSecret(clientSecret)
.WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}"))
.Build();
var authResult = await app.AcquireTokenForClient(scopes).ExecuteAsync();
return authResult.AccessToken;
}
}It returns a token but obvisouly an invalid one. Any help would be appreciated to tell me why I am getting a token that doesn't work and how to get one that works.
Thanks,
Tim
- AmosHersch7 months agoMicrosoft Employee
Hi bigmac025 ,
I am not sure which of the API calls fails for you, I can see 2 at least different ones in the code you've shared:
var workspaces = await client.Groups.GetGroupsAsAdminAsync(top: 500);
var reports = await client.Reports.GetReportsInGroupAsync(groupId);
If the service principal is a tenant admin then the first one should work.For the second one to work the service principal need to be at least a viewer in the workspace. Not every admin user can call this API for any workspace in the tenant. Can this be the reason?
- v-veshwara-msft7 months agoCommunity Support
Hi bigmac025 ,
Thanks for sharing the additional details and for testing with the token from the Try It experience.
The AcquireTokenForClient call and the scope you are using are correct, and the token itself is being accepted by the Power BI service.
The important clue is the response header X-PowerBI-Error-Info: GroupNotAccessible. This indicates an authorization issue at the workspace level, not a problem with the token.
In the code you shared, GetGroupsAsync() is still being executed. This API is user scoped and is not supported when using service principal (app only) authentication.
Enable service principal authentication for admin APIs - Microsoft Fabric | Microsoft Learn
You are also calling non admin APIs such as GetReportsInGroupAsync. For these calls, the service principal must be explicitly granted access to the workspace, either directly or via an Entra ID security group, with at least Viewer permissions. Without workspace access, Power BI will return 401 or 403 even with a valid token.
For tenant wide discovery using a service principal, GetGroupsAsAdminAsync() is the supported approach. For any workspace scoped operations, ensure the service principal has access to the target workspace.
So the issue is caused by a mismatch between the API being called and the authorization context, rather than an invalid or expired token.
Hope this helps. Please reach out for further assistance.
Thank you.
- v-veshwara-msft7 months agoCommunity Support
Hi bigmac025 ,
Just wanted to check if the responses provided were helpful. If further assistance is needed, please reach out. Also thanks AmosHersch for sharing your insights.
Thank you.