Using Microsoft Graph Search API as current user

Microsoft Graph API allows you to work with all the Microsoft 365 content – including search through Exchange e-mail messages, Yammer (Viva Engage) and Teams chat messages and surely OneDrive and SharePoint content (please refer to the MS’s original doc). After we got a registered Azure app configured correctly, including Authentication and API permissions provided (more on this) – we should be ready to authenticate and call Graph API on behalf of a user.

Let me focus on searching in SharePoint Online and OD here but you can use the same technique to search through other Microsoft 365 services. I will use PowerShell but same ideas should work for other platforms/languages – Python, C#, node.js etc.

Let us authenticate first. We’d need a MSAL.PS module for that.

# Ensure we have MSAL.PS module installed
Get-Module MSAL.PS -ListAvailable | ft name, Version, Path 
# Install-Module MSAL.PS -Force -Scope CurrentUser -AcceptLicense
Import-Module MSAL.PS

# Authenticate to Microsoft Interactively 
$clientid = 'd82858e0-ed99-424f-a00f-cef64125e49c' # your client id
$TenantId = '7ddc7314-9f01-45d5-b012-71665bb1c544' # your tenant id
$token = Get-MsalToken -TenantId $TenantId -ClientId $clientid -Interactive
$headers = @{Authorization = "Bearer $($token.AccessToken)" }

Below is how I search Microsoft 365 content programmatically from PowerShell using MS Graph API being authenticates as user:

# Search
# MS Graph Search API url (beta or v1.0):
$apiUrl = "https://graph.microsoft.com/beta/search/query"

# specify where to search - entity types
$entityTypes = "['driveItem','listItem','list','drive','site']"
$entityTypes = "['driveItem','listItem']"

# query
$query = "test*"

# build a simple request body
$body = @"
{ 
  "requests": [
    {
      "entityTypes": $entityTypes,
      "query": {
        "queryString": "$query"
      }
    }
  ]
}
"@

# call Graph API:
$res = Invoke-RestMethod -Headers $Headers -Uri $apiUrl -Body $Body -Method Post -ContentType 'application/json'

# explore returned object
$res.value[0].searchTerms
$res.value[0].hitsContainers[0].hits
$res.value[0].hitsContainers[0].hits.Count
$res.value[0].hitsContainers[0].moreResultsAvailable

I used “beta” search API to research or make demos, but in production code youd stick with “v1.0”.

You can scope search down using entity types – ‘driveItem’,’listItem’,’list’,’drive’,’site’. “driveitem” here represents document library.

In query you can use KQL.

Always check if more results available with “$res.value[0].hitsContainers[0].moreResultsAvailable”. If there are more results and you need them – consider looping using paging technique.

References

4 thoughts on “Using Microsoft Graph Search API as current user

  1. Pingback: Search Microsoft 365 content programmatically ⋆ Microsoft 365 engineering

  2. Michael Kelly

    I keep getting a bad request and am using your code verbatim. Any suggestions? I have all the correct app permissions and other details needed are correct as well (tenant, client, secret).

    $apiUrl = “https://graph.microsoft.com/beta/search/query”

    $entityTypes = “[‘driveItem’,’listItem’,’list’,’drive’,’site’]”
    $query = “test*”

    $body = @”
    {
    “requests”: [
    {
    “entityTypes”: $entityTypes,
    “query”: {
    “queryString”: “$query”
    },
    “region”: “NAM”
    }
    ]
    }
    “@

    $res = Invoke-RestMethod -Headers $Headers -Uri $apiUrl -Body $body -Method Post -ContentType ‘application/json’

    Results in:
    Invoke-RestMethod : The remote server returned an error: (400) Bad Request.

    Reply
  3. Michael Kelly

    Using the same authentication method and header, I’m able to list out all of the sites with the following code:

    $URI = “https://graph.microsoft.com/v1.0/sites”
    $WebRequest = Invoke-WebRequest -Headers $headers -Uri $URI
    $Result = ($WebRequest.Content | ConvertFrom-Json).Value

    write-host $result

    That said, I don’t believe its the headers, but perhaps the body?

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *