Share via

eDiscovery Graph API: app-only POST /searches succeeds but estimateStatistics + addToReviewSet return 404 NotFound on the new search

Libaan Hassan 0 Reputation points
2026-04-18T17:34:50.8133333+00:00

App-only token with eDiscovery.ReadWrite.All on a Premium-licensed case. POST /security/cases/ediscoveryCases/{caseId}/searches returns 201 + a search id; GET /searches/{id} returns 200; but POST .../searches/{id}/estimateStatistics and POST .../reviewSets/{rsId}/addToReviewSet both return 404 NotFound. Same calls work fine on searches created via the Purview portal UI.

Microsoft Security | Microsoft Purview
0 comments No comments

2 answers

Sort by: Most helpful
  1. SAI JAGADEESH KUDIPUDI 2,625 Reputation points Microsoft External Staff Moderator
    2026-04-20T06:29:12.8833333+00:00

    Hi Libaan Hassan,
    Thank you for sharing the detailed behavior you are seeing with the eDiscovery Graph APIs. I understand this can be confusing, especially since the search creation itself succeeds.

    Based on how Microsoft Purview eDiscovery is designed today, this behavior is expected.

    When a search is created programmatically using the Microsoft Graph API (app‑only access), the search object is created and can be retrieved successfully. However, advanced Premium actions such as Estimate statistics and Add to review set are only supported for searches that are fully initialized through the Purview portal UI.

    Searches created in the Purview portal go through additional internal processing that prepares them for downstream Premium operations. Searches created via Graph API may exist and return 200 OK on GET requests, but they are not yet eligible for estimate or review‑set operations, which is why those calls return 404 NotFound. This is a known product behavior and is not related to permissions, licensing, or token type, provided the case is eDiscovery (Premium) and the correct permissions are granted.

    • Create the eDiscovery search in the Microsoft Purview portal UI
    • Use the Microsoft Graph API for post‑creation automation, such as:
      • Running estimateStatistics
        • Adding results to a review set
          • Exporting or reporting

    This approach aligns with Microsoft’s supported patterns for eDiscovery automation and avoids the 404 errors you are encountering.

    At this time, creating searches in the Purview portal and then using Microsoft Graph for follow‑up operations is the recommended and supported solution. This should allow estimate and review‑set operations to work as expected.

    Microsoft references Links:

    Hope this helps. If you have any follow-up questions, please let me know. I would be happy to help.

    Please do not forget to "Accept Answer" and "up-vote" wherever the information provided helps you, as this can be beneficial to other community members.

    2 people found this answer helpful.

  2. Q&A Assist
    2026-04-18T17:35:04.5766667+00:00
    AI generated content. This question contains an answer created with AI from Q&A Assist. Learn more

    POST /security/cases/ediscoveryCases/{caseId}/searches/{searchId}/estimateStatistics only works for eDiscovery searches in the microsoft.graph.security namespace and requires that the case has Premium features enabled and that the app has the correct permissions. The same is true conceptually for adding content to a review set.

    From the context:

    • The ediscoverySearch resource and its estimateStatistics action are defined under microsoft.graph.security and are only supported for eDiscovery (Premium) cases.
    • The HTTP pattern for estimate statistics is:
        POST /security/cases/ediscoveryCases/{ediscoveryCaseId}/searches/{ediscoverySearchId}/estimateStatistics
      
      with a JSON body containing statisticsOptions if specific statistics are required.
    • When successful, estimateStatistics returns 202 Accepted and a Location header pointing to an estimateStatisticsOperation resource. A 404 NotFound indicates that the resource path does not resolve to a valid search in the security namespace.
    • The PowerShell cmdlet Invoke-MgEstimateSecurityCaseEdiscoveryCaseSearchStatistics wraps this same API and demonstrates the required parameters and permissions (eDiscovery.Read.All or eDiscovery.ReadWrite.All, app-only supported).
    • The reviewSet: addToReviewSet example in the context is from the older, deprecated microsoft.graph.ediscovery subnamespace (/compliance/ediscovery/...), which is explicitly called out as deprecated in favor of the microsoft.graph.security eDiscovery APIs.

    Given that:

    1. POST /security/cases/ediscoveryCases/{caseId}/searches and GET /searches/{id} succeed for the app-only token, the app permissions and case premium status are correct.
    2. A 404 NotFound on POST .../searches/{id}/estimateStatistics and POST .../reviewSets/{rsId}/addToReviewSet while the same operations work for searches created in the Purview UI strongly indicates a mismatch in API surface or resource identity rather than permissions:
      • estimateStatistics must be called on a microsoft.graph.security.ediscoverySearch under /security/cases/ediscoveryCases/....
      • addToReviewSet in the context is shown only for the deprecated /compliance/ediscovery/... path in the microsoft.graph.ediscovery namespace.

    Actionable checks and adjustments:

    1. Ensure the estimateStatistics call is using the exact v1.0 security path and the same IDs returned by the create call:
         POST https://graph.microsoft.com/v1.0/security/cases/ediscoveryCases/{ediscoveryCaseId}/searches/{ediscoverySearchId}/estimateStatistics
         Content-Type: application/json
         
         {
           "statisticsOptions": "includeRefiners, includeQueryStats, includeUnindexedStats, advancedIndexing, locationsWithoutHits"
         }
      
      If the search was created under /security/cases/ediscoveryCases, calling estimateStatistics under any other namespace or base path (for example, /compliance/ediscovery/...) will return 404.
    2. Use the PowerShell cmdlet once against the same case/search to validate the path and IDs:
         Import-Module Microsoft.Graph.Security
         
         $params = @{ statisticsOptions = "includeRefiners, includeQueryStats, includeUnindexedStats, advancedIndexing, locationsWithoutHits" }
         
         Invoke-MgEstimateSecurityCaseEdiscoveryCaseSearchStatistics `
           -EdiscoveryCaseId  $ediscoveryCaseId `
           -EdiscoverySearchId $ediscoverySearchId `
           -BodyParameter $params
      
      If this succeeds but the custom call does not, the issue is with the HTTP path or version being used in the custom code.
    3. For adding to a review set, avoid the deprecated /compliance/ediscovery/.../addToReviewSet path shown in the microsoft.graph.ediscovery example. Use the corresponding operation in the microsoft.graph.security eDiscovery API instead. Mixing a search created under microsoft.graph.security with a review set operation under the deprecated microsoft.graph.ediscovery namespace will result in 404 because they are different resource trees.
    4. Confirm that all calls (create search, estimate statistics, add to review set) are made consistently in the same API version (v1.0) and namespace (/security/cases/ediscoveryCases/...) and that no beta or /compliance/ediscovery endpoints are used for the programmatically created search.

    Once all operations are aligned to the microsoft.graph.security namespace and the same case/search IDs, the 404 behavior should match what is observed for searches created in the Purview portal UI.


    References:

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.