Skip to content

Microsoft Purview Audit Log Queries

Microsoft Graph auditLogQuery API— within microsoft.graph.security (beta endpoint)—is paramount for today’s SOC teams to allow investigation across their Microsoft tenant.

auditLogQuery supports the high-volume data demands of SOC but also everything revolving around IT, GRC, and Sec

One thing to note is that auditLogQuery runs on an asynchronous system, by decoupling the query definition from the data extraction process, thereby allowing for the retrieval of hundreds of thousands of records without the limitations of traditional synchronous requests.

Architectural Foundations of the Asynchronous Audit Framework

Section titled “Architectural Foundations of the Asynchronous Audit Framework”

Microsoft Graph auditLogQuery API is characterized by its asynchronous lifecycle, which transforms how you interact with the Unified Audit Log (UAL).

Instead of a single request returning a static result set, the API requires a multi-stage orchestration that includes query submission, status monitoring, and paged data retrieval.

Users will have to configure their workflow to interpret and respond to the various states of an audit query. Upon submission, Microsoft will answer with a unique identifier that serves as the primary key for all subsequent interactions.

Query StatusOperational SignificanceAutomation Action Required
notStartedThe request is queued but has not yet been processed by the auditing engine.Continue polling; no results available.
runningThe engine is actively scanning the data mart and aggregating records based on filters.Continue polling; estimate remaining time based on history.
succeededThe query has finished, and the complete result set is ready for extraction.Trigger the data retrieval and pagination logic.
failedAn error occurred, such as an invalid filter or an internal service interruption.Log the error details and potentially retry with a narrowed window.
cancelledThe query was manually terminated by an administrative action.Terminate the workflow or restart the job.
unknownFutureValueA placeholder for future additions to the status enumeration.Implement default error handling to maintain robustness.

The API employs a granular permission model that allows for service-specific scoping, enabling organizations to adhere to the principle of least privilege.

For instance, a workflow dedicated to monitoring file exfiltration in OneDrive does not necessarily require the same level of access as a global compliance audit of all Exchange Online administrative actions.

Section titled “Permission Scopes and Administrative Consent”

To enable the auditLogQuery functionality, an application registration must be created in Microsoft Entra ID (see Authentication).

Permission ScopeTarget Service DomainUsage Context
AuditLogsQuery.Read.AllAll Microsoft 365 servicesGlobal security sweeps and comprehensive compliance reporting.
AuditLogsQuery-Entra.Read.AllMicrosoft Entra ID (Azure AD)Monitoring logins, account changes, and role assignments.
AuditLogsQuery-SharePoint.Read.AllSharePoint OnlineAuditing site access, file operations, and sharing events.
AuditLogsQuery-OneDrive.Read.AllOneDrive for BusinessFocused monitoring of personal document library activities.
AuditLogsQuery-Exchange.Read.AllExchange OnlineAuditing mailbox access, mail flow rules, and admin actions.
AuditLogsQuery-CRM.Read.AllDynamics 365Tracking access to customer relationship management data.
AuditLogsQuery-Endpoint.Read.AllEndpoint DLPMonitoring data loss prevention events on managed devices.

These permissions are supported for both Delegated (work or school) and Application permissions, though Application permissions are standard for background automation.

The service principal must be granted the AuditLogsQuery.Read.All application permission and receive administrator consent through the Entra portal.

When the flow executes, it uses the installed certificate to obtain a token from the Microsoft Identity Platform, ensuring that the entire lifecycle of the audit search—from job creation to record retrieval—is performed securely under the context of a managed identity.

Engineering the Query: JSON Schema and Filter Logic

Section titled “Engineering the Query: JSON Schema and Filter Logic”

The efficacy of an automated audit process depends heavily on the precision of the query filters. The auditLogQuery resource provides a wide array of properties that allow an automation platform to refine the search at the source, significantly reducing the volume of data that must be transmitted and processed downstream.

A POST request to the /security/auditLog/queries endpoint requires a JSON body that defines the search parameters.

The following table details the schema used to construct these requests.

PropertyData TypeRequiredDescription and Use case
displayNameStringNoA human-readable label for the job, such as “Daily_File_Sweep_2025-05-15”.
filterStartDateTimeDateTimeOffsetYesThe beginning of the audit window in ISO 8601 format (UTC).
filterEndDateTimeDateTimeOffsetNoThe end of the audit window. Usually calculated as .
recordTypeFiltersString CollectionNoFilters results to specific workloads (e.g., sharePoint, exchangeItem).
operationFiltersString CollectionNoFilters for specific actions like FileDownloaded or UserLoggedIn.
userPrincipalNameFiltersString CollectionNoRestricts the search to specific actors by their UPN.
ipAddressFiltersString CollectionNoFilters by the source IP address of the logged activity.
objectIdFiltersString CollectionNoTarget URLs for files or names of modified administrative objects.
administrativeUnitIdFiltersString CollectionNoScopes the query to specific Entra ID Administrative Units.
keywordFilterStringNoA free-text search against non-indexed properties in the log.

The filterStartDateTime and filterEndDateTime are the most critical parameters for ensuring data continuity. Use Data Transform Functions to generate the auditLogQuery window!

The recordTypeFilters property acts as a high-level classifier that directs the query engine to specific data silos.

Selecting the appropriate record types is essential for performance, as it allows the service to ignore irrelevant telemetry from other workloads.

Record TypeWorkload Context
azureActiveDirectoryIdentity management, group changes, and application registrations.
azureActiveDirectoryAccountLogonSpecific logon events and authentication attempts.
sharePointFileOperationGranular file-level activities within SharePoint sites.
oneDriveDocument-centric activities within personal OneDrive storage.
exchangeAdminConfiguration changes made by Exchange administrators.
exchangeItemAccess and modification of mailbox items (e.g., emails, calendar).
complianceDLPSharePointData loss prevention policy matches within SharePoint.
syntheticProbeSystem-generated events for monitoring and health checks.

By combining these record types with specific operationFilters, such as FileDownloaded or SharingSet, you can build highly targeted detection monitors on Mindflow.

The automation is typically structured as a “Poll-and-Retrieve” workflow. This pattern utilizes the “Until” loop to manage the state of the audit job.

  1. Job Initialization: User may submit their query to the following HTTP POST endpoint https://graph.microsoft.com/beta/security/auditLog/queries.

    Terminal window
    curl -X POST "https://graph.microsoft.com/beta/security/auditLog/queries" \
    -H "Authorization: Bearer `<YOUR_ACCESS_TOKEN>`" \
    -H "Content-Type: application/json" \
    -d '{
    "displayName": "Forensic_Investigation_Feb2026",
    "filterStartDateTime": "2026-02-10T00:00:00Z",
    "filterEndDateTime": "2026-02-11T00:00:00Z",
    "recordTypeFilters": ["azureActiveDirectory", "sharePointFileOperation"],
    "userPrincipalNameFilters": ["target.user@contoso.com"]
    }'

    This step will return a jobId.

  2. State Polling: An “Until” loop is configured to execute until the status property of the query object equals succeeded. Within this loop, an HTTP GET request is directed to https://graph.microsoft.com/beta/security/auditLog/queries/{id}.

    Terminal window
    curl -X GET "[https://graph.microsoft.com/beta/security/auditLog/queries/](https://graph.microsoft.com/beta/security/auditLog/queries/)`<QUERY_ID>`" \
    -H "Authorization: Bearer `<YOUR_ACCESS_TOKEN>`"
  3. Backoff Logic: To comply with API throttling and reduce unnecessary load, a “Delay” action (typically 30 to 60 seconds) is placed inside the loop.

  4. Error Handling: Users may have a condition step within the loop to check on the status of the query and detect if the status becomes failed or cancelled.

  5. Record Extraction: Once the loop completes successfully, a final GET request is made to https://graph.microsoft.com/beta/security/auditLog/queries/{id}/records to fetch the first page of audit data.

    Terminal window
    curl -X GET "[https://graph.microsoft.com/beta/security/auditLog/queries/](https://graph.microsoft.com/beta/security/auditLog/queries/)`<QUERY_ID>`/records" \
    -H "Authorization: Bearer `<YOUR_ACCESS_TOKEN>`"

Specialized Use Case: User and File Investigation

Section titled “Specialized Use Case: User and File Investigation”

One of the primary advantages of the auditLogQuery API is its ability to perform targeted investigations across multiple users or specific sensitive assets.

The userPrincipalNameFilters property accepts a collection of strings, allowing an automation platform to audit an entire group of individuals simultaneously.

This is particularly useful in insider threat scenarios where a list of “high-risk” employees is maintained in an external HR system. Mindflow can ingest this list and generate a single audit job that covers all relevant activities across the entire tenant.

Tip: You can also run a query on an IP address:

Terminal window
Inside the -d JSON body:
"ipAddressFilters": ["192.168.1.50"]

Or on specific operations:

Terminal window
Inside the -d JSON body:
"recordTypeFilters": ["azureActiveDirectory"],
"operationFilters": ["Reset user password", "Add member to group"]

File-Centric Forensics via objectIdFilters

Section titled “File-Centric Forensics via objectIdFilters”

For file activities, the objectIdFilters property is the primary mechanism for scoping. In the context of SharePoint and OneDrive, this filter requires the full URL path of the document or folder.

Terminal window
{
"filterStartDateTime": "2026-02-01T00:00:00Z",
"objectIdFilters": ["[https://tenant.sharepoint.com/sites/Finance/Docs/Budget2026.pdf](https://tenant.sharepoint.com/sites/Finance/Docs/Budget2026.pdf)"],
"operationFilters": ["FileDownloaded", "FileAccessed"]
}

Mindflow can be triggered by a sensitive file being labeled as “Confidential” by an automated labeling policy or an alert regarding a potentially malicious file uploaded on SharePoint. The automation then initiates an audit query to identify every user who has accessed, downloaded, or shared that specific URL over the previous 90 days, providing an immediate forensic trail.

Forensic ParameterValue ExampleImpact on Query Scope
recordTypeFilterssharePointFileOperationRestricts to file-level telemetry only.
operationFiltersFileDownloaded, FileAccessedFocuses on data egress and viewing.
objectIdFiltershttps://tenant.sharepoint.com/sites/Legal/Shared Documents/Contract.pdfPins the query to a single specific asset.

Correlating activity across different Microsoft 365 services is a complex task often hindered by the sheer volume of data. The keywordFilter property provides a vital tool for this purpose by allowing a free-text search against the non-indexed fields within the audit log records.

The most effective use of the keywordFilter in a security automation context is for session correlation. When an suspicious event is detected in Microsoft Entra ID—such as a login from an atypical location—the audit record for that login includes an AzureActiveDirectorySessionId.

To find all other actions performed by that attacker within the same authenticated session across SharePoint, Exchange, or Teams, the automation platform can initiate a new auditLogQuery with the keywordFilter set to that specific Session ID.

This “pivoting” capability allows the automation to reconstruct the attacker’s timeline with high precision. Because the keywordFilter searches through the raw JSON payload of the audit records, it can find strings that are not promoted to top-level properties, making it an indispensable tool for deep forensic analysis.

When an audit query results in a large volume of telemetry—sometimes exceeding hundreds of thousands of records—the automation platform must be equipped to handle paged data retrieval and ensure data integrity.

The Microsoft Graph API implements server-side pagination to manage the size of individual HTTP responses. When the results of an auditLogQuery exceed the page size limit (typically 150 to 200 records), the response from the records endpoint includes an @odata.nextLink property. This property contains the full URL required to fetch the next batch of data.

Terminal window
{
"value": [... 150 records ...],
"@odata.nextLink": "[https://graph.microsoft.com/beta/security/auditLog/queries/{id}/records?$skip=150](https://graph.microsoft.com/beta/security/auditLog/queries/%7Bid%7D/records?$skip=150)"
}

Users may rely on Loops to:

  1. Check for the existence of @odata.nextLink in every response from the records endpoint.

  2. Execute a GET request to the provided URL if the link is present.

    Terminal window
    curl -X GET "[https://graph.microsoft.com/beta/security/auditLog/queries/](https://graph.microsoft.com/beta/security/auditLog/queries/)`<QUERY_ID>`/records?$skip=150" \
    -H "Authorization: Bearer `<YOUR_ACCESS_TOKEN>`"
  3. Accumulate the records from each page into a variable (with array concat).

  4. Terminate the loop when the link is no longer returned.

Advanced Data Integrity: Handling Split Records

Section titled “Advanced Data Integrity: Handling Split Records”

A challenge in automating queries on audit logs is the “Split Record” phenomenon. Graph enforces an internal size limit for individual audit records (approximately 30-50 KB).

When an event—such as a large-scale license change or an update to a group with thousands of members—results in a payload that exceeds this limit, the system automatically splits the event into multiple sequential records.

Each part of a split record contains metadata that allows users to reconstruct the original event. These fragments are linked by a shared CorrelationId and include sequence information within the extendedProperties object.

Fragment PropertyValue Meaning
seqThe specific position of this chunk in the sequence (e.g., “2”).
cThe total number of expected chunks for this event (e.g., “5”).
bThe actual fragment of the JSON payload, often escaped.

To maintain data integrity, users must implement a reconstruction algorithm:

  1. Buffer records in memory or a staging table as they are retrieved.
  2. Filter for records where the c (count) property is greater than 1.
  3. Group these records by their CorrelationId.
  4. Sort the records within each group by the seq (sequence) number.
  5. Concatenate the strings found in the b (base) properties in the correct order.
  6. Parse the resulting complete string as the final, valid JSON event.

Throttling, Limits, and Operational Resilience

Section titled “Throttling, Limits, and Operational Resilience”

Operating Mindflow against the Microsoft Graph API requires a strategic approach to rate limiting and service-specific constraints.

Microsoft Graph concurrently imposes several categories of throttling limits. For the Identity and Access Reports service, which handles audit queries, the limits are significantly tighter than general Graph operations.

Limit TypeResource Unit Quota (Example)Timing Window
Global App Limit130,000 requests10 Seconds
Identity Reports (Per App/Tenant)5 requests10 Seconds
POST on Export1,000 requestsPer Day

Users may add a check logic within requests’ response headers, to check for x-ms-throttle-priority-parameter or similar headers to gauge how close they are to reaching limits.

When hitting throttle, users may implement a Retry attempt logic or use Loop to handle the timeout.

A common mistake in audit automation is querying for data that occurred too recently. Due to the distributed nature of the Microsoft 365 environment, there is an inherent delay between the occurrence of an event and its availability in the audit log.

While simple events like Entra ID logins may appear within minutes, complex SharePoint or Exchange actions can take significantly longer—sometimes up to 24 hours—to be fully indexed and searchable.

For a daily or hourly automation, it is a recommended practice to set the filterEndDateTime to at least one hour in the past to ensure that the ingestion process has completed for that time window.

To maximize the value of the auditLogQuery API within an automation platform, organizations should adopt the following strategic principles.

To reduce the total time required for historical data retrieval, users may leverage parallelisation either through subflow/agents/for each.

Given that the results of an auditLogQuery are only available online for 30 days after a job finishes,users should prioritize storing the retrieved records into their incidents tickets or long-term cloud storage.