How to create Microsoft Team via Microsoft Graph API with Owners specified by User Email rather than User ID? - microsoft-graph-api

Desired Behaviour
Create a Microsoft Team, with specified Owners and Members, in a Power Automate Flow using the HTTP connector to make requests to the Microsoft Graph API.
Actual Behaviour
This code shows how you can create a Microsoft Team whilst specifying it's Owners by User ID.
{
"template#odata.bind": "https://graph.microsoft.com/v1.0/teamsTemplates('standard')",
"displayName": "My Sample Team",
"description": "My Sample Team’s Description",
"members": [
{
"#odata.type": "#microsoft.graph.aadUserConversationMember",
"roles": [
"owner"
],
"user#odata.bind": "https://graph.microsoft.com/v1.0/users('0040b377-61d8-43db-94f5-81374122dc7e')"
}]
}
Source
For reference, the Graph API docs entry for Get a user (which is used to specify the Owner in the code above), specifies the endpoint syntax as:
GET /users/{id | userPrincipalName}
Currently, I do not have access to users' id or userPrincipalName.
What I've Tried
I am using a Power Automate Flow with the SharePoint For a selected item trigger.
The list includes two columns of type Person where Owners and Members are specified.
In order to get a list of Owners, I am using the SharePoint connector's Get item action on the selected item and then using an Apply to each control to iterate over each columns' values.
Below is the Raw Output of Get Item - the Owners column array is TeamOwner_x002f_s.
You can see that each object only has DisplayName and Email and not User ID or userPrincipalName:
{
"statusCode": 200,
"headers": {
"Transfer-Encoding": "chunked",
"Vary": "Origin,Accept-Encoding",
"X-SharePointHealthScore": "1",
"X-MS-SPConnector": "1",
"X-SP-SERVERSTATE": "ReadOnly=0",
"DATASERVICEVERSION": "3.0",
"SPClientServiceRequestDuration": "68",
"SPRequestGuid": "letters-and-numbers",
"request-id": "letters-and-numbers",
"MS-CV": "letters-and-numbers.0",
"Strict-Transport-Security": "max-age=31536000",
"X-FRAME-OPTIONS": "SAMEORIGIN",
"Content-Security-Policy": "frame-ancestors 'self' teams.microsoft.com *.teams.microsoft.com *.skype.com *.teams.microsoft.us local.teams.office.com *.powerapps.com *.yammer.com *.officeapps.live.com *.office.com *.stream.azure-test.net *.microsoftstream.com;",
"MicrosoftSharePointTeamServices": "numbers-and-dots",
"X-Content-Type-Options": "nosniff",
"X-MS-InvokeApp": "1; RequireReadOnly",
"Timing-Allow-Origin": "*",
"x-ms-apihub-cached-response": "false",
"Cache-Control": "max-age=0, private",
"Date": "Sun, 04 Jul 2021 06:42:53 GMT",
"P3P": "CP=\"SOME CODES HERE\"",
"X-AspNet-Version": "4.0.30319",
"X-Powered-By": "ASP.NET",
"Content-Type": "application/json; charset=utf-8",
"Expires": "Sat, 19 Jun 2021 06:42:54 GMT",
"Last-Modified": "Sun, 04 Jul 2021 06:42:54 GMT",
"Content-Length": "3938"
},
"body": {
"#odata.etag": "\"2\"",
"ItemInternalId": "1",
"ID": 1,
"Title": "View",
"Year": {
"#odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedReference",
"Id": 2,
"Value": "2023"
},
"Year#Id": 2,
"ProgramType": {
"#odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedReference",
"Id": 0,
"Value": "Program Type 01"
},
"ProgramType#Id": 0,
"ProgramName": {
"#odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedReference",
"Id": 1,
"Value": "02"
},
"ProgramName#Id": 1,
"TeamOwner_x002f_s": [
{
"#odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
"Claims": "i:0#.f|membership|user_1#my-tenant.onmicrosoft.com",
"DisplayName": "User Name 1",
"Email": "user_1#my-tenant.onmicrosoft.com",
"Picture": "https://my-tenant.sharepoint.com/sites/ExampleTeam/_layouts/15/UserPhoto.aspx?Size=L&AccountName=user_1#my-tenant.onmicrosoft.com",
"Department": null,
"JobTitle": null
},
{
"#odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
"Claims": "i:0#.f|membership|user_2#my-tenant.onmicrosoft.com",
"DisplayName": "User Name 2",
"Email": "user_2#my-tenant.onmicrosoft.com",
"Picture": "https://my-tenant.sharepoint.com/sites/ExampleTeam/_layouts/15/UserPhoto.aspx?Size=L&AccountName=user_2#my-tenant.onmicrosoft.com",
"Department": null,
"JobTitle": null
}
],
"TeamOwner_x002f_s#odata.type": "#Collection(Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser)",
"TeamOwner_x002f_s#Claims": [
"i:0#.f|membership|user_1#my-tenant.onmicrosoft.com",
"i:0#.f|membership|user_2#my-tenant.onmicrosoft.com"
],
"TeamOwner_x002f_s#Claims#odata.type": "#Collection(String)",
"Team_x0020_Member_x002f_s": [
{
"#odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
"Claims": "i:0#.f|membership|user_3#my-tenant.onmicrosoft.com",
"DisplayName": "User Name 3",
"Email": "user_3#my-tenant.onmicrosoft.com",
"Picture": "https://my-tenant.sharepoint.com/sites/ExampleTeam/_layouts/15/UserPhoto.aspx?Size=L&AccountName=user_3#my-tenant.onmicrosoft.com",
"Department": null,
"JobTitle": null
}
],
"Team_x0020_Member_x002f_s#odata.type": "#Collection(Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser)",
"Team_x0020_Member_x002f_s#Claims": [
"i:0#.f|membership|user_3#my-tenant.onmicrosoft.com"
],
"Team_x0020_Member_x002f_s#Claims#odata.type": "#Collection(String)",
"Status": {
"#odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedReference",
"Id": 0,
"Value": "Details Added"
},
"Status#Id": 0,
"Modified": "2021-07-04T03:57:16Z",
"Created": "2021-07-04T03:51:18Z",
"Author": {
"#odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
"Claims": "i:0#.f|membership|user_1#my-tenant.onmicrosoft.com",
"DisplayName": "User Name 1",
"Email": "user_1#my-tenant.onmicrosoft.com",
"Picture": "https://my-tenant.sharepoint.com/sites/ExampleTeam/_layouts/15/UserPhoto.aspx?Size=L&AccountName=user_1#my-tenant.onmicrosoft.com",
"Department": null,
"JobTitle": null
},
"Author#Claims": "i:0#.f|membership|user_1#my-tenant.onmicrosoft.com",
"Editor": {
"#odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
"Claims": "i:0#.f|membership|user_1#my-tenant.onmicrosoft.com",
"DisplayName": "User Name 1",
"Email": "user_1#my-tenant.onmicrosoft.com",
"Picture": "https://my-tenant.sharepoint.com/sites/ExampleTeam/_layouts/15/UserPhoto.aspx?Size=L&AccountName=user_1#my-tenant.onmicrosoft.com",
"Department": null,
"JobTitle": null
},
"Editor#Claims": "i:0#.f|membership|user_1#my-tenant.onmicrosoft.com",
"{Identifier}": "Lists%252fMy%2bList%2bName%252f1_.000",
"{IsFolder}": false,
"{Thumbnail}": {
"Large": null,
"Medium": null,
"Small": null
},
"{Link}": "https://my-tenant.sharepoint.com/sites/ExampleTeam/_layouts/15/listform.aspx?PageType=4&ListId=list-id-here&ID=1&ContentTypeID=content-type-id-here",
"{Name}": "View",
"{FilenameWithExtension}": "View",
"{Path}": "Lists/My List Name/",
"{FullPath}": "Lists/My List Name/1_.000",
"{VersionNumber}": "2.0"
}
}
Question
Is it possible to specify Team members by Email in the Graph API request?
Or do I need to somehow get the User ID of each user specified (and if so, what is the best way to do that)?
Update
I tried this HTTP connector GET request in the hopes it would return User ID for each Person:
https://graph.microsoft.com/v1.0/sites/site-id-here/lists/list-id-here/items/item-id-here?expand=fields(select=TeamOwner%5Fx002f%5Fs)
But it returned even less information:
"fields": {
"#odata.etag": "\"letters-and-numbers,2\"",
"TeamOwner_x002f_s": [{
"LookupId": 9,
"LookupValue": "User Name 1",
"Email": "user_1#my-tenant.onmicrosoft.com"
},
{
"LookupId": 27,
"LookupValue": "User Name 2",
"Email": "user_2#my-tenant.onmicrosoft.com"
}
]
}
API docs reference for this approach
Get specific column values of a listItem
GET https://graph.microsoft.com/v1.0/sites/{site-id}/lists/{list-id}/items/{item-id}?expand=fields(select=Column1,Column2)

You can get the user information from Microsoft Graph itself, what you can try out is List Users with filter parameter.
like this:
GET https://graph.microsoft.com/v1.0/users?$filter(mail eq 'user_1#my-tenant.onmicrosoft.com')
OR
You can list all users and do a mail/displayName search(Ctrl+F) on results at graph explorer.
By these you will be able to get userPrincipalName as well as id.
Permission required:-
One of the following permissions is required to call this API.
Delegated (work or school account) - User.ReadBasic.All,
User.Read.All, User.ReadWrite.All, Directory.Read.All,
Directory.ReadWrite.All, Directory.AccessAsUser.All
Delegated
(personal Microsoft account) - Not supported.
Application - User.Read.All, User.ReadWrite.All, Directory.Read.All,
Directory.ReadWrite.All
Thanks.

Related

Microsoft graph user delta - manager issue

When I try to get users via the delta endpoint:
https://graph.microsoft.com/v1.0/users/delta?$select=id,displayName,manager
The returned response will contain some users with the manager property defined, as expected:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users(id,displayName,manager)",
"#odata.nextLink": "https://graph.microsoft.com/v1.0/users/delta?$skiptoken=[token]",
"value": [
{
"displayName": "user1",
"id": "id1"
},
{
"displayName": "user2",
"id": "id2",
"manager#delta": [
{
"#odata.type": "#microsoft.graph.user",
"id": "managerId1"
}
]
},
{
"displayName": "user3",
"id": "id3"
},
// etc
]
}
However when I then query the returned nextLink to get the second page, the same set of users are returned as the first page, and this time without any managers. Also note that the #odata.context value has changed now too:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users",
"#odata.nextLink": "https://graph.microsoft.com/v1.0/users/delta?$skiptoken=[token]",
"value": [
{
"displayName": "user1",
"id": "id1"
},
{
"displayName": "user2",
"id": "id2"
},
{
"displayName": "user3",
"id": "id3"
},
... etc
]
}
When I remove the displayName property, so am only selecting for id and manager, the paging seems to work correctly:
https://graph.microsoft.com/v1.0/users/delta?$select=id,manager
The issue has been reproduced when including the userPrincipalName property in the $select too.

Unable to retrieve event details using Microsoft Graph API 1.0

Has anyone got Microsoft Graph API working for EventMessage? i.e reading email content of EventMessage using Graph API.
Looks like it has actionable card and graph API 1.0 is not able to read it.
Provided delegate access to user for a room resource.
On event creation for that room, mail is received by the delegated user in inbox. The mail type is eventMessage ("#odata.type": "#microsoft.graph.eventMessage").
On fetching the mail through GraphAPI v1.0, the event values are not visible in the response.
Also on setting the Expand property for the mail in graph API as per docs, results in below error.
{ "error": {
"code": "BadRequest",
"message": "Parsing Select and Expand failed.",
"innerError": {
"request-id": "310bbcce-bdd8-4cb6-890c-035243a5ab6d",
"date": "2020-01-21T09:18:10"
}
}
}
I'm unable to repro your issue. The Microsoft Graph API returns details for event messages. Can you provide repro steps, request/response capture, and the values that you'd expect to see?
I used v1.0/me/messagesto get all of the messages to find an eventMessage. I then perform the following to get details on the eventMessage:
GET https://graph.microsoft.com/v1.0/me/messages/{messagedId}
Response body:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('d09-94-498-a9777d4b')/messages/$entity",
"#odata.type": "#microsoft.graph.eventMessage",
"#odata.etag": "W/\"DAA2pU9s\"",
"id": "AAMkADEzOTExYjJkAAA=",
"createdDateTime": "2020-01-24T14:47:24Z",
"lastModifiedDateTime": "2020-01-24T21:08:07Z",
"changeKey": "DApU9s",
"categories": [],
"receivedDateTime": "2020-01-24T14:47:25Z",
"sentDateTime": "2020-01-24T14:47:11Z",
"hasAttachments": false,
"internetMessageId": "<AM5P3M#A38.EURPRD83.prod.outlook.com>",
"subject": "Accepted: Microsoft Graph DevX Roadmap",
"bodyPreview": "",
"importance": "normal",
"parentFolderId": "AAMk3AAA=",
"conversationId": "AAQkADEzOU4=",
"conversationIndex": "AdXReVPepTg==",
"isDeliveryReceiptRequested": null,
"isReadReceiptRequested": false,
"isRead": true,
"isDraft": false,
"webLink": "https://outlook.office365.com/owa/?ItemID=AAMkA%3D&exvsurl=1&viewmodel=ReadMessageItem",
"inferenceClassification": "focused",
"meetingMessageType": "meetingAccepted",
"body": {
"contentType": "text",
"content": ""
},
"sender": {
"emailAddress": {
"name": "Nicole",
"address": "sig#contoso.com"
}
},
"from": {
"emailAddress": {
"name": "Nicole",
"address": "sig#contoso.com"
}
},
"toRecipients": [
{
"emailAddress": {
"name": "Michael Mainer",
"address": "mm#contoso.com"
}
}
],
"ccRecipients": [],
"bccRecipients": [],
"replyTo": [],
"flag": {
"flagStatus": "notFlagged"
}
}

personal onedrive is returning same id for drive and user?

When reviewing some example OneDrive Items using Graph Explorer, it appears that the user.id and the parentReference.driveId are identical. Is MSFT re-using one Id to identify both the user and drive object?
I have been testing my app against a number of OneDrive Business accounts and I do not believe I have seen this scenario. I would like to understand if this is something specific to OneDrive Personal and/or what implications it might have...
I am not sure this will cause any issues, but my understanding was that all "IDs" were generally unique.
Here's a redacted snippet of JSON returned from Graph Explorer to illustrate what I am seeing:
{
"#microsoft.graph.downloadUrl": "https://xxx.yyy",
"createdDateTime": "2018-12-04T19:02:41.173Z",
"cTag": "aYzpDQjBCMTc0REJFRUY2RTU4ITMxNzEuMjI1",
"eTag": "aQ0IwQjE3NERCRUVGNkU1OCEzMTcxLjk",
"id": "<MY_USER_ID>!3171",
"lastModifiedDateTime": "2018-12-04T19:10:36.83Z",
"name": "blah-2018.docx",
"size": 250538,
"webUrl": "https://1drv.ms/...",
"createdBy": {
"application": {
"displayName": "MSOffice15",
"id": "480728c5"
},
"device": {
"id": "188000899fbcaf"
},
"user": {
"displayName": "My Name",
"id": "<MY_USER_ID>"
}
},
"lastModifiedBy": {
"application": {
"displayName": "MSOffice15",
"id": "480728c5"
},
"device": {
"id": "188000899fbcaf"
},
"user": {
"displayName": "My Name",
"id": "<MY_USER_ID>"
}
},
"parentReference": {
"driveId": "<MY_USER_ID>",
"driveType": "personal",
"id": "<MY_USER_ID>!109",
"path": "/drive/root:"
},
"file": {
"mimeType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"hashes": {
"sha1Hash": "F0370F54348ED81F421EB036868AEBE5253AF58A"
}
},
"fileSystemInfo": {
"createdDateTime": "2018-12-04T19:02:41.173Z",
"lastModifiedDateTime": "2018-12-04T19:02:38.633Z"
}
},
Note that MY_USER_ID is all uppercase in the prefix of the driveItem.Id. It is all lowercase as my driveId and my userId.
OneDrive Personal isn't reusing the same id, it's using the User's Id as a prefix for Drive and DriveItem ids:
{User Id}!{OneDrive ID}
Since there is a 1:1 relationship between an MSA and it's Drive, there isn't much call for a more complex mechanism. OneDrive for Business, on the other hand, is hosted in SharePoint and, as such, use's SharePoint's identifiers.
`

Office 365 API - Get meeting room location and capacity

I'm doing an integration of mobile app with the Office 365 Calendar. I want to show room capacity and location on the screen. I trying to find an API to get meeting room info (this info is available on website when selecting room as user).
I tried both Outlook REST API (version 2.0) and Microsoft Graph but found nothing in the docs on how to get such info.
Where I can find such API if it exists?
I know this is an old question but you can do it using the List Places API in Graph API: https://learn.microsoft.com/en-us/graph/api/place-list?view=graph-rest-1.0&tabs=http
GET https://graph.microsoft.com/v1.0/places/microsoft.graph.room
RESPONSE:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#places/microsoft.graph.room",
"value": [
{
"id": "3162F1E1-C4C0-604B-51D8-91DA78989EB1",
"emailAddress": "cf100#contoso.com",
"displayName": "Conf Room 100",
"address": {
"street": "4567 Main Street",
"city": "Buffalo",
"state": "NY",
"postalCode": "98052",
"countryOrRegion": "USA"
},
"geoCoordinates": {
"latitude": 47.640568390488626,
"longitude": -122.1293731033803
},
"phone": "000-000-0000",
"nickname": "Conf Room",
"label": "100",
"capacity": 50,
"building": "1",
"floorNumber": 1,
"isManaged": true,
"isWheelChairAccessible": false,
"bookingType": "standard",
"tags": [
"bean bags"
],
"audioDeviceName": null,
"videoDeviceName": null,
"displayDevice": "surface hub"
},
{
"id": "3162F1E1-C4C0-604B-51D8-91DA78970B97",
"emailAddress": "cf200#contoso.com",
"displayName": "Conf Room 200",
"address": {
"street": "4567 Main Street",
"city": "Buffalo",
"state": "NY",
"postalCode": "98052",
"countryOrRegion": "USA"
},
"geoCoordinates": {
"latitude": 47.640568390488625,
"longitude": -122.1293731033802
},
"phone": "000-000-0000",
"nickname": "Conf Room",
"label": "200",
"capacity": 40,
"building": "2",
"floorNumber": 2,
"isManaged": true,
"isWheelChairAccessible": false,
"bookingType": "standard",
"tags": [
"benches",
"nice view"
],
"audioDeviceName": null,
"videoDeviceName": null,
"displayDevice": "surface hub"
}
]
}

Microsoft graph API: empty BCC field

Scenario:
Jenny and Tom have gmail accounts. Jerry is o365 user
Jenny sends email to Tom (in TO: field) and BCC: Jerry.
When Jerry gets message from graph api and doesn't see himself in BCC entry, which is empty (in both versions of API - 1 and beta).
If Jenny, Jerry and Tom would be in the group and Jenny have sent email to group, it would exactly the same for Jerry. There is no way to distinguish those two cases.
I would expect that when user is in BCC he should see himself there.
I know if sender is O365 user and getsMessage via graph API he will see all BCC users.
Is there any API call that I could use to learn that given user was in BCC of given message?
Here is what Jerry sees:
{
"#odata.etag": "W/\"CQAAABYAAACWhXAbJxpFRb0V3o8I2vIPAACwRstA\"",
"id": "AAMkAGMyNDE4NGI5LTRlNmItNDUzMy04ZTBlLTgxNjM3MDZhODE5NgBGAAAAAABT6x1NTxG_S7bw4uHJw-_tBwDEbTtXm_E6Rr8LT_x2xj5KAAAAnJfJAACWhXAbJxpFRb0V3o8I2vIPAACwGG_qAAA=",
"createdDateTime": "2017-11-15T19:50:57Z",
"lastModifiedDateTime": "2017-11-15T19:50:57Z",
"changeKey": "CQAAABYAAACWhXAbJxpFRb0V3o8I2vIPAACwRstA",
"categories": [],
"receivedDateTime": "2017-11-15T19:50:57Z",
"sentDateTime": "2017-11-15T19:50:54Z",
"hasAttachments": false,
"internetMessageId": "<CAHF5u5KsOQd43c4dtnx0uTQRor_dt7Y1uy=F3G4i6-c+TdUgug#mail.gmail.com>",
"subject": "test bcc=",
"bodyPreview": "test bcc",
"importance": "normal",
"parentFolderId": "AAMkAGMyE4NGI5LTRlNmItNDUzMy04ZTBlLTgxNjM3MDZhODE5NgAuAAAAAABT6x1NTxG_S7bw4uHJw-_tAQDEbTtXm_E6Rr8LT_x2xj5KAAAAnJfJAAA=",
"conversationId": "AAQkAGMyGI5LTRlNmItNDUzMy04ZTBlLTgxNjM3MDZhODE5NgAQAMaAYzrmsyxGq7ZujLh23q0=",
"conversationIndex": "AQHTXxoBjOuazLEartm6MuHberQ==",
"isDeliveryReceiptRequested": null,
"isReadReceiptRequested": false,
"isRead": false,
"isDraft": false,
"webLink": "https://outlook.office365.com/owa/?ItemID=AAMkAGMyNDE4NAACwGG%2BqAAA%3D&exvsurl=1&viewmodel=ReadMessageItem",
"inferenceClassification": "focused",
"unsubscribeData": [],
"unsubscribeEnabled": false,
"body": {
"contentType": "html",
"content": "<html>\r\n<head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\r\n<meta content=\"text/html; charset=utf-8\">\r\n</head>\r\n<body>\r\n<div dir=\"ltr\">test bcc<br>\r\n</div>\r\n</body>\r\n</html>\r\n"
},
"sender": {
"emailAddress": {
"name": "Jenny",
"address": "jenny1234#gmail.com"
}
},
"from": {
"emailAddress": {
"name": "Jenny",
"address": "jenny1234#gmail.com"
}
},
"toRecipients": [
{
"emailAddress": {
"name": "Tom",
"address": "tom1234#gmail.com"
}
}
],
"ccRecipients": [],
"bccRecipients": [],
"replyTo": [],
"mentionsPreview": null,
"flag": {
"flagStatus": "notFlagged"
}
},
For any messages that comes from an external source (in this case GMail), there is no BCC data available.
This works this way in order to meet the requirements set forth for "Blind Carbon Copy" in RFC 2822.

Resources