Related
We have an application that uses the Security eDiscovery Graph API URLs to create exports based on a Case/Review Set that already exists within the Microsoft Compliance solution. The solution is correctly exporting to the Storage Account container we select, but we do not have a way to determine which folder in the container the export was sent to. See below for example flow/output.
Create Export call (https://learn.microsoft.com/en-us/graph/api/security-ediscoveryreviewset-export?view=graph-rest-beta&tabs=http):
https://graph.microsoft.com/beta/security/cases/ediscoveryCases/{CASE_ID}/reviewSets/{REVIEW_SET}/export
Payload sent:
{
"outputName": "{OUTPUT}",
"description": "",
"exportOptions": "originalFiles",
"exportStructure": "directory",
"azureBlobContainer": "{REDACTED}",
"azureBlobToken": "{REDACTED}"
}
First Response from URL in Location Header:
https://graph.microsoft.com/beta/security/cases/ediscoverycases({CASE_ID})/operations({OPERATION_ID})
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#security/cases/ediscoveryCases({CASE_ID})/operations/$entity",
"#odata.type": "#microsoft.graph.security.ediscoveryExportOperation",
"createdDateTime": "2023-02-16T15:16:12.2704755Z",
"completedDateTime": "0001-01-01T00:00:00Z",
"percentProgress": 0,
"status": "running",
"action": "contentExport",
"id": "86b2309224dd42ccb79271245ea542b6",
"outputName": "{REDACTED}",
"description": "",
"outputFolderId": null,
"azureBlobContainer": null,
"azureBlobToken": null,
"exportOptions": null,
"exportStructure": "none",
"createdBy": {
"application": null,
"user": {
"id": null,
"displayName": null,
"userPrincipalName": "{REDACTED}"
}
}
}
Response when progress hits 100%
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#security/cases/ediscoveryCases({CASE_ID})/operations/$entity",
"#odata.type": "#microsoft.graph.security.ediscoveryExportOperation",
"createdDateTime": "2023-02-16T15:16:12.2704755Z",
"completedDateTime": "2023-02-16T15:28:16.438Z",
"percentProgress": 100,
"status": "succeeded",
"action": "contentExport",
"id": "86b2309224dd42ccb79271245ea542b6",
"outputName": "{REDACTED}",
"description": "",
"outputFolderId": null,
"azureBlobContainer": null,
"azureBlobToken": null,
"exportOptions": null,
"exportStructure": "none",
"createdBy": {
"application": null,
"user": {
"id": null,
"displayName": null,
"userPrincipalName": "{REDACTED}"
}
}
}
Notice that several fields from the Operations call (https://learn.microsoft.com/en-us/graph/api/resources/security-ediscoveryexportoperation?view=graph-rest-beta) are set to null including exportOptions, azureBlobContainer, azureBlobToken, and exportOptions. Then exportStructure is set incorrectly to none.
The exported folder looks like below in the Azure Storage account. That GUID is not surfaced anywhere in the API calls we are getting and makes it very difficult to download the exported files programatically. Is this possible currently?
My goal is to display the 6 most recent items in the current users OneDrive.
Using https://graph.microsoft.com/v1.0/me/drive/recent?top=6 gives me the correct documents.
Some of these documents are OneNote Items.
At www.office.com the OneNote Items are displayed with the Notebook's displayname.
In the API response only the filename is contained.
Testing this is Microsoft's example data here:
https://developer.microsoft.com/en-us/graph/graph-explorer
Example response
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(driveItem)",
"#odata.nextLink": "https://graph.microsoft.com/v1.0/me/drive/recent?top=6&expand=section&$skiptoken=s!Njs3NGI0MzJjYS1mNmIzLTQ5YmQtOWIxMC02OTIyNjRlMTI3YTI",
"value": [
...
{
"#odata.type": "#microsoft.graph.driveItem",
"createdDateTime": "2017-08-07T16:08:45Z",
"id": "01BYE5RZ2IKLBQXYXELFD23BMJIB545TH6",
"lastModifiedDateTime": "2020-01-09T03:02:37Z",
"name": "Fabrikam.one",
"webUrl": "https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/_layouts/15/Doc.aspx?sourcedoc=%7B0BC35248-E4E2-4759-AD85-89407BCECCFE%7D&file=Fabrikam.one&action=edit&mobileredirect=true&wdorigin=Sharepoint&DefaultItemOpen=1",
"size": 55782,
"createdBy": {
"user": {
"email": "MeganB#M365x214355.onmicrosoft.com",
"displayName": "Megan Bowen"
}
},
"lastModifiedBy": {
"user": {
"email": "",
"displayName": "System Account"
}
},
"file": {
"mimeType": "application/msonenote"
},
"fileSystemInfo": {
"createdDateTime": "2017-08-07T16:08:45Z",
"lastModifiedDateTime": "2020-01-09T03:02:37Z"
},
"remoteItem": {
"createdDateTime": "2017-08-07T16:08:45Z",
"id": "01BYE5RZ2IKLBQXYXELFD23BMJIB545TH6",
"lastModifiedDateTime": "2020-01-09T03:02:37Z",
"name": "Fabrikam.one",
"size": 55782,
"webDavUrl": "https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/Documents/Fabrikam.one",
"webUrl": "https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/_layouts/15/Doc.aspx?sourcedoc=%7B0BC35248-E4E2-4759-AD85-89407BCECCFE%7D&file=Fabrikam.one&action=edit&mobileredirect=true&wdorigin=Sharepoint&DefaultItemOpen=1",
"createdBy": {
"user": {
"email": "MeganB#M365x214355.onmicrosoft.com",
"displayName": "Megan Bowen"
}
},
"file": {
"mimeType": "application/msonenote"
},
"fileSystemInfo": {
"createdDateTime": "2017-08-07T16:08:45Z",
"lastModifiedDateTime": "2020-01-09T03:02:37Z"
},
"lastModifiedBy": {
"user": {
"email": "",
"displayName": "System Account"
}
},
"parentReference": {
"driveType": "business",
"driveId": "b!-RIj2DuyvEyV1T4NlOaMHk8XkS_I8MdFlUCq1BlcjgmhRfAj3-Z8RY2VpuvV_tpd",
"id": "01BYE5RZ56Y2GOVW7725BZO354PWSELRRZ"
},
"shared": {
"scope": "users"
},
"sharepointIds": {
"listId": "23f045a1-e6df-457c-8d95-a6ebd5feda5d",
"listItemId": "36",
"listItemUniqueId": "0bc35248-e4e2-4759-ad85-89407bceccfe",
"siteId": "d82312f9-b23b-4cbc-95d5-3e0d94e68c1e",
"siteUrl": "https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com",
"webId": "2f91174f-f0c8-45c7-9540-aad4195c8e09"
}
}
},
...
]
}
Is there a way to retrieve the OneNote notebook's name from here?
The API provides a way to retrieve all notebooks like so:
https://graph.microsoft.com/v1.0/me/onenote/notebooks
However I do not see a connection between these responses.
Maybe relevant how to find OneNote Notebook object from driveItem with MS Graph? - this shows a workaround. I am curious if there is a better solution.
I want to use the graph api to get the teams a list of users is a member/owner of. I am using this endpoint to pass the list of users, then select the properties of the group that I am interested in:
/beta/users/$filter=id+in+('user-1','user-2','user-15')$expand=transitiveMemberOf($select=id,resourceProvisioningOptions,displayName,mailNickname)&$select=id,resourceProvisioningOptions,displayName
This will return a list of groups the member is apart of, including the Teams the member is apart of (up to 15 users). It will filter the groups to only return id,resourceProvisioningOption,displayName and mailNickname.
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users(id,resourceProvisioningOptions,displayName,transitiveMemberOf(id,resourceProvisioningOptions,displayName,mailNickname))",
"value": [
{
"id": "user-1",
"displayName": "Jeff Smith",
"transitiveMemberOf": [
{
"#odata.type": "#microsoft.graph.directoryRole",
"id": "directoryRole-1",
"displayName": null
},
{
"#odata.type": "#microsoft.graph.directoryRole",
"id": "directoryRole-2",
"displayName": null
},
{
"#odata.type": "#microsoft.graph.group",
"id": "team-id-1",
"resourceProvisioningOptions": [
"Team"
],
"displayName": "My Team 1",
"mailNickname": "MyTeam1"
},
{
"#odata.type": "#microsoft.graph.directoryRole",
"id": "directoryRole-3",
"displayName": null
},
{
"#odata.type": "#microsoft.graph.group",
"id": "team-id-2",
"resourceProvisioningOptions": [
"Team"
],
"displayName": "My Team 2",
"mailNickname": "MyTeam2"
}
]
}
]
}
Since the user is apart of Azure directory groups, those are returned, but the resourceProvisioningOptions identifies if the user is on a team. In this case - 2 teams.
Problem
When looking in the Teams App, we see that the user is actually apart of the 10 different teams.
When calling this endpoint: https://graph.microsoft.com/v1.0/users/user-1/joinedTeams we see that the user is apart of 10 teams
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#teams",
"#odata.count": 10,
"value": [
{
"id": "team-id-1",
"createdDateTime": null,
"displayName": "Team 1",
"description": "Team1",
"internalId": null,
"classification": null,
"specialization": null,
"visibility": null,
"webUrl": null,
"isArchived": false,
"isMembershipLimitedToOwners": null,
"memberSettings": null,
"guestSettings": null,
"messagingSettings": null,
"funSettings": null,
"discoverySettings": null,
"summary": null
},
{
"id": "team-id-2",
"createdDateTime": null,
"displayName": "Team 2",
"description": "Team2",
"internalId": null,
"classification": null,
"specialization": null,
"visibility": null,
"webUrl": null,
"isArchived": false,
"isMembershipLimitedToOwners": null,
"memberSettings": null,
"guestSettings": null,
"messagingSettings": null,
"funSettings": null,
"discoverySettings": null,
"summary": null
},
...
{
"id": "team-id-10",
"createdDateTime": null,
"displayName": "Team 3",
"description": "Team3",
"internalId": null,
"classification": null,
"specialization": null,
"visibility": null,
"webUrl": null,
"isArchived": false,
"isMembershipLimitedToOwners": null,
"memberSettings": null,
"guestSettings": null,
"messagingSettings": null,
"funSettings": null,
"discoverySettings": null,
"summary": null
}
]
}
Questions:
Is there another endpoint that I can use to pass a list of users and get the teams they are owner/member of?
Why is the data different between endpoints
I am trying to avoid calling the /joinedTeams endpoint due to number of users and rate limiting.
You could use the /joinedTeams endpoint, but also put those calls in a batch to MS Graph.
See: https://learn.microsoft.com/en-us/graph/json-batching
This would allow you to send a batch of 20 (i think) requests in one call to the graph making it much faster and less likely to be throttled.
I'm am developing a power automate flow using the Beta Advanced eDiscovery Graph API which I do the following:
Create a Tag structure for an Advanced eDiscovery Case. This consists of a Section/Group (Parent) Tag named 'Privilege' the 4 child Tags. (see code below) All functions are working w/o error and appear in the eDisovery Case.
Using the Beta Graph API I create a Review Set Query. (see code below) This too is working w/o errors and appears in the eDiscovery Case Review.
Lastly, Using the Beta Graph API I apply one of the child tags associated to the review query from step 2. Again this works w/o error.
The issue is that when I open the Review in Advanced eDiscovery I see the messages that match the review query matches on with Tags, however when I view the message the child tag does not get highlighted.
If I apply a tag manually then again view the message the Tag is highlighted (selected).
Also, when in the Review Set page tag Filter only lists the Parent Tag not the child tag which I specified in the applytag Graph Apl call.
Following are Graph API calls, URI, Body, and Outputs:
Make the Group Tag
https://graph.microsoft.com/beta/compliance/ediscovery/cases/9bb82c7c-bba3-4ad2-a584-4ec30a33544b/tags
Body
{
"displayName": "Privilege",
"childSelectability": "Many"
}
Output
{
"#odata.context": "graph.microsoft.com/beta/$metadata#compliance/ediscovery/cases('9bb82c7c-bba3-4ad2-a584-4ec30a33544b')/tags/$entity",
"displayName": "Privilege",
"description": null,
"lastModifiedDateTime": "2021-11-06T21:13:59.6518126Z",
"childSelectability": "Many",
**"id": "4ab4daccb8c14ef789be7d2580bab245",**
"createdBy": {
"user": {
"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"displayName": null,
"userPrincipalName": "xxxxxxxxxxxxx.onmicrosoft.com"
}
}
}
Make 4 child options
1.
POST //graph.microsoft.com/beta/compliance/ediscovery/cases/9bb82c7c-bba3-4ad2-a584-4ec30a33544b/tags
Body
{
"displayName": "Attorney Work Product",
"childSelectability": "Many",
"parent#odata.bind": "//graph.microsoft.com/beta/compliance/ediscovery/cases/9bb82c7c-bba3-4ad2-a584-4ec30a33544b/tags/**4ab4daccb8c14ef789be7d2580bab245**"
}
Outputs
Status Code:201
{
"#odata.context": "://graph.microsoft.com/beta/$metadata#compliance/ediscovery/cases('9bb82c7c-bba3-4ad2-a584-4ec30a33544b')/tags/$entity",
"displayName": "Attorney Work Product",
"description": null,
"lastModifiedDateTime": "2021-11-06T21:14:00.2924266Z",
"childSelectability": "Many",
"id": "6646aa1cde37408dad6be43723dd0503",
"createdBy": {
"user": {
"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"displayName": null,
"userPrincipalName": "xxxxxxxxxxxxxxxxxxxxxx.onmicrosoft.com"
}
}
}
2.POST
//graph.microsoft.com/beta/compliance/ediscovery/cases/9bb82c7c-bba3-4ad2-a584-4ec30a33544b/tags
Body
{
"displayName": "Attorney Communication",
"childSelectability": "Many",
"parent#odata.bind": "https://graph.microsoft.com/beta/compliance/ediscovery/cases/9bb82c7c-bba3-4ad2-a584-4ec30a33544b/tags/4ab4daccb8c14ef789be7d2580bab245"
}
Outputs
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#compliance/ediscovery/cases('9bb82c7c-bba3-4ad2-a584-4ec30a33544b')/tags/$entity",
"displayName": "Attorney Communication",
"description": null,
"lastModifiedDateTime": "2021-11-06T21:14:01.1385531Z",
"childSelectability": "Many",
"id": "03a1f53540874e7085dc57bdb6e71b29",
"createdBy": {
"user": {
"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"displayName": null,
"userPrincipalName": "xxxxxxxxxxxxxxxx.onmicrosoft.com"
}
}
}
3. POST
//graph.microsoft.com/beta/compliance/ediscovery/cases/9bb82c7c-bba3-4ad2-a584-4ec30a33544b/tags
Body
{
"displayName": "Potentially Privileged",
"childSelectability": "Many",
"parent#odata.bind": "https://graph.microsoft.com/beta/compliance/ediscovery/cases/9bb82c7c-bba3-4ad2-a584-4ec30a33544b/tags/4ab4daccb8c14ef789be7d2580bab245"
}
Outputs
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#compliance/ediscovery/cases('9bb82c7c-bba3-4ad2-a584-4ec30a33544b')/tags/$entity",
"displayName": "Potentially Privileged",
"description": null,
"lastModifiedDateTime": "2021-11-06T21:14:01.5424902Z",
"childSelectability": "Many",
"id": "dee7b721d042423a870f9fd695cff573",
"createdBy": {
"user": {
"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"displayName": null,
"userPrincipalName": "xxxxxxxxxxxxxxxxxxxxxx.onmicrosoft.com"
}
}
}
4. Post
://graph.microsoft.com/beta/compliance/ediscovery/cases/9bb82c7c-bba3-4ad2-a584-4ec30a33544b/tags
body
{
"displayName": "Privileged",
"childSelectability": "Many",
"parent#odata.bind": "https://graph.microsoft.com/beta/compliance/ediscovery/cases/9bb82c7c-bba3-4ad2-a584-4ec30a33544b/tags/4ab4daccb8c14ef789be7d2580bab245"
}
Outputs
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#compliance/ediscovery/cases('9bb82c7c-bba3-4ad2-a584-4ec30a33544b')/tags/$entity",
"displayName": "Privileged",
"description": null,
"lastModifiedDateTime": "2021-11-06T21:14:02.0233516Z",
"childSelectability": "Many",
"id": "2bb05d142ab7455eb16a820a54f147fb",
"createdBy": {
"user": {
"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"displayName": null,
"userPrincipalName": "xxxxxxxxxxxxxxxxxx.onmicrosoft.com"
}
}
}
enter image description here
Make Review Set Query
//graph.microsoft.com/beta/compliance/ediscovery/cases/f193df40-551d-451c-9ef8-135df2475fc2/reviewSets/921d10fa-9a16-44e5-8240-d9f9cb7d1b5f/queries
Body
{
"displayName": "Potentially Privileged",
"query": "(SenderAuthor:\"adeleV#pageman.onmicrosoft.com\" OR Recipients:\"adeleV#xxxxxxxxxxxx.onmicrosoft.com\")"
}
Outputs
Status code 201
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#compliance/ediscovery/cases('f193df40-551d-451c-9ef8-135df2475fc2')/reviewSets('921d10fa-9a16-44e5-8240-d9f9cb7d1b5f')/queries/$entity",
"displayName": "Potentially Privileged",
"query": "((SenderAuthor:\"adeleV#xxxxxxxxxxx.onmicrosoft.com\" OR Recipients:\"adeleV#xxxxxxxxx.onmicrosoft.com\"))",
"lastModifiedDateTime": "2021-11-11T21:37:38.4273704Z",
"id": "1c2670a8-7542-4168-9873-b62b3d097cc5",
"createdDateTime": "2021-11-11T21:37:38.4273704Z",
"lastModifiedBy": {
"user": {
"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"displayName": null,
"userPrincipalName": "xxxxxxxxxxxxxxxxxxx.onmicrosoft.com"
}
},
"createdBy": {
"user": {
"id": "xxxxxxxxxxxxxxxxxxxxxx",
"displayName": null,
"userPrincipalName": "xxxxxxxxxxxxxxx.onmicrosoft.com"
}
}
}
Apply Tag
//graph.microsoft.com/beta/compliance/ediscovery/cases/f193df40-551d-451c-9ef8-135df2475fc2/reviewSets/921d10fa-9a16-44e5-8240-d9f9cb7d1b5f/queries/1c2670a8-7542-4168-9873-b62b3d097cc5/applyTags
Body
{
"tagsToAdd": [
{
"id": "e4518b76afec491b8d845f87179791f3"
}
]
}
Outputs
Status Code 202
Using the location I track the progress until 100% complete
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#compliance/ediscovery/cases('f193df40-551d-451c-9ef8-135df2475fc2')/operations/$entity",
"#odata.type": "#microsoft.graph.ediscovery.tagOperation",
"createdDateTime": "2021-11-11T21:37:41.4396791Z",
"completedDateTime": "2021-11-11T21:40:42.919Z",
"percentProgress": 100,
"status": "succeeded",
"action": "applyTags",
"id": "b1755016878c49ed875ce9246c30614d",
"createdBy": {
"user": {
"id": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
"displayName": null,
"userPrincipalName": "xxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
enter image description here
enter image description here
enter image description here
I used Create Call of Microsoft Graph API to create a group call(audio). The connection has created successfully, but every member cannot receive any chat message posted by other members.
(picture)The phenomenon that everyone cannot receive other's message
Request as below:
POST https://graph.microsoft.com/beta/app/calls
Content-Type: application/json
Authorization: Bearer <Token>
{
"#odata.type": "#microsoft.graph.call",
"callbackUri": "https://myhostname.ngrok.io/callback/calling",
"mediaConfig": {
"#odata.type": "#microsoft.graph.serviceHostedMediaConfig"
},
"source": {
"identity": {
"application": {
"id": "myCallingAppId"
}
}
},
"subject": "Test Call",
"targets": [
{
"identity": {
"user": {
"id": "User_1-Id",
"displayName": "User_1-DisplayName"
}
},
"identity": {
"user": {
"id": "User_2-Id",
"displayName": "User_2-Name"
}
}
}
],
"tenantId": "myCallingAppTenant"
}
Response:
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#communications/calls/$entity",
"id": "481f0c00-ffff-41cd-bbc8-7e21fb5e8b1b",
"state": "establishing",
"transferState": null,
"terminationReason": null,
"direction": "outgoing",
"ringingTimeoutInSeconds": null,
"subject": "Test Call",
"callbackUri": "https://myhostname.ngrok.io/callback/calling",
"requestedModalities": [],
"activeModalities": [],
"routingPolicies": [],
"tenantId": "myCallingAppTenant",
"myParticipantId": "59e11e38-87d0-4ae5-b3ce-051ea26aa34d",
"mediaState": null,
"resultInfo": null,
"answeredBy": null,
"chatInfo": null,
"meetingInfo": null,
"meetingCapability": null,
"toneInfo": null,
"incomingContext": null,
"callRoutes": [],
"source": {
"region": null,
"languageId": null,
"identity": {
"user": null,
"device": null,
"phone": null,
"application": {
"id": "myCallingAppId",
"displayName": null
}
}
},
"targets": [
{
"region": null,
"languageId": null,
"identity": {
"application": null,
"device": null,
"phone": null,
"user": {
"id": "User_1-Id",
"displayName": "User_1-DisplayName"
}
}
},
{
"region": null,
"languageId": null,
"identity": {
"application": null,
"device": null,
"phone": null,
"user": {
"id": "User_2-Id",
"displayName": "User_2-DisplayName"
}
}
}
],
"mediaConfig": {
"#odata.type": "#microsoft.graph.serviceHostedMediaConfig",
"removeFromDefaultAudioGroup": null,
"preFetchMedia": []
}
}
Is any configuration missed. How to create a calling with normal message communication. Could anyone help me, thanks!