Assuming we have a registered Azure app configured correctly, including Authentication and API permissions provided – we should be ready to authenticate and call Graph API on behalf of a 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 original doc).
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
Pingback: Search Microsoft 365 content programmatically ⋆ Microsoft 365 engineering
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.
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?
Yes, please refer to https://github.com/VladilenK/m365-PowerShell/tree/main/KBA/Search
and do not reformat the body part… also ensure your region code…