I'm using Projects - List REST API to retrieve the list of DevOps projects, with their avatar
[GET] https://dev.azure.com/MY_ORGANIZATION/_apis/projects?getDefaultTeamImageUrl=true
Each returned project
has this structure:
{
"id": "abcdxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"name": "PROJ",
"url": "https://dev.azure.com/MY_ORGANIZATION/_apis/projects/abcdxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"state": "wellFormed",
"revision": 21,
"visibility": "public",
"defaultTeamImageUrl": "https://dev.azure.com/MY_ORGANIZATION/_apis/GraphProfile/MemberAvatars/efghxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx?overrideDisplayName=PROJ&size=2",
"lastUpdateTime": "2025-03-12T10:21:29.513Z"
}
I tried to load /_apis/GraphProfile/MemberAvatars
avatar image as is, by signing the request with the same valid OAuth 2.0 access token used for the REST API.
In Microsoft Entra Admin Center, I made sure to include vso.graph
API permission for my app registration, but it didn't do the trick.
I know there's the dedicated Avatars - Get REST API (/_apis/graph/Subjects/{subjectDescriptor}/avatars
) to get base64 avatars, but it needs the subject descriptor as input, and it's not included in /_apis/projects
REST API response (and I'd like to avoid additional API calls to retrieve them).
Fun fact: I tried adding all 76 vso
API permissions to my app registration, also with admin consent, and the avatar did load as intended.
But now I'm having a hard time in identifying which is the involved API permission.
Any suggestions? Thanks in advance
Based on my test, to run REST API https://dev.azure.com/{OrgName}/_apis/GraphProfile/MemberAvatars/{AvatarId}?api-version=7.1
, your API needs user_impersonation
permission.
user_impersonation
allows the application full access to the REST APIs provided by Visual Studio Team Services on behalf of the signed-in user. If the sign-in user has permissions to get project avatar, then the app has permissions.
I tried assigning all API permissions except `user_impersonation` to my app registration, but my app still does not have enough permissions. Therefore, I guess that additional permissions are required to run the current API, and the permissions come from the user's membership in the organization. For example, PCA has more permissions than shown in the UI and PAT scope.