Forum Discussion
Admin API for Service principle
I've got this working and it was straightforward. You've done some of these steps already, but worthwhile listing them anyway.
1. Create app in Azure. Dont give it any permissions.
2. Create a secret for the app in Azure.
3. Create a security group, and add the app to this group.
4. In the PBI Tenant settings, enable Read Only Admin API's and add the security group from #3 to the list to authorised users. Do not add the app itself, just the group it is a member of.
5. Done
Now for how to actually authenticate! I've actually done this in a Power BI report, so I'll share the code for that and you should be able to figure it out fairly easily as the API calls are the same.
I have an Authenticate function which grabs the bearer token, and a query which does the data retrieval using that bearer token.
I also have parameters for: APP ID, TenantID and APP Secret so that I can quickly swap between our various tenants.
The M code for the Authenticate function is:
() =>
let
body = "client_id=" & #"App ID" & "&scope=https://analysis.windows.net/powerbi/api/.default&client_secret=" & #"App Secret" & "&grant_type=client_credentials",
Data= Json.Document(Web.Contents("https://login.microsoftonline.com/"& TenantID & "/oauth2/v2.0/token/", [Headers=[#"Content-Type"="application/x-www-form-urlencoded"], Content=Text.ToBinary(body)])),
access_token = Data[access_token]
in
access_token
I think the important bit you may be missing is .default at the end of the API you're asking for permissions to access.
The code I'm using to query the API itself is:
let
Source = Json.Document(Web.Contents("https://api.powerbi.com",
[
RelativePath = "/v1.0/myorg/admin/groups?$top=5000&$expand=datasets,dataflows,reports,dashboards,users&$filter=type eq 'PersonalGroup'",
Headers=[Authorization="Bearer " & #"Authenticate"() ]
] )),
#"Converted to Table" = Record.ToTable(Source),
Value = #"Converted to Table"{2}[Value],
#"Converted to Table1" = Table.FromList(Value, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column1" = Table.ExpandRecordColumn(#"Converted to Table1", "Column1", {"id", "isReadOnly", "isOnDedicatedCapacity", "capacityMigrationStatus", "type", "state", "name", "datasets", "dataflows", "reports", "dashboards", "users", "capacityId"}, {"id", "isReadOnly", "isOnDedicatedCapacity", "capacityMigrationStatus", "type", "state", "name", "datasets", "dataflows", "reports", "dashboards", "users", "capacityId"}),
#"Reordered Columns" = Table.ReorderColumns(#"Expanded Column1",{"id", "isReadOnly", "isOnDedicatedCapacity", "capacityMigrationStatus", "type", "state", "name", "capacityId", "datasets", "dataflows", "reports", "dashboards", "users"}),
#"Renamed Columns" = Table.RenameColumns(#"Reordered Columns",{{"id", "workspaceId"}})
in
#"Renamed Columns"
This returns everything people have put into their personal workspace. To just get proper workspace contents, swap the filter to: filter=type ne 'PersonalGroup'
Hopefully this gets you the rest of the way! Just bear in mind that the Read Only API has a limited list of API functions that actually work with it.