We have been busy working to enable organisations that leverage the Microsoft Purview eDiscovery Graph APIs to benefit from the enhancements in the new modern experience for eDiscovery. I am pleased to share that APIs have now been updated with additional parameters to enable organisations to now benefit from the following features already present in the modern experience within the Purview Portal:
- Ability to control the export package structure and item naming convention
- Trigger advanced indexing as part of the Statistics, Add to Review and Export jobs
- Enables for the first time the ability to trigger HTML transcription of Teams, Viva and Copilot interaction when adding to a review set
- Benefit from the new statistic options such as Include Categories and Include Keyword Report
- More granular control of the number of versions collected of modern attachments and documents collected directly collected from OneDrive and SharePoint
These changes were communicated as part of the M365 Message Center Post MC1115305. This change involved the beta version of the API calls being promoted into the V1.0 endpoint of the Graph API.
The following v1.0 API calls were updated as part of this work:
- Search Estimate Statistics – ediscoverySearch: estimateStatistics
- Search Export Report - ediscoverySearch: exportReport
- Search Export Result - ediscoverySearch: exportResult
- Search Add to ReviewSet – ediscoveryReviewSet: addToReviewSet
- ReviewSet Export - ediscoveryReviewSet: export
This blog post is intended to walk through the updates to each of these APIs and provide understanding on how to update your calls to these APIs to maintain a consistent outcome (and benefit from the new functionality).
If you are new to the Microsoft Purview eDiscovery APIs you can refer to my previous blog post on how to get started with them.
Getting started with the eDiscovery APIs | Microsoft Community Hub
Wait, but what about the custodian and noncustodial locations workflow in eDiscovery Classic (Premium)?
As you are probably aware, in the modern user experience for eDiscovery there have been some changes to the Data Sources tab and how it is used in the workflow.
Typically, organisations leveraging the Microsoft Purview eDiscovery APIs previously would have used the custodian and noncustodial data sources APIs to add the relevant data sources to the case using the following APIs.
ediscoveryCustodian resource type - Microsoft Graph v1.0 | Microsoft Learn
ediscoveryNoncustodialDataSource resource type - Microsoft Graph v1.0 | Microsoft Learn
Once added via the API calls, when creating a search these locations would be bound to a search.
This workflow in the API remains supported for backwards compatibility. This includes the creation of system generated case hold policies when applying holds to the locations via these APIs.
Organisations can continue to use this approach with the APIs. However, to simplify your code and workflow in the APIs consider using the following API call to add additional sources directly to the search.
Add additional sources - Microsoft Graph v1.0 | Microsoft Learn
Some key things to note if you continue to use the custodian and noncustodial data sources APIs in your automation workflow.
- This will not populate the new data sources tab in the modern experience for eDiscovery
- They can continue to be queried via the API calls
- Advanced indexing triggered via these APIs will have no influence on if advanced indexing is used in jobs triggered from a search
- Make sure you use the new parameters to trigger advanced indexing on the job when running the Statistics, Add to Review Set and Direct Export jobs
Generating Search Statistics
ediscoverySearch: estimateStatistics
In eDiscovery Premium (Classic) and the previous version of the APIs, generating statistics was a mandatory step before you could progress to either adding the search to a review set or triggering a direct export.
With the new modern experience for eDiscovery, this step is completely optional and is not mandatory. For organizations that previously generated search statistics but never checked or used the results before moving to adding the search to a review set or triggering a direct export job, they can now skip this step.
If organizations do want to continue to generate statistics, then calling the updated API with the same parameters call will continue to generate statistics for the search. An example of a previous call would look as follows:
POST /security/cases/ediscoveryCases/{ediscoveryCaseId}/searches/{ediscoverySearchId}/estimateStatistics
Historically this API didn’t require a request body. With the APIs now natively working with the modern experience for eDiscovery; the API call now supports a request body, enabling you to benefit from the new statistic options. Details on these new options can be found in the links below.
Create a search for a case in eDiscovery | Microsoft Learn
Evaluate and refine search results in eDiscovery | Microsoft Learn
If a search is run without a request body it will still generate the following information:
- Total matches and volume
- Number of locations searched and the number of locations with hits
- Number of data sources searched and the number of data sources with hits
- The top five data sources that make up the most search hits matching your query
- Hit count by location type (mailbox versus site)
As the API is now natively working with the modern experience for eDiscovery you can optionally include a request body to pass the statisticOptions parameter in the POST API call.
With the changes to how Advanced Indexing works within the new UX and the additional reporting categories available, you can use the statisticsOptions parameter to trigger the generate statistic job with the additional options within the modern experience for the modern UX. The values you can include are detailed in the table below.
Property |
Option from Portal |
includeRefiners |
Include categories: Refine your view to include people, sensitive information types, item types, and errors. |
includeQueryStats |
Include query keywords report: Assess keyword relevance for different parts of your search query. |
includeUnindexedStats |
Include partially indexed items: We'll provide details about items that weren't fully indexed. These partially indexed items might be unsearchable or partially searchable |
advancedIndexing |
Perform advanced indexing on partially indexed items: We'll try to reindex a sample of partially indexed items to determine whether they match your query. After running the query, check the Statistics page to review information about partially indexed items.
Note: Can only be used if includeUnindexedStats is also included. |
locationsWithoutHits |
Exclude partially indexed items in locations without search hits: Ignore partially indexed items in locations with no matches to the search query. Checking this setting will only return partially indexed items in locations where there is already at least one hit.
Note: Can only be used if includeUnindexedStats is also included. |
In eDiscovery Premium (Classic) the advanced indexing took place when a custodian or non-custodial data location was added to the Data Sources tab. This means that when you triggered the estimate statistics call on the search it would include results from both the native Exchange and SharePoint index as well as the Advanced Index.
In the modern experience for eDiscovery, the advanced indexing runs as part of the job. However, this must be selected as an option on the job. Note that not all searches will benefit from advanced indexing, one example would be a simple date range search on a mailbox or SPO site as this will still have hits on the partially indexed items (even partial indexed email and SPO file items have date metadata in the native indexes).
The following example using PowerShell and the Microsoft Graph PowerShell module and passes the new StatisticsOptions parameter to the POST call and selects all available options.
# Generate estimates for the newly created search
$statParams = @{
statisticsOptions = "includeRefiners,includeQueryStats,includeUnindexedStats,advancedIndexing,locationsWithoutHits"
}
$params = $statParams | ConvertTo-Json -Depth 10
$uri = "https://graph.microsoft.com/v1.0/security/cases/ediscoveryCases/$caseID/searches/$searchID/estimateStatistics"
Invoke-MgGraphRequest -Method Post -Uri $uri -Body $params
Write-Host "Estimate statistics generation triggered for search ID: $searchID"
Once run, it will create a generated statistic job with the additional options selected.
Direct Export - Report
ediscoverySearch: exportReport
This API enables you to generate an item report directly form a search without taking the data into a review set or exporting the items that match the search.
With the APIs now natively working with the modern experience for eDiscovery, new parameters have been added to the request body as well as new values available for existing parameters.
The new parameters are as follows:
- cloudAttachmentVersion: The versions of cloud attachments to include in messages ( e.g. latest, latest 10, latest 100 or All). This controls how many versions of a file that is collected when a cloud attachment is contained within a email, teams or viva engage messages. If version shared is configured this is also always returned.
- documentVersion: The versions of files in SharePoint to include (e.g. latest, latest 10, latest 100 or All). This controls how many versions of a file that is collected when targeting a SharePoint or OneDrive site directly in the search.
These new parameters reflect the changes made in the modern experience for eDiscovery that provides more granular control for eDiscovery managers to apply different collection options based on where the SPO item was collected from (e.g. directly from a SPO site vs a cloud attachment link included in an email).
Within eDiscovery Premium (Classic) the All Document Versions option applied to both SharePoint and OneDrive files collected directly from SharePoint and any cloud attachments contained within email, teams and viva engage messages.
Historically for this API, within the additionalOptions parameter you could include the allDocumentVersions value to trigger the collection of all versions of any file stored in SharePoint and OneDrive.
With the APIs now natively working with the modern experience for eDiscovery, the allDocumentVersions value can still be included in the additionalOptions parameter but it will only apply to files collected directly from a SharePoint or OneDrive site. It will not influence any cloud attachments included in email, teams and viva engage messages.
To collect additional versions of cloud attachments use the cloudAttachmentVersion parameter to control the number of versions that are included. Also consider moving from using the allDocumentVersions value in the additionalOptions parameter and switch to using the new documentVersion parameter.
As described earlier, to benefit from advanced indexing in the modern experience for eDiscovery, you must trigger advanced indexing as part of the direct export job. Within the portal to include partially indexed items and run advanced indexing you would make the following selections.
To achieve this via the API call we need to ensure we include the following parameters and values into the request body of the API call.
Parameter |
Value |
Option from the portal |
additionalOptions |
advancedIndexing |
Perform advanced indexing on partially indexed items |
exportCriteria |
searchHits, partiallyIndexed |
Indexed items that match your search query and partially indexed items |
exportLocation |
responsiveLocations, nonresponsiveLocations |
Exclude partially indexed items in locations without search hits. |
Finally, in the new modern experience for eDiscovery more granular control has been introduced to enable organisations to independently choose to convert Teams, Viva Engage and Copilot interactions into HTML transcripts and the ability to collect up to 12 hours of related conversations when a message matches a search. This is reflected in the job settings by the following options:
- Organize conversations into HTML transcripts
- Include Teams and Viva Engage conversations
In the classic experience this was a single option titled Teams and Yammer Conversations that did both actions and was controlled by including the teamsAndYammerConversations value in the additionalOptions parameter.
With the APIs now natively working with the modern experience for eDiscovery, the teamsAndYammerConversations value can still be included in the additionalOptions parameter but it will only trigger the collection of up to 12 hours of related conversations when a message matches a search without converting the items into HTML transcripts. To do this we need to include the new value of htmlTranscripts in the additionalOptions parameter.
As an example, lets look at the following direct export report job from the portal and use the Microsoft Graph PowerShell module to call the exportReport API call with the updated request body.
$exportName = "New UX - Direct Export Report"
$exportParams = @{
displayName = $exportName
description = "Direct export report from the search"
additionalOptions = "teamsAndYammerConversations,cloudAttachments,htmlTranscripts,advancedIndexing"
exportCriteria = "searchHits,partiallyIndexed"
documentVersion = "recent10"
cloudAttachmentVersion = "recent10"
exportLocation = "responsiveLocations"
}
$params = $exportParams | ConvertTo-Json -Depth 10
$uri = https://graph.microsoft.com/v1.0/security/cases/ediscoveryCases/$caseID/searches/$searchID/exportReport"
$exportResponse = Invoke-MgGraphRequest -Method Post -Uri $uri -Body $params
Direct Export - Results
ediscoverySearch: exportResult - Microsoft Graph v1.0 | Microsoft Learn
This API call enables you to export the items from a search without taking the data into a review set. All the information from the above section on the changes to the exportReport API also applies to this API call.
However with this API call we will actually be exporting the items from the search and not just the report. As such we need to pass in the request body information on how we want the export package to look.
Previously with direct export for eDiscovery Premium (Classic) you had a three options in the UX and in the API to define the export format.
Option |
Exchange Export Structure |
SharePoint / OneDrive Export Structure |
Individual PST files for each mailbox |
PST created for each mailbox.
The structure of each PST is reflective of the folders within the mailbox with emails stored based on their original location in the mailbox.
Emails named based on their subject. |
Folder for each mailbox site.
Within each folder, the structure is reflective of the SharePoint/OneDrive site with documents stored based on their original location in the site.
Documents are named based on their document name. |
Individual .msg files for each message |
Folder created for each mailbox.
Within each folder the file structure within is reflective of the folders within the mailbox with emails stored as .msg files based on their original location in the mailbox.
Emails named based on their subject. |
As above. |
Individual .eml files for each message |
Folder created for each mailbox.
Within each folder the file structure within is reflective of the folder within the mailbox with emails stored as .eml files based on their original location in the mailbox.
Emails named based on their subject |
As above. |
Historically with this API, the exportFormat parameter was used to control the desired export format. Three values could be used and they were pst, msg and eml. This parameter is still relevant but only controls how email items will be saved, either in a PST file, as individual .msg files or as individual .eml files.
Note: The eml export format option is depreciated in the new UX. Going forward you should use either pst or msg.
With the APIs now natively working with the modern experience for eDiscovery; we need to account for the additional flexibility customers have to control the structure of their export package. An example of the options available in the direct export job can be seen below.
More information on the export package options and what they control can be found in the following link.
https://learn.microsoft.com/en-gb/purview/edisc-search-export#export-package-options
To support this, new values have been added to the additionalOptions parameter for this API call, these must be included in the request body otherwise the export structure will be as follows.
exportFormat value |
Exchange Export Structure |
SharePoint / OneDrive Export Structure |
pst |
PST files created that containing data from multiple mailboxes.
All emails contained within a single folder within the PST.
Emails named a based on an assigned unique identifier (GUID) |
One folder for all documents.
All documents contained within a single folder.
Documents are named based on an assigned unique identifier (GUID) |
msg |
Folder created containing data from all mailboxes.
All emails contained within a single folder stored as .msg files.
Emails named a based on an assigned unique identifier (GUID) |
As above. |
The new values added to the additionalOptions parameters are as follows. They control the export package structure for both Exchange and SharePoint/OneDrive items.
Property |
Option from Portal |
includeFolderAndPath |
Organize data from different locations into separate folders or PSTs |
splitSource |
Include folder and path of the source |
condensePaths |
Condense paths to fit within 259 characters limit |
friendlyName |
Give each item a friendly name |
Organizations are free to mix and match which export options they include in the request body to meet their own organizational requirements.
To receive a similar output structure when previously using the pst or msg values in the exportFormat parameter I would include all of the above values in the additionalOptions parameter.
For example, to generate a direct export where the email items are stored in separate PSTs per mailbox, the structure of the PST files reflects the mailbox and each items is named as per the subject of the email; I would use the Microsoft Graph PowerShell module to call the exportResults API call with the updated request body.
$exportName = "New UX - DirectExportJob - PST"
$exportParams = @{
displayName = $exportName
description = "Direct export of items from the search"
additionalOptions = "teamsAndYammerConversations,cloudAttachments,htmlTranscripts,advancedIndexing,includeFolderAndPath,splitSource,condensePaths,friendlyName"
exportCriteria = "searchHits,partiallyIndexed"
documentVersion = "recent10"
cloudAttachmentVersion = "recent10"
exportLocation = "responsiveLocations"
exportFormat = "pst"
}
$params = $exportParams | ConvertTo-Json -Depth 10
$uri = “https://graph.microsoft.com/v1.0/security/cases/ediscoveryCases/$caseID/searches/$searchID/exportResult"
$exportResponse = Invoke-MgGraphRequest -Method Post -Uri $uri -Body $params
If I want to export the email items as individual .msg files instead of storing them in PST files; I would use the Microsoft Graph PowerShell module to call the exportResults API call with the updated request body.
$exportName = "New UX - DirectExportJob - MSG"
$exportParams = @{
displayName = $exportName
description = "Direct export of items from the search"
additionalOptions = "teamsAndYammerConversations,cloudAttachments,htmlTranscripts,advancedIndexing,includeFolderAndPath,splitSource,condensePaths,friendlyName"
exportCriteria = "searchHits,partiallyIndexed"
documentVersion = "recent10"
cloudAttachmentVersion = "recent10"
exportLocation = "responsiveLocations"
exportFormat = "msg"
}
$params = $exportParams | ConvertTo-Json -Depth 10
$uri = " https://graph.microsoft.com/v1.0/security/cases/ediscoveryCases/$caseID/searches/$searchID/exportResult"
Add to Review Set
ediscoveryReviewSet: addToReviewSet
This API call enables you to commit the items that match the search to a Review Set within an eDiscovery case. This enables you to review, tag, redact and filter the items that match the search without exporting the data from the M365 service boundary.
Historically with this API call it was more limited compared to triggering the job via the eDiscovery Premium (Classic) UI. With the APIs now natively working with the modern experience for eDiscovery organizations can make use of the enhancements made within the modern UX and have greater flexibility in selecting the options that are relevant for your requirements.
There is a lot of overlap with previous sections, specifically the “Direct Export – Report” section on what updates are required to benefit from updated API. They are as follows:
- Controlling the number of versions of SPO and OneDrive documents added to the review set via the new cloudAttachmentVersion and documentVersion parameters
- Enabling organizations to trigger the advanced indexing of partial indexed items during the add to review set job via new values added to existing parameters
However there are some nuances to the parameter names and the values for this specific API call compared to the exportReport API call.
For example, with this API call we use the additionalDataOptions parameter opposed to the additionalOptions parameter.
As with the exportReport and exportResult APIs, there are new parameters to control the number of versions of SPO and OneDrive documents added to the review set are as follows:
- cloudAttachmentVersion: The versions of cloud attachments to include in messages ( e.g. latest, latest 10, latest 100 or All). This controls how many versions of a file that is collected when a cloud attachment is contained within a email, teams or viva engage messages. If version shared is configured this is also always returned.
- documentVersion: The versions of files in SharePoint to include (e.g. latest, latest 10, latest 100 or All). This controls how many versions of a file that is collected when targeting a SharePoint or OneDrive site directly in the search.
Historically for this API call, within the additionalDataOptions parameter you could include the allVersions value to trigger the collection of all versions of any file stored in SharePoint and OneDrive.
With the APIs now natively working with the modern experience for eDiscovery, the allVersions value can still be included in the additionalDataOptions parameter but it will only apply to files collected directly from a SharePoint or OneDrive site. It will not influence any cloud attachments included in email, teams and viva engage messages.
To collect additional versions of cloud attachments use the cloudAttachmentVersion parameter to control the number of versions that are included. Also consider moving from using the allDocumentVersions value in the additionalDataOptions parameter and switch to using the new documentVersion parameter.
To benefit from advanced indexing in the modern experience for eDiscovery, you must trigger advanced indexing as part of the add to review set job. Within the portal to include partially indexed items and run advanced indexing you would make the following selections.
To achieve this via the API call we need to ensure we include the following parameters and values into the request body of the API call.
Parameter |
Value |
Option from the portal |
additionalDataOptions |
advancedIndexing |
Perform advanced indexing on partially indexed items |
itemsToInclude |
searchHits, partiallyIndexed |
Indexed items that match your search query and partially indexed items |
additionalDataOptions |
locationsWithoutHits |
Exclude partially indexed items in locations without search hits. |
Historically the API call didn’t support the add to review set job options to convert Teams, Viva Engage and Copilot interactions into HTML transcripts and collect up to 12 hours of related conversations when a message matches a search.
With the APIs now natively working with the modern experience for eDiscovery this is now possible by adding support for the htmlTranscripts and messageConversationExpansion values to the addtionalDataOptions parameter.
As an example, let’s look at the following add to review set job from the portal and use the Microsoft Graph PowerShell module to invoke the addToReviewSet API call with the updated request body.
$commitParams = @{
search = @{ id = $searchID }
additionalDataOptions = "linkedFiles,advancedIndexing,htmlTranscripts,messageConversationExpansion,locationsWithoutHits"
cloudAttachmentVersion = "latest"
documentVersion = "latest"
itemsToInclude = "searchHits,partiallyIndexed"
}
$params = $commitParams | ConvertTo-Json -Depth 10
$uri = "https://graph.microsoft.com/v1.0/security/cases/ediscoveryCases/$caseID/reviewSets/$reviewSetID/addToReviewSet"
Invoke-MgGraphRequest -Method Post -Uri $uri -Body $params
Export from Review Set
This API call enables you to export items from a Review Set within an eDiscovery case.
Historically with this API, the exportStructure parameter was used to control the desired export format. Two values could be used and they were directory and pst. This parameter has had been updated to include a new value of msg.
Note: The directory value is depreciated in the new UX but remains available in v1.0 of the API call for backwards compatibility. Going forward you should use msg alongside the new exportOptions values.
The exportStructure parameter will only control how email items are saved, either within PST files or as individual .msg files.
With the APIs now natively working with the modern experience for eDiscovery; we need to account for the additional flexibility customers have to control the structure of their export package. An example of the options available in the direct export job can be seen below.
As with the exportResults API call for direct export, new values have been added to the exportOptions parameter for this API call.
The new values added to the exportOptions parameters are as follows. They control the export package structure for both Exchange and SharePoint/OneDrive items.
Property |
Option from Portal |
includeFolderAndPath |
Organize data from different locations into separate folders or PSTs |
splitSource |
Include folder and path of the source |
condensePaths |
Condense paths to fit within 259 characters limit |
friendlyName |
Give each item a friendly name |
Organizations are free to mix and match which export options they include in the request body to meet their own organizational requirements.
To receive an equivalent output structure when previously using the pst value in the exportStructure parameter I would include all of the above values in the exportOptions parameter within the request body. An example using the Microsoft Graph PowerShell module can be found below.
$exportName = "ReviewSetExport - PST"
$exportParams = @{
outputName = $exportName
description = "Exporting all items from the review set"
exportOptions = "originalFiles,includeFolderAndPath,splitSource,condensePaths,friendlyName"
exportStructure = "pst"
}
$params = $exportParams | ConvertTo-Json -Depth 10
$uri = "https://graph.microsoft.com/v1.0/security/cases/ediscoveryCases/$caseID/reviewSets/$reviewSetID/export"
Invoke-MgGraphRequest -Method Post -Uri $uri -Body $params
To receive an equivalent output structure when previously using the directory value in the exportStructure parameter I would instead use the msg value within the request body. As the condensed directory structure format export all items into a single folder, all named based on uniquely assigned identifier I do not need to include the new values added to the exportOptions parameter. An example using the Microsoft Graph PowerShell module can be found below. An example using the Microsoft Graph PowerShell module can be found below.
$exportName = "ReviewSetExport - MSG"
$exportParams = @{
outputName = $exportName
description = "Exporting all items from the review set"
exportOptions = "originalFiles"
exportStructure = "msg"
}
$params = $exportParams | ConvertTo-Json -Depth 10
$uri = "https://graph.microsoft.com/v1.0/security/cases/ediscoveryCases/$caseID/reviewSets/$reviewSetID/export"
Invoke-MgGraphRequest -Method Post -Uri $uri -Body $params
Continuing to use the directory value in exportStructure will produce the same output as if msg was used.
Wrap Up
Thank you for your time reading through this post. Hopefully you are now equipped with the information needed to make the most of the new modern experience for eDiscovery when making your Graph API calls.