{"id":62084,"date":"2025-04-08T06:00:00","date_gmt":"2025-04-08T10:00:00","guid":{"rendered":"https:\/\/practical365.com\/?p=62084"},"modified":"2025-04-10T09:22:38","modified_gmt":"2025-04-10T13:22:38","slug":"auditlog-query-api-deeper-look","status":"publish","type":"post","link":"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/","title":{"rendered":"Practical Graph: Running Audit Log Searches with the AuditLog Query API"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 eztoc-toggle-hide-by-default' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/#Taking_a_Deeper_Look_into_the_AuditLog_Query_API\" >Taking a Deeper Look into the AuditLog Query API<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/#Advantages_of_Using_the_AuditLog_Query_API\" >Advantages of Using the AuditLog Query API<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/#Running_an_Unfiltered_Audit_Log_Search\" >Running an Unfiltered Audit Log Search<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/#Running_a_Filtered_Audit_Log_Search\" >Running a Filtered Audit Log Search<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/#Monitoring_Audit_Job_Progress\" >Monitoring Audit Job Progress<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/#Fetching_Audit_Job_Results\" >Fetching Audit Job Results<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/#Viewing_Audit_Job_Details\" >Viewing Audit Job Details<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/#An_Option_Worth_Considering\" >An Option Worth Considering<\/a><\/li><\/ul><\/nav><\/div>\n<div id=\"bsf_rt_marker\"><\/div>\n<h2 class=\"wp-block-heading\" id=\"h-taking-a-deeper-look-into-the-auditlog-query-api\"><span class=\"ez-toc-section\" id=\"Taking_a_Deeper_Look_into_the_AuditLog_Query_API\"><\/span>Taking a Deeper Look into the AuditLog Query API<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p><em>Update (10 April, 2025): In message center notification MC1052169, Microsoft announced that they have moved the AuditLogQuery API back from production (V1.0) to beta status to address some problems. The API continues to work via the beta endpoint. Microsoft says that they will republish the API to V1.0 after they have fixed the problems. <\/em><\/p>\n\n\n\n<p>A year ago, Microsoft launched the <a href=\"https:\/\/practical365.com\/audit-log-query-api\/\" target=\"_blank\" rel=\"noreferrer noopener\">preview of the AuditLog Query Graph API<\/a>. The new API is a Graph implementation of the API used by the Microsoft Purview Audit solution, which switched from on-demand synchronous audit searches to asynchronous background processing several years ago. While it\u2019s more than capable of running audit log searches, the AuditLog Query API isn\u2019t quite as capable in some respects to the options available through the Purview Audit GUI. However, that doesn\u2019t stop it from deserving a deeper look.<\/p>\n\n\n\n<p>Those considering using the AuditLog Query API will probably compare it to the <em>Search-UnifiedAuditLog<\/em> cmdlet from the Exchange Online management module. Microsoft would like you to use asynchronous searches whenever possible because they believe that this approach makes better use of service resources. The decision about which route to take depends on the solution you\u2019re trying to create. In some cases, processing requirements will dictate that a fast synchronous audit log search is the best approach. In others, code can wait for an audit job to finish running before proceeding to process the job results. Processes run as Azure Automation runbooks are especially good candidates for using the AuditLog Query API.<\/p>\n\n\n\n<p>Running audit jobs with the AuditLog Query API requires consent for the <em>AuditLogsQuery.Read.All<\/em> permission. This permission allows access to all audit events. Some <a href=\"https:\/\/learn.microsoft.com\/en-us\/graph\/api\/security-auditcoreroot-post-auditlogqueries?view=graph-rest-1.0#permissions\" target=\"_blank\" rel=\"noreferrer noopener\">granular permissions <\/a>are available to restrict access to specific events, such as only for SharePoint Online. The permissions are available in both delegated and application form. To use a delegated <em>AuditLogs <\/em>permission in an interactive Microsoft Graph PowerShell SDK session, the signed-in account must be a member of the Purview Audit Manager role group.<\/p>\n\n\n\n<p><a href=\"https:\/\/office365itpros.com\/2024\/08\/14\/auditlog-query-oddities\/\" target=\"_blank\" rel=\"noreferrer noopener\">Cmdlets for the AuditLog Query API<\/a> are available in the Microsoft Graph PowerShell SDK. I use straightforward API requests here, but it\u2019s easy to convert the requests into cmdlets if you wish.<\/p>\n\n\n\n<div class=\"q-blockads-inside-content q-blockads-entity-placement\" id=\"q-blockads-2431472853\"><div id=\"q-blockads-91737658\"><p><a href=\"https:\/\/www.quest.com\/P365_On_Demand_Migration\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-62892\" src=\"https:\/\/practical365.com\/wp-content\/uploads\/2024\/09\/1901-10-20-2025-Redone-300x31.jpg\" alt=\"\" width=\"861\" height=\"89\" srcset=\"https:\/\/practical365.com\/wp-content\/uploads\/2024\/09\/1901-10-20-2025-Redone-300x31.jpg 300w, https:\/\/practical365.com\/wp-content\/uploads\/2024\/09\/1901-10-20-2025-Redone-768x80.jpg 768w, https:\/\/practical365.com\/wp-content\/uploads\/2024\/09\/1901-10-20-2025-Redone.jpg 860w\" sizes=\"auto, (max-width: 861px) 100vw, 861px\" \/><\/a><\/p>\n<\/div><\/div><h2 class=\"wp-block-heading\" id=\"h-advantages-of-using-the-auditlog-query-api\"><span class=\"ez-toc-section\" id=\"Advantages_of_Using_the_AuditLog_Query_API\"><\/span>Advantages of Using the AuditLog Query API<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Using the AuditLog Query API to run audit log searches comes with some advantages. For example, each administrator can submit up to ten audit jobs to run concurrently. One of the jobs can be unfiltered, meaning that it fetches every available audit record for the search period. The other jobs (or all ten jobs) can apply different search criteria to fetch specific sets of audit records. When the jobs finish, their results can be combined or processed separately.<\/p>\n\n\n\n<p>Results for an audit job don\u2019t have to be processed immediately because they remain available online for 30 days after the job finishes. The results can be fetched at any time until Purview removes them automatically.<\/p>\n\n\n\n<p>Another advantage is that audit log searches executed using the AuditLog Query API can return more records than the 50,000 limit for the <em>Search-UnifiedAuditLog<\/em> cmdlet. The highest number fetched by an audit job I have run is 415,406 records (Figure 1).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"601\" src=\"https:\/\/practical365.com\/wp-content\/uploads\/2025\/03\/Audit-Log-Search-Lots-of-records-1024x601.jpg\" alt=\"Downloading a large number of records returned by an AuditLog Query search\" class=\"wp-image-62085\" srcset=\"https:\/\/practical365.com\/wp-content\/uploads\/2025\/03\/Audit-Log-Search-Lots-of-records-1024x601.jpg 1024w, https:\/\/practical365.com\/wp-content\/uploads\/2025\/03\/Audit-Log-Search-Lots-of-records-300x176.jpg 300w, https:\/\/practical365.com\/wp-content\/uploads\/2025\/03\/Audit-Log-Search-Lots-of-records-768x451.jpg 768w, https:\/\/practical365.com\/wp-content\/uploads\/2025\/03\/Audit-Log-Search-Lots-of-records.jpg 1151w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Figure 1: Downloading a large number of records returned by an AuditLog Query search<\/figcaption><\/figure>\n<\/div>\n\n\n<p>The time needed by Purview to process an audit job depends on multiple factors, including the current load on the service, the complexity of the filter used by the job, and the number of records retrieved by the search. Most audit jobs should complete within ten minutes. The same jobs might take between four to forty minutes. On the other hand, I\u2019ve seen an unfiltered query that returned 65,000 records complete in just over four minutes.<\/p>\n\n\n\n<p>Everything depends on what\u2019s happening in the service when an audit job is submitted. Like any search, the more focused and precise the query, the faster the search is likely to finish.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Running_an_Unfiltered_Audit_Log_Search\"><\/span>Running an Unfiltered Audit Log Search<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The simplest kind of audit query is an unfiltered search that fetches all audit data between two dates. To submit an audit job with the AuditLog Query API, the first task is to construct the query parameters. Because we\u2019re going to run an unfiltered query, the only parameters are the start and end dates. This code creates a name for the audit job and specifies that the start time is 30 days ago, and the end time is an hour in the future:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$AuditJobName = (\"Full audit job created at {0}\" -f (Get-Date -format 'dd-MMM-yyyy HH:mm'))\n$EndDate = (Get-Date).AddHours(1)\n$StartDate = (Get-Date $EndDate).AddDays(-30)\n$AuditQueryStart = (Get-Date $StartDate -format s)\n$AuditQueryEnd = (Get-Date $EndDate -format s)\n<\/pre>\n\n\n\n<p>The query parameters are inserted into a hash table to be submitted to the audit job queue:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$AuditQueryParameters = @{}\n$AuditQueryParameters.Add(\"@odata.type\",\"#microsoft.graph.security.auditLogQuery\")\n$AuditQueryParameters.Add(\"displayName\", $AuditJobName)\n$AuditQueryParameters.Add(\"filterStartDateTime\", $AuditQueryStart)\n$AuditQueryParameters.Add(\"filterEndDateTime\", $AuditQueryEnd)\n<\/pre>\n\n\n\n<p>The next step is to submit the audit job to the queue by posting a request containing the hash table to the Queries endpoint:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$Uri = \"https:\/\/graph.microsoft.com\/beta\/security\/auditLog\/queries\"\n$AuditJob = Invoke-MgGraphRequest -Method POST -Uri $Uri -Body $AuditQueryParameters\n<\/pre>\n\n\n\n<p>If an error isn\u2019t flagged, the variable used to receive the status of the audit job contains the job details:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$AuditJob\n\nName                           Value\n----                           -----\noperationFilters               {}\nobjectIdFilters                {}\nfilterStartDateTime            07\/02\/2025 22:04:24\nserviceFilters                 {}\nid                             21a96394-20f4-4505-9f99-72f2fd960eb0\nipAddressFilters               {}\nrecordTypeFilters              {}\nkeywordFilter\ndisplayName                    Unfiltered Audit job created at 09-Mar-2025 21:04\n@odata.context                 https:\/\/graph.microsoft.com\/beta\/$metadata#security\/auditLog\/queries\/$entity\nuserPrincipalNameFilters       {}\nfilterEndDateTime              09\/03\/2025 22:04:24\nstatus                         notStarted\nadministrativeUnitIdFilters    {}\n<\/pre>\n\n\n\n<p>The problem with unfiltered searches is that they usually return many thousands of records, most of which are not relevant to the information that\u2019s needed. For this reason, it\u2019s always best to limit the period used for unfiltered searches to give administrators or investigators less information to review.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Running_a_Filtered_Audit_Log_Search\"><\/span>Running a Filtered Audit Log Search<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>A filtered audit log search uses one or more optional filters to refine the set of audit events returned by the search. Table 1 lists the audit log search filters supported by the <a href=\"https:\/\/learn.microsoft.com\/graph\/api\/security-auditcoreroot-post-auditlogqueries?view=graph-rest-1.0&amp;WT.mc_id=M365-MVP-9501\" target=\"_blank\" rel=\"noreferrer noopener\">AuditLog Query API<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>Filter name<\/td><td>Filters against<\/td><\/tr><tr><td>RecordTypeFilters<\/td><td>Search based on categories of audit log records, like ExchangeItem and microsoftPurview. Each category covers multiple operations.<\/td><\/tr><tr><td>KeywordFilter<\/td><td>Free text search against non-indexed properties of audit log records.<\/td><\/tr><tr><td>ServiceFilter<\/td><td>Search against a workload identity, like Exchange or SharePoint. Takes a single string value.<\/td><\/tr><tr><td>OperationFilters<\/td><td>A collection (array) of string values to search for common operations, like FileModified or<\/td><\/tr><tr><td>userPrincipalNameFilters<\/td><td>A collection of string values to search against the UserPrincipalName property of audit records. These values should contain the user principal names who caused auditable actions to occur.<\/td><\/tr><tr><td>objectIdFilters<\/td><td>A collection containing values to search against the ObjectId property in audit records. For SharePoint Online and OneDrive for Business, the full path name to files (supports * wildcard). For Exchange administrative logging, the name of the object modified by a cmdlet.<\/td><\/tr><tr><td>administrativeUnitIdFilters<\/td><td>A collection of Entra ID administrative unit identifiers to search against the tags in audit log records.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Table 1: Optional filters for audit log queries<\/p>\n\n\n\n<p>Filters can be combined to focus in on specific data. For example, this audit log query searches for audit events captured for three different operations performed against files in two different SharePoint Online sites by three different users.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$AuditJobName = (\"Audit job created at {0}\" -f (Get-Date -format 'dd-MMM-yyyy HH:mm'))\n$EndDate = (Get-Date).AddHours(1)\n$StartDate = (Get-Date $EndDate).AddDays(-60)\n$AuditQueryStart = (Get-Date $StartDate -format s)\n$AuditQueryEnd = (Get-Date $EndDate -format s)\n[array]$AuditOperationFilters = \"FileModified\", \"FileDeleted\", \"FileUploaded\"\n[array]$AuditobjectIdFilters = \"https:\/\/office365itpros.sharepoint.com\/sites\/productcreation\/*\", \"https:\/\/office365itpros.sharepoint.com\/sites\/Office365Adoption\/*\"\n[array]$AuditUserPrincipalNameFilters = \"Ken.Bowers@office365itpros.com\", \"Lotte.Vetler@office365itpros.com\", \"tony.redmond@office365itpros.com\"\n\n$AuditQueryParameters = @{}\n$AuditQueryParameters.Add(\"@odata.type\",\"#microsoft.graph.security.auditLogQuery\")\n$AuditQueryParameters.Add(\"displayName\", $AuditJobName)\n$AuditQueryParameters.Add(\"OperationFilters\", $AuditOperationFilters)\n$AuditQueryParameters.Add(\"filterStartDateTime\", $AuditQueryStart)\n$AuditQueryParameters.Add(\"filterEndDateTime\", $AuditQueryEnd)\n$AuditQueryParameters.Add(\"userPrincipalNameFilters\", $AuditUserPrincipalNameFilters)\n$AuditQueryParameters.Add(\"objectIdFilters\", $AuditobjectIdFilters)\n\n$Uri = \"https:\/\/graph.microsoft.com\/beta\/security\/auditLog\/queries\"\n$AuditJob = Invoke-MgGraphRequest -Method POST -Uri $Uri -Body $AuditQueryParameters\n<\/pre>\n\n\n\n<div class=\"q-blockads-content q-blockads-entity-placement\" id=\"q-blockads-1686117727\"><div id=\"q-blockads-2392702889\"><p><a href=\"https:\/\/www.quest.com\/Security_Guardian_P365\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-62893\" src=\"https:\/\/practical365.com\/wp-content\/uploads\/2024\/04\/1902-10-20-2025-Redone-300x31.jpg\" alt=\"\" width=\"861\" height=\"89\" srcset=\"https:\/\/practical365.com\/wp-content\/uploads\/2024\/04\/1902-10-20-2025-Redone-300x31.jpg 300w, https:\/\/practical365.com\/wp-content\/uploads\/2024\/04\/1902-10-20-2025-Redone-768x80.jpg 768w, https:\/\/practical365.com\/wp-content\/uploads\/2024\/04\/1902-10-20-2025-Redone.jpg 860w\" sizes=\"auto, (max-width: 861px) 100vw, 861px\" \/><\/a><\/p>\n<\/div><\/div><h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Monitoring_Audit_Job_Progress\"><\/span>Monitoring Audit Job Progress<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The status of an audit job tells you what state it is in. The initial post-submission status is \u201cnot started.\u201d When Purview begins to process the query, the job status changes to &#8220;running.&#8221; To keep an eye on its progress, we can run a loop to check the status of the job until it finally completes, indicated by its status changing from \u201crunning\u201d to \u201csucceeded\u201d:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">[int]$i = 1\n[int]$SleepSeconds = 20\n$SearchFinished = $false; [int]$SecondsElapsed = 20\nWrite-Host \"Checking audit query status...\"\nStart-Sleep -Seconds 30\n$Uri = (\"https:\/\/graph.microsoft.com\/beta\/security\/auditLog\/queries\/{0}\" -f $AuditJob.id)\n$AuditQueryStatus = Invoke-MgGraphRequest -Uri $Uri -Method Get\n\nWhile ($SearchFinished -eq $false) {\n    $i++\n    Write-Host (\"Waiting for audit search to complete. Check {0} after {1} seconds. Current state {2}\" -f $i, $SecondsElapsed, $AuditQueryStatus.status)\n    If ($AuditQueryStatus.status -eq 'succeeded') {\n        $SearchFinished = $true\n    } Else {\n        Start-Sleep -Seconds $SleepSeconds\n        $SecondsElapsed = $SecondsElapsed + $SleepSeconds\n        $AuditQueryStatus = Invoke-MgGraphRequest -Uri $Uri -Method Get\n    }\n}\n<\/pre>\n\n\n\n<p>The code shown above doesn\u2019t cope with status values other than \u201csucceeded\u201d, so it would need to be bullet-proofed for production use to handle status values such as failed or cancelled.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Fetching_Audit_Job_Results\"><\/span>Fetching Audit Job Results<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>To fetch the records found by an audit job, post a <em>Get<\/em> request to the queries endpoint for the audit job. A request can fetch a maximum of 999 records, so <a href=\"https:\/\/practical365.com\/pagination-graph-sdk\/\" target=\"_blank\" rel=\"noreferrer noopener\">pagination<\/a> is often needed to fetch the remaining records. This code shows how to fetch all the records.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$AuditRecords = [System.Collections.Generic.List[string]]::new()\n$Uri = (\"https:\/\/graph.microsoft.com\/beta\/security\/auditLog\/queries\/{0}\/records?`$top=999\" -f $AuditJob.Id)\n[array]$AuditSearchRecords = Invoke-MgGraphRequest -Uri $Uri -Method GET\n[array]$AuditRecords = $AuditSearchRecords.value\n\n$NextLink = $AuditSearchRecords.'@Odata.NextLink'\nWhile ($null -ne $NextLink) {\n    $AuditSearchRecords = $null\n    [array]$AuditSearchRecords = Invoke-MgGraphRequest -Uri $NextLink -Method GET \n    $AuditRecords += $AuditSearchRecords.value\n    Write-Host (\"{0} audit records fetched so far...\" -f $AuditRecords.count)\n    $NextLink = $AuditSearchRecords.'@odata.NextLink' \n}\n\nWrite-Host (\"Audit query {0} returned {1} records\" -f $AuditJobName, $AuditRecords.Count)\n<\/pre>\n\n\n\n<p>The code uses a <a href=\"https:\/\/learn.microsoft.com\/en-us\/powershell\/scripting\/learn\/deep-dives\/everything-about-arrays?view=powershell-7.5&amp;WT.mc_id=M365-MVP-9501#generic-list\" target=\"_blank\" rel=\"noreferrer noopener\">generic string list<\/a> instead of an array to avoid the performance penalty incurred if an array needs to be rebuilt frequently to add records. A regular array is fine for jobs that return less than a couple of thousand audit records.<\/p>\n\n\n\n<p>After fetching all the audit records, you can process them as required. For example, here\u2019s how to get a quick insight into the auditable actions included in the set of results for an audit log query.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$AuditRecords | Group-Object Operation -NoElement | Sort-Object Count -Descending | Format-Table -AutoSize<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Viewing_Audit_Job_Details\"><\/span>Viewing Audit Job Details<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>When an audit job is submitted, it joins the same queue that\u2019s visible in the Purview Audit solution, which means that you can follow the progress of an audit job through the Purview Audit UI (Figure 2). The advantage of using Purview Audit is that the GUI includes additional information about audit jobs, including the start time of the job, who submitted the job, how long the job has been running for, and how many audit records have been found so far. This information isn\u2019t available through the AuditLog Query API, which is limited to a simple output of the audit jobs on the queue.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"669\" src=\"https:\/\/practical365.com\/wp-content\/uploads\/2025\/03\/Audit-Log-GUI-1024x669.jpg\" alt=\"The GUI for the Purview Audit solution.\" class=\"wp-image-62086\" srcset=\"https:\/\/practical365.com\/wp-content\/uploads\/2025\/03\/Audit-Log-GUI-1024x669.jpg 1024w, https:\/\/practical365.com\/wp-content\/uploads\/2025\/03\/Audit-Log-GUI-300x196.jpg 300w, https:\/\/practical365.com\/wp-content\/uploads\/2025\/03\/Audit-Log-GUI-768x502.jpg 768w, https:\/\/practical365.com\/wp-content\/uploads\/2025\/03\/Audit-Log-GUI-1536x1003.jpg 1536w, https:\/\/practical365.com\/wp-content\/uploads\/2025\/03\/Audit-Log-GUI.jpg 1764w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Figure 2: The GUI for the Purview Audit solution<\/figcaption><\/figure>\n<\/div>\n\n\n<p>The Purview Audit GUI can report incorrect total results numbers for jobs that retrieve large numbers of audit records (more than 50,000). For instance, the third job shown in Figure 2 reports that it has found 172,951 records. When an API request fetched the records, the total retrieved was 415,406 (Figure 1). Treat the number shown in Purview as an estimate rather than an accurate value.<\/p>\n\n\n\n<p>The queue holds all audit jobs for the last 30 days, including those that are running and completed. The most valuable information displayed by listing audit log queries is the identifier, which can be used to retrieve the records found by the job. For example:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$Uri = \"https:\/\/graph.microsoft.com\/beta\/security\/auditLog\/queries\"\n$Data = Invoke-MgGraphRequest -Uri $Uri -Method GET\nIf ($Data) {\n    Write-Output \"Audit Jobs found\"\n    $Data.Value | ForEach-Object {\n        Write-Host (\"{0} {1}\" -f $_.id, $_.displayName)\n    }\n} Else {\n    Write-Output \"No audit jobs found\"\n}\n\nAudit Jobs found\nb19c7368-43e4-4f34-b693-9713549dbb80 Full audit job created at 09-Mar-2025 18:54\n713ac6f4-bb07-42af-b8b3-2f539ef5e9ea Big Audit job created at 09-Mar-2025 18:15\n<\/pre>\n\n\n\n<p>To fetch the records for an audit log search, all you need to do is add the job identifier to the query to the list audit records API:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$AuditJob = \"b19c7368-43e4-4f34-b693-9713549dbb80\"\n$Uri = (\"https:\/\/graph.microsoft.com\/beta\/security\/auditLog\/queries\/{0}\/records?`$top=999\" -f $AuditJob)\n[array]$AuditSearchRecords = Invoke-MgGraphRequest -Uri $Uri -Method GET\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-an-option-worth-considering\"><span class=\"ez-toc-section\" id=\"An_Option_Worth_Considering\"><\/span>An Option Worth Considering<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The AuditLog Query API is worth considering if you need to fetch audit data, especially when time is not of the essence. Processing of the AuditData property is still necessary to extract details about the actions captured in the records. The property is provided as a hash table and doesn\u2019t need to be converted from JSON, as is the case with data fetched by <em>Search-UnifiedAuditLog<\/em>. Overall, the AuditLog Query API is a welcome addition to the administrator\u2019s toolbox.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>After a year or so of using the AuditLog Query Graph API, we have enough experience to be able to explain how to take advantage of the API and when it could be used to run audit searches instead of the Search-UnifiedAuditLog cmdlet. There&#8217;s lots of PowerShell code in this article to give anyone who wants to experiment with the API a good start to finding audit events.<\/p>\n","protected":false},"author":84,"featured_media":62213,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[9890],"tags":[11354,11093,11356,11355],"class_list":["post-62084","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-microsoft-graph","tag-audit-log-search","tag-auditlog-query","tag-find-microsoft-365-audit-data","tag-purview-audit","entry","has-media"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.2 (Yoast SEO v27.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Running Audit Log Searches with the AuditLog Query API<\/title>\n<meta name=\"description\" content=\"After a year or so of using the AuditLog Query Graph API, we have enough experience to be able to explain how to take advantage of the API and when it could be used to run audit searches instead of the Search-UnifiedAuditLog cmdlet. There&#039;s lots of PowerShell code in this article to give anyone who wants to experiment with the API a good start to finding audit events.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Practical Graph: Running Audit Log Searches with the AuditLog Query API\" \/>\n<meta property=\"og:description\" content=\"After a year or so of using the AuditLog Query Graph API, we have enough experience to be able to explain how to take advantage of the API and when it could be used to run audit searches instead of the Search-UnifiedAuditLog cmdlet. There&#039;s lots of PowerShell code in this article to give anyone who wants to experiment with the API a good start to finding audit events.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/\" \/>\n<meta property=\"og:site_name\" content=\"Practical 365\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Practical365\" \/>\n<meta property=\"article:published_time\" content=\"2025-04-08T10:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-04-10T13:22:38+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/practical365.com\/wp-content\/uploads\/2025\/04\/1651-03-10-2025-Practical-Graph-Running-Audit-Log-Searches-with-the-AuditLog-Query-API-scaled.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1164\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Tony Redmond\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/12Knocksinna\" \/>\n<meta name=\"twitter:site\" content=\"@Practical365\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Tony Redmond\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/practical365.com\\\/auditlog-query-api-deeper-look\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/auditlog-query-api-deeper-look\\\/\"},\"author\":{\"name\":\"Tony Redmond\",\"@id\":\"https:\\\/\\\/practical365.com\\\/#\\\/schema\\\/person\\\/19d7b2f404dd1da1d87586fb07015a19\"},\"headline\":\"Practical Graph: Running Audit Log Searches with the AuditLog Query API\",\"datePublished\":\"2025-04-08T10:00:00+00:00\",\"dateModified\":\"2025-04-10T13:22:38+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/auditlog-query-api-deeper-look\\\/\"},\"wordCount\":1673,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/auditlog-query-api-deeper-look\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/practical365.com\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/1651-03-10-2025-Practical-Graph-Running-Audit-Log-Searches-with-the-AuditLog-Query-API-scaled.jpg\",\"keywords\":[\"Audit Log search\",\"Auditlog query\",\"Find Microsoft 365 audit data\",\"Purview Audit\"],\"articleSection\":[\"Microsoft Graph\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/practical365.com\\\/auditlog-query-api-deeper-look\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/practical365.com\\\/auditlog-query-api-deeper-look\\\/\",\"url\":\"https:\\\/\\\/practical365.com\\\/auditlog-query-api-deeper-look\\\/\",\"name\":\"Running Audit Log Searches with the AuditLog Query API\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/auditlog-query-api-deeper-look\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/auditlog-query-api-deeper-look\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/practical365.com\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/1651-03-10-2025-Practical-Graph-Running-Audit-Log-Searches-with-the-AuditLog-Query-API-scaled.jpg\",\"datePublished\":\"2025-04-08T10:00:00+00:00\",\"dateModified\":\"2025-04-10T13:22:38+00:00\",\"description\":\"After a year or so of using the AuditLog Query Graph API, we have enough experience to be able to explain how to take advantage of the API and when it could be used to run audit searches instead of the Search-UnifiedAuditLog cmdlet. There's lots of PowerShell code in this article to give anyone who wants to experiment with the API a good start to finding audit events.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/auditlog-query-api-deeper-look\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/practical365.com\\\/auditlog-query-api-deeper-look\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/practical365.com\\\/auditlog-query-api-deeper-look\\\/#primaryimage\",\"url\":\"https:\\\/\\\/practical365.com\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/1651-03-10-2025-Practical-Graph-Running-Audit-Log-Searches-with-the-AuditLog-Query-API-scaled.jpg\",\"contentUrl\":\"https:\\\/\\\/practical365.com\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/1651-03-10-2025-Practical-Graph-Running-Audit-Log-Searches-with-the-AuditLog-Query-API-scaled.jpg\",\"width\":2560,\"height\":1164},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/practical365.com\\\/auditlog-query-api-deeper-look\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/practical365.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Microsoft Graph\",\"item\":\"https:\\\/\\\/practical365.com\\\/microsoft-graph\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Practical Graph: Running Audit Log Searches with the AuditLog Query API\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/practical365.com\\\/#website\",\"url\":\"https:\\\/\\\/practical365.com\\\/\",\"name\":\"Practical 365\",\"description\":\"Practical Office 365 News, Tips, and Tutorials\",\"publisher\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/practical365.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/practical365.com\\\/#organization\",\"name\":\"Practical 365\",\"url\":\"https:\\\/\\\/practical365.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/practical365.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/practical365.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/Logo-P365-stacked.jpg\",\"contentUrl\":\"https:\\\/\\\/practical365.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/Logo-P365-stacked.jpg\",\"width\":1176,\"height\":696,\"caption\":\"Practical 365\"},\"image\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/Practical365\",\"https:\\\/\\\/x.com\\\/Practical365\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/practical365-com\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/practical365.com\\\/#\\\/schema\\\/person\\\/19d7b2f404dd1da1d87586fb07015a19\",\"name\":\"Tony Redmond\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/practical365.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/cropped-TonyRedmondHeadShot2016-1200-96x96.jpg\",\"url\":\"https:\\\/\\\/practical365.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/cropped-TonyRedmondHeadShot2016-1200-96x96.jpg\",\"contentUrl\":\"https:\\\/\\\/practical365.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/cropped-TonyRedmondHeadShot2016-1200-96x96.jpg\",\"caption\":\"Tony Redmond\"},\"description\":\"Tony Redmond has written thousands of articles about Microsoft technology since 1996. He is the lead author for the Office 365 for IT Pros eBook, the only book covering Office 365 that is updated monthly to keep pace with change in the cloud. Apart from contributing to Practical365.com, Tony also writes at Office365itpros.com to support the development of the eBook. He has been a Microsoft MVP since 2004.\",\"sameAs\":[\"https:\\\/\\\/office365itpros.com\",\"https:\\\/\\\/x.com\\\/https:\\\/\\\/twitter.com\\\/12Knocksinna\"],\"url\":\"https:\\\/\\\/practical365.com\\\/author\\\/tony-redmondredmondassociates-org\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Running Audit Log Searches with the AuditLog Query API","description":"After a year or so of using the AuditLog Query Graph API, we have enough experience to be able to explain how to take advantage of the API and when it could be used to run audit searches instead of the Search-UnifiedAuditLog cmdlet. There's lots of PowerShell code in this article to give anyone who wants to experiment with the API a good start to finding audit events.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/","og_locale":"en_US","og_type":"article","og_title":"Practical Graph: Running Audit Log Searches with the AuditLog Query API","og_description":"After a year or so of using the AuditLog Query Graph API, we have enough experience to be able to explain how to take advantage of the API and when it could be used to run audit searches instead of the Search-UnifiedAuditLog cmdlet. There's lots of PowerShell code in this article to give anyone who wants to experiment with the API a good start to finding audit events.","og_url":"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/","og_site_name":"Practical 365","article_publisher":"https:\/\/www.facebook.com\/Practical365","article_published_time":"2025-04-08T10:00:00+00:00","article_modified_time":"2025-04-10T13:22:38+00:00","og_image":[{"width":2560,"height":1164,"url":"https:\/\/practical365.com\/wp-content\/uploads\/2025\/04\/1651-03-10-2025-Practical-Graph-Running-Audit-Log-Searches-with-the-AuditLog-Query-API-scaled.jpg","type":"image\/jpeg"}],"author":"Tony Redmond","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/12Knocksinna","twitter_site":"@Practical365","twitter_misc":{"Written by":"Tony Redmond","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/#article","isPartOf":{"@id":"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/"},"author":{"name":"Tony Redmond","@id":"https:\/\/practical365.com\/#\/schema\/person\/19d7b2f404dd1da1d87586fb07015a19"},"headline":"Practical Graph: Running Audit Log Searches with the AuditLog Query API","datePublished":"2025-04-08T10:00:00+00:00","dateModified":"2025-04-10T13:22:38+00:00","mainEntityOfPage":{"@id":"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/"},"wordCount":1673,"commentCount":0,"publisher":{"@id":"https:\/\/practical365.com\/#organization"},"image":{"@id":"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/#primaryimage"},"thumbnailUrl":"https:\/\/practical365.com\/wp-content\/uploads\/2025\/04\/1651-03-10-2025-Practical-Graph-Running-Audit-Log-Searches-with-the-AuditLog-Query-API-scaled.jpg","keywords":["Audit Log search","Auditlog query","Find Microsoft 365 audit data","Purview Audit"],"articleSection":["Microsoft Graph"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/practical365.com\/auditlog-query-api-deeper-look\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/","url":"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/","name":"Running Audit Log Searches with the AuditLog Query API","isPartOf":{"@id":"https:\/\/practical365.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/#primaryimage"},"image":{"@id":"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/#primaryimage"},"thumbnailUrl":"https:\/\/practical365.com\/wp-content\/uploads\/2025\/04\/1651-03-10-2025-Practical-Graph-Running-Audit-Log-Searches-with-the-AuditLog-Query-API-scaled.jpg","datePublished":"2025-04-08T10:00:00+00:00","dateModified":"2025-04-10T13:22:38+00:00","description":"After a year or so of using the AuditLog Query Graph API, we have enough experience to be able to explain how to take advantage of the API and when it could be used to run audit searches instead of the Search-UnifiedAuditLog cmdlet. There's lots of PowerShell code in this article to give anyone who wants to experiment with the API a good start to finding audit events.","breadcrumb":{"@id":"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/practical365.com\/auditlog-query-api-deeper-look\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/#primaryimage","url":"https:\/\/practical365.com\/wp-content\/uploads\/2025\/04\/1651-03-10-2025-Practical-Graph-Running-Audit-Log-Searches-with-the-AuditLog-Query-API-scaled.jpg","contentUrl":"https:\/\/practical365.com\/wp-content\/uploads\/2025\/04\/1651-03-10-2025-Practical-Graph-Running-Audit-Log-Searches-with-the-AuditLog-Query-API-scaled.jpg","width":2560,"height":1164},{"@type":"BreadcrumbList","@id":"https:\/\/practical365.com\/auditlog-query-api-deeper-look\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/practical365.com\/"},{"@type":"ListItem","position":2,"name":"Microsoft Graph","item":"https:\/\/practical365.com\/microsoft-graph\/"},{"@type":"ListItem","position":3,"name":"Practical Graph: Running Audit Log Searches with the AuditLog Query API"}]},{"@type":"WebSite","@id":"https:\/\/practical365.com\/#website","url":"https:\/\/practical365.com\/","name":"Practical 365","description":"Practical Office 365 News, Tips, and Tutorials","publisher":{"@id":"https:\/\/practical365.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/practical365.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/practical365.com\/#organization","name":"Practical 365","url":"https:\/\/practical365.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/practical365.com\/#\/schema\/logo\/image\/","url":"https:\/\/practical365.com\/wp-content\/uploads\/2022\/06\/Logo-P365-stacked.jpg","contentUrl":"https:\/\/practical365.com\/wp-content\/uploads\/2022\/06\/Logo-P365-stacked.jpg","width":1176,"height":696,"caption":"Practical 365"},"image":{"@id":"https:\/\/practical365.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/Practical365","https:\/\/x.com\/Practical365","https:\/\/www.linkedin.com\/company\/practical365-com"]},{"@type":"Person","@id":"https:\/\/practical365.com\/#\/schema\/person\/19d7b2f404dd1da1d87586fb07015a19","name":"Tony Redmond","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/practical365.com\/wp-content\/uploads\/2022\/06\/cropped-TonyRedmondHeadShot2016-1200-96x96.jpg","url":"https:\/\/practical365.com\/wp-content\/uploads\/2022\/06\/cropped-TonyRedmondHeadShot2016-1200-96x96.jpg","contentUrl":"https:\/\/practical365.com\/wp-content\/uploads\/2022\/06\/cropped-TonyRedmondHeadShot2016-1200-96x96.jpg","caption":"Tony Redmond"},"description":"Tony Redmond has written thousands of articles about Microsoft technology since 1996. He is the lead author for the Office 365 for IT Pros eBook, the only book covering Office 365 that is updated monthly to keep pace with change in the cloud. Apart from contributing to Practical365.com, Tony also writes at Office365itpros.com to support the development of the eBook. He has been a Microsoft MVP since 2004.","sameAs":["https:\/\/office365itpros.com","https:\/\/x.com\/https:\/\/twitter.com\/12Knocksinna"],"url":"https:\/\/practical365.com\/author\/tony-redmondredmondassociates-org\/"}]}},"_links":{"self":[{"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/posts\/62084","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/users\/84"}],"replies":[{"embeddable":true,"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/comments?post=62084"}],"version-history":[{"count":0,"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/posts\/62084\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/media\/62213"}],"wp:attachment":[{"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/media?parent=62084"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/categories?post=62084"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/tags?post=62084"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}