If a script, SIEM connector, Power Automate flow or Power BI report runs KQL against Defender through api.security.microsoft.com, it has a deadline. Microsoft is retiring the Defender for Endpoint and Defender XDR advanced hunting APIs, and there is no automatic migration: every caller has to be moved to the Microsoft Graph security API by hand. In this post I'll cover what Microsoft has announced, how to find what still calls the old endpoints, the exact changes a migration needs, and how to prove each integration works before the switch-off.
Status (November 2026): Microsoft announced the retirement in Message center post MC1220762 (published 22 January 2026, reminder update 26 October 2026). Retirement started on 6 February 2026 according to the post; the full retirement is 1 February 2027, after which both APIs stop working. Microsoft asks organizations to migrate by 31 January 2027. This is a planned retirement, not a bug, and it affects anyone using the old APIs for automation, integrations or custom workflows. Re-check the post and the Learn pages before January, because dates can change.
What is changing#
Microsoft Graph's advanced hunting API, runHuntingQuery, replaces these older endpoints:
| Old API | Microsoft Graph | |
|---|---|---|
| Endpoint | https://api.securitycenter.microsoft.com/api/advancedqueries/run (Defender for Endpoint, also under api.security.microsoft.com and its regional hosts)https://api.security.microsoft.com/api/advancedhunting/run (Defender XDR) | https://graph.microsoft.com/v1.0/security/runHuntingQuery |
| Permissions | AdvancedQuery.Read / AdvancedQuery.Read.All on WindowsDefenderATP; AdvancedHunting.Read / AdvancedHunting.Read.All on Microsoft Threat Protection | ThreatHunting.Read.All (delegated and application) on Microsoft Graph |
| Request body | {"Query": "..."} | {"Query": "...", "Timespan": "P30D"} (Timespan optional, ISO 8601) |
| Response | Stats, Schema, Results | schema and results (lowercase) |
Your KQL itself carries over: the tables are the same advanced hunting schema you use in the Microsoft Defender portal.
Who is affected#
Anyone with an app registration, managed identity, script or connector that calls the old endpoints. Typical examples are scheduled PowerShell reports, SOAR playbooks, Logic Apps or Power Automate flows that use the Advanced Hunting action of the Microsoft Defender ATP connector, Power BI reports built on the old API, and third-party tools. Microsoft says it sent MC1220762 to tenants whose usage it detected, so if you received it, assume something still calls the old API.
What breaks if you do nothing#
After 1 February 2027 the old endpoints no longer return data, so scheduled hunts, enrichment lookups in playbooks and dashboards built on them simply fail. In a SOC that often goes unnoticed until someone asks why a daily report is empty.
What to do now#
1. Find the callers#
Start from the permissions. This Graph PowerShell snippet lists every service principal that holds an application permission on the two old API resources, plus delegated grants:
Connect-MgGraph -Scopes 'Application.Read.All','Directory.Read.All'
foreach ($name in 'WindowsDefenderATP','Microsoft Threat Protection') {
$res = Get-MgServicePrincipal -Filter "displayName eq '$name'"
if (-not $res) { continue }
Get-MgServicePrincipalAppRoleAssignedTo -ServicePrincipalId $res.Id -All | ForEach-Object {
$role = ($res.AppRoles | Where-Object Id -eq $_.AppRoleId).Value
if ($role -match 'AdvancedQuery|AdvancedHunting') { '{0} -> {1} ({2})' -f $_.PrincipalDisplayName, $role, $name }
}
Get-MgOauth2PermissionGrant -Filter "resourceId eq '$($res.Id)'" -All |
Where-Object Scope -match 'AdvancedQuery|AdvancedHunting' |
ForEach-Object { 'Delegated grant: client {0} scope {1}' -f $_.ClientId, $_.Scope }
}Then check the other half of the picture: the Service principal sign-ins view of the Microsoft Entra sign-in logs, filtered on those two resources, shows which apps actually requested tokens recently. An app with the permission but no sign-ins is a cleanup candidate, not a migration task. Also search your code repositories and automation accounts for advancedqueries/run and advancedhunting/run.
2. Grant the new permission#
For each app you keep, add the Microsoft Graph application permission ThreatHunting.Read.All (or the delegated one for user-context tools) and grant admin consent. Leave the old permissions in place until the new code is proven, then remove them.
3. Change the call#
A minimal PowerShell example with Graph:
Connect-MgGraph -Scopes 'ThreatHunting.Read.All'
$body = @{
Query = 'DeviceProcessEvents | where InitiatingProcessFileName =~ "powershell.exe" | project Timestamp, DeviceName, ProcessCommandLine | take 10'
Timespan = 'P7D'
} | ConvertTo-Json
$r = Invoke-MgGraphRequest -Method POST -Uri 'https://graph.microsoft.com/v1.0/security/runHuntingQuery' -Body $body -ContentType 'application/json'
$r.results | ForEach-Object { [pscustomobject]$_ }In existing code the changes are usually: token audience (https://graph.microsoft.com instead of the Defender resource), URL, and property names in the response parsing (results instead of Results). Watch the last one: code that reads Results from a case-sensitive parser can quietly get nothing back instead of raising an error.
4. Rebuild Power Platform and Power BI integrations#
Microsoft notes that Microsoft Graph has no built-in Advanced Hunting action like the one in the Defender ATP connector, so flows need a custom connector that calls runHuntingQuery. Power BI reports need their query updated to the Graph endpoint and parameters.
5. Plan for Graph's limits#
Microsoft documents limits for runHuntingQuery: up to 100,000 rows and 50 MB per result, a three-minute timeout per request, a per-tenant CPU allocation with HTTP 429 when it's exhausted, and at least 45 calls per minute per tenant. Add retry with back-off on 429, and keep queries narrow with project and time filters.
How to verify#
- Run the same KQL in the Defender portal's advanced hunting page and through the migrated integration; row counts for the same time range should match.
- The migrated app's service principal sign-ins now show Microsoft Graph as the resource, and no longer the old Defender resources.
- The step 1 script still lists the app until you remove the old permission; afterwards, the integration still works, which proves it no longer depends on it.
- Scheduled jobs have produced output on at least one normal run since the change, not just in a manual test.
Timeline#
| Date | What happens |
|---|---|
| 22 January 2026 | Retirement announced (MC1220762) |
| 6 February 2026 | Retirement starts, according to MC1220762 |
| 26 October 2026 | Reminder update to MC1220762 |
| 31 January 2027 | Microsoft's migrate-by date |
| 1 February 2027 | Old MDE and XDR advanced hunting APIs stop working |
While you're in this code, check for the first-generation Graph legacy alerts API too: Microsoft's Graph security API overview lists it as deprecated with a retirement date of 15 October 2026, replaced by the alerts and incidents API. For query ideas to test with, see advanced hunting KQL queries for Intune admins.
References#
- Use the Microsoft Graph security API (Migrate from the older APIs)
- security: runHuntingQuery
- Advanced hunting API (Microsoft Defender for Endpoint)

