Microsoft Graph API
Synopsis
Creates a poller that signs in to Microsoft Entra ID as an app registration and reads a Microsoft 365 tenant through Microsoft Graph, on a configurable interval, and forwards records to downstream pipelines. Director polls the source system's API at configured intervals to retrieve log and telemetry data rather than receiving pushed events. Supports time windows that stay behind the current time, pagination that resumes where it stopped, retry logic, and mutual TLS.
What a Device Reads
In the console, a device reads one of three things:
- One resource path of its own, set on the device (see API and Incremental Polling).
- Its datasets: each dataset reads one Graph resource, on its own interval, through its own pipeline, with a saved position of its own. The dataset types, and what each needs, are on Microsoft Graph API Datasets.
- Its profiles: the datasets of the profiles assigned to it.
A device made through the API or a deployment template can still read a resource path and datasets together.
Two things change for a device that reads a resource path of its own:
- Records arrive later. With a
timestamp_field, each read now stopsdelayseconds before the current time, 300 by default. Records reach the pipeline that much later than before. max_pagesmeans something else. It used to be a hard limit, and the records beyond it were lost. Now it is the number of pages read in one poll, and the next poll continues where this one stopped.
Schema
- id: <numeric>
name: <string>
description: <string>
type: graphapi
tags: <string[]>
pipelines: <pipeline[]>
status: <boolean>
properties:
tenant_id: <string>
client_id: <string>
client_secret: <string>
version: <string>
resource: <string>
query_params: <string>
poll_interval: <numeric>
timeout: <numeric>
max_retries: <numeric>
retry_delay: <numeric>
enable_pagination: <boolean>
max_pages: <numeric>
enable_delta_query: <boolean>
timestamp_field: <string>
delay: <numeric>
initial_lookback: <numeric>
tls:
status: <boolean>
cert_name: <string>
key_name: <string>
passphrase: <string>
ca_name: <string>
min_tls_version: <string>
max_tls_version: <string>
insecure_skip_verify: <boolean>
Configuration
The following fields are used to define the device:
Device
| Field | Required | Default | Description |
|---|---|---|---|
id | Y | Unique identifier | |
name | Y | Device name | |
description | N | - | Optional description |
type | Y | Must be graphapi | |
tags | N | - | Optional tags |
pipelines | N | - | Optional pre-processor pipelines |
status | N | true | Enable/disable the device |
Authentication
| Field | Required | Default | Description |
|---|---|---|---|
tenant_id | Y | Azure AD tenant ID | |
client_id | Y | App registration client ID | |
client_secret | Y | App registration client secret |
API
| Field | Required | Default | Description |
|---|---|---|---|
version | N | v1.0 | Graph API version: v1.0 or beta. A custom dataset that names no version reads with this one |
resource | N | Graph API resource path that the device reads itself (see Allowed Resources). Optional when the device reads datasets. A device with no resource and no dataset reads nothing, and its connection state says so | |
query_params | N | "" | OData query parameters (e.g., $select=id,createdDateTime&$top=100) |
Polling
| Field | Required | Default | Description |
|---|---|---|---|
poll_interval | N | 10 | Seconds between polls of the device's own resource (must be > 0). Each dataset has its own interval |
HTTP
| Field | Required | Default | Description |
|---|---|---|---|
timeout | N | 30 | Request timeout in seconds |
max_retries | N | 3 | Number of retry attempts on failure |
retry_delay | N | 5 | Seconds to wait between retries |
Pagination
| Field | Required | Default | Description |
|---|---|---|---|
enable_pagination | N | true | Follow @odata.nextLink pages automatically. Applies only to the device's own resource |
max_pages | N | 10 | Maximum pages per poll of the device's own resource (0 = unlimited). A poll that reaches it saves the link to the next page, and the next poll continues from it. Each dataset has its own max_pages |
Incremental Polling
| Field | Required | Default | Description |
|---|---|---|---|
timestamp_field | N | "" | JSON field name to read the device's own resource by, such as createdDateTime. Each poll then reads one time window (see Incremental Polling). Empty reads the whole resource at every poll |
delay | N | 300 | Seconds before the current time at which each window of the device's own resource ends |
initial_lookback | N | 3600 | Seconds back that the first window starts. It is also the default of the device's datasets |
enable_delta_query | N | false | Not supported: none of the allowed resources has a delta query, so Graph refuses the request. The device logs a warning when it is on. A timestamp_field takes priority over it |
TLS
| Field | Required | Default | Description |
|---|---|---|---|
tls.status | N | false | Enable mutual TLS |
tls.cert_name | Y* | cert.pem | Client certificate for mutual TLS |
tls.key_name | Y* | key.pem | Client private key for mutual TLS |
tls.passphrase | N | - | Passphrase for an encrypted private key |
tls.ca_name | N | - | CA bundle used to verify the server certificate. When unset, the host trust store is used. |
tls.min_tls_version | N | tls1.2 | Minimum accepted TLS version (tls1.0, tls1.1, tls1.2, tls1.3) |
tls.max_tls_version | N | - | Maximum accepted TLS version. When unset, the highest mutually supported version is negotiated. |
tls.insecure_skip_verify | N | false | Skip server certificate verification. Use only for testing. |
* = Required when tls.status is true.
TLS material fields (cert_name, key_name, ca_name, client_ca_name) accept any of the following:
- File name — resolved relative to the service root directory. Nested paths such as
certs/prod/server.pemare supported. - Absolute path — honored only if it resolves inside the service root. Any path that escapes the root is refused.
- Inline PEM content — used verbatim when the value contains
-----BEGIN. - Environment variable —
${ENV_VAR}. - Vault reference —
$secret{id=...}or$secret{store=...,ref=...}.
Details
Authentication
The device uses OAuth2 client credentials flow to obtain an access token from Azure AD. Tokens are cached per device/tenant/client combination and automatically refreshed on authentication failure (HTTP 401/403).
When client_id and client_secret are omitted, the credential provider automatically falls back to Azure Managed Identity, authenticating without explicit credentials when running on an Azure-hosted VM or container with a system-assigned or user-assigned managed identity.
Incremental Polling
With a timestamp_field, each poll of the device's own resource reads one time window:
- Each window covers the records whose time field falls between the end of the last window and
delayseconds before now. Microsoft adds records to Graph some minutes after they happen, and a window that ended at the poll would miss the ones on their way. - When
max_pagesstops a poll, the next poll continues from the same place, so nothing is skipped. - A record at the window's edge is read once. It used to be read twice.
- The first poll starts
initial_lookbackseconds back. The cursor merges with any existing$filterinquery_params.
Without a timestamp_field, each poll fetches the whole resource.
Delta query. No allowed resource supports a delta query, so enable_delta_query cannot work: Graph refuses the request. Use a timestamp_field instead.
Allowed Resources
The device enforces an allow list of Graph API resource paths. Requests to unlisted resources are rejected. Sub-paths of allowed resources (e.g., auditLogs/directoryAudits/someId) are also accepted. The same list applies to a custom dataset.
The permissions below are the least-privileged application permissions. Where a resource also needs a licence in the tenant, the licence is named: without it, Graph refuses the request whatever the app's permissions.
Audit Logs
| Resource | Required Permission | Licence |
|---|---|---|
auditLogs/signIns | AuditLog.Read.All | Microsoft Entra ID P1 or P2 |
auditLogs/directoryAudits | AuditLog.Read.All | |
auditLogs/provisioning | AuditLog.Read.All and Directory.Read.All |
Security
| Resource | Required Permission | Licence |
|---|---|---|
security/alerts_v2 | SecurityAlert.Read.All | |
security/incidents | SecurityIncident.Read.All | |
security/secureScores | SecurityEvents.Read.All | |
security/secureScoreControlProfiles | SecurityEvents.Read.All | |
security/attackSimulation | AttackSimulation.Read.All | Microsoft Defender for Office 365 Plan 2 |
security/cases/ediscoveryCases | eDiscovery.Read.All | An eDiscovery licence |
security/threatIntelligence/articles | ThreatIntelligence.Read.All | Microsoft Defender XDR or Microsoft Sentinel |
Identity Protection
| Resource | Required Permission | Licence |
|---|---|---|
identityProtection/riskDetections | IdentityRiskEvent.Read.All | Microsoft Entra ID P1 or P2 |
identityProtection/riskyUsers | IdentityRiskyUser.Read.All | Microsoft Entra ID P2 |
identityProtection/riskyServicePrincipals | IdentityRiskyServicePrincipal.Read.All | Microsoft Entra Workload ID Premium |
identityProtection/servicePrincipalRiskDetections | IdentityRiskEvent.Read.All | Microsoft Entra Workload ID Premium |
Reports
| Resource | Required Permission | Licence |
|---|---|---|
reports/authenticationMethods/userRegistrationDetails | AuditLog.Read.All | Microsoft Entra ID P1 or P2 |
The Microsoft 365 usage reports (reports/getEmailActivityUserDetail, reports/getEmailActivityCounts, reports/getEmailAppUsageUserDetail, reports/getMailboxUsageDetail, reports/getOffice365ActivationsUserDetail, reports/getOffice365ActiveUserDetail, reports/getOffice365GroupsActivityDetail, reports/getOneDriveActivityUserDetail, reports/getOneDriveUsageAccountDetail, reports/getSharePointActivityUserDetail, reports/getSharePointSiteUsageDetail, reports/getTeamsUserActivityUserDetail, reports/getTeamsDeviceUsageUserDetail and reports/getYammerActivityUserDetail) are on the allow list, but they cannot be read as a device's own resource. They need a period or date parameter, and on v1.0 they return a CSV file. Read them with the usage report datasets on Microsoft Graph API Datasets. They need Reports.Read.All.
Service Announcements
| Resource | Required Permission | Licence |
|---|---|---|
admin/serviceAnnouncement/issues | ServiceHealth.Read.All | |
admin/serviceAnnouncement/messages | ServiceMessage.Read.All | |
admin/serviceAnnouncement/healthOverviews | ServiceHealth.Read.All |
Exchange Message Trace
Message trace is read with the message trace dataset, from admin/exchange/tracing/messageTraces. It needs ExchangeMessageTrace.Read.All and a one-time setup step in the tenant. See Microsoft Graph API Datasets.
Resources That Cannot Be Read
These entries stay on the allow list, so that a configuration naming one still loads. They cannot be read, and a device whose own resource is one of them logs why:
| Resource | Why |
|---|---|
security/alerts | Microsoft retired it on 2026-10-15. Use security/alerts_v2. |
security/tiIndicators | Beta only and deprecated. Microsoft scheduled its removal for April 2026. |
security/cloudAppSecurityProfiles | Graph documents no such API. |
security/threatIntelligence/hosts | Graph cannot list it. You can only fetch one host by name or IP address. |
reports/credentialUserRegistrationDetails | It stopped returning data on 2024-06-30. Use authentication method registration (reports/authenticationMethods/userRegistrationDetails). |
reports/userCredentialUsageDetails | It stopped returning data on 2025-08-01. |
reports/applicationSignInDetailedSummary | Graph does not allow application permissions for it. |
reports/messageTrace | No such Graph path exists. The message trace dataset reads admin/exchange/tracing/messageTraces. |
Required Permissions
To cover all readable resources and datasets, add the following Application permissions to the Azure App Registration and grant admin consent:
AuditLog.Read.AllDirectory.Read.AllSecurityAlert.Read.AllSecurityIncident.Read.AllSecurityEvents.Read.AllAttackSimulation.Read.AlleDiscovery.Read.AllThreatIntelligence.Read.AllIdentityRiskEvent.Read.AllIdentityRiskyUser.Read.AllIdentityRiskyServicePrincipal.Read.AllReports.Read.AllServiceHealth.Read.AllServiceMessage.Read.AllExchangeMessageTrace.Read.All
All permissions require admin consent. After adding them in the Azure portal, click Grant admin consent for [your tenant] to activate them. Only add permissions for the resources you intend to poll.
Console
In the console, go to
General settings , as on every device.API settings : underAuthentication ,Managed identity , orTenant ID ,Client ID andClient secret ; underAPI ,API version (v1.0). A custom dataset that sets no version reads with this one.Advanced settings : underHTTP ,Timeout (Optional) (30),Maximum retries (Optional) (3) andRetry delay (Optional) (5); thenTLS settings , with theMutual TLS switch and, while it is on,Certificate ,Private key andSkip certificate verification .Data collection : what the device reads, one of three tiles. A new device starts onDatasets . A clone of a device with a resource path starts onResource path .Resource path :Resource path (required here) andQuery parameters (Optional) ; underPolling ,Poll interval (Optional) (10); underPagination ,Automatic pagination andMaximum pages (Optional) (10); underIncremental polling ,Timestamp field (Optional) andDelay (Optional) (300).Delta query shows only on a device saved with it on, with a warning to turn it off.Datasets orProfiles : the datasets or profiles assigned to the device. The device then sends noresource,query_params,poll_interval,timestamp_field,delay,enable_delta_query,enable_paginationormax_pages. A Director older than 2.6.1 refuses such a device, and the step warns as soon as one of these tiles is chosen.
Review and create .
The device's page has
Examples
Basic
Polling sign-in logs with a timestamp cursor for incremental collection... | |
Datasets
Reading security alerts and directory audits as datasets, with no resource of the device's own. Each dataset reads on its own interval, and the alerts go through a pipeline of their own... | |
Security Alerts
Collecting security alerts with OData filtering and preprocessing pipelines... | |
High-Volume
Optimizing for high data volumes with a longer timeout and more pages per poll... | |
Secure Connection
Enabling mutual TLS for outbound Graph API requests... | |