Purpose: A practical, engineer-focused reference for discovering and using Microsoft Graph endpoints that return Entra ID data.
Use this as a printable reference, a living document, or a baseline for building your own internal Graph catalog.
-
π¨π»βπ» Microsoft Graph
/meand/$valueβ Quick Reference -
π± Microsoft Graph Intune Device Management β Metadata & OData Usage Guide
Microsoft Graph is Microsoftβs unified REST API that provides a single endpoint to access data and actions across Microsoft cloud services.
Instead of calling many different service-specific APIs (Azure AD, Exchange, SharePoint, Intune, Teams), Microsoft Graph exposes them through one consistent API surface.
At a high level, Microsoft Graph allows you to:
- Read and manage Entra ID (Azure AD) objects (users, groups, devices)
- Configure authentication and security policies
- Access Microsoft 365 data (mail, calendar, files)
- Manage Intune / device management
- Query audit logs, sign-ins, and reports
All Microsoft Graph calls use a single base URL:
https://graph.microsoft.comYou then choose an API version:
v1.0β production, stablebetaβ preview, newest features (may change)
Example:
https://graph.microsoft.com/v1.0/meMicrosoft Graph is built on REST + OData principles.
Key concepts:
- Resources β users, groups, devices, policies
- Relationships β members, owners, assignments
- Actions β reset password, assign license
Example resource path:
/users/{id}/memberOf
Microsoft Graph uses OAuth 2.0 access tokens issued by Entra ID.
You must authenticate using one of these identities:
- A signed-in user (delegated permissions)
- An application / service principal (application permissions)
| Permission type | Runs as | Typical use |
|---|---|---|
| Delegated | Signed-in user | Graph Explorer, user tools |
| Application | App identity | Automation, background jobs |
Digging Into the Graph Documentation
Getting familiar with upcoming Microsoft Changes
https://developer.microsoft.com/en-us/graph/changelog/?filterBy=beta,Identity%20and%20access
Daniel Bradley MS Docs Tracker
Lokka
Graph Explorer is a browser-based tool for testing Graph requests.
- Runs as you
- Handles tokens automatically
- Best for learning and discovery
Example:
GET https://graph.microsoft.com/v1.0/meGraph Explorer
Microsoft Graph is fundamentally an HTTP REST API.
Example:
GET /v1.0/users
Authorization: Bearer {access_token}Used when:
- Building custom apps
- Calling Graph from scripts or services
Microsoft provides PowerShell modules that wrap Graph calls.
Example:
Connect-MgGraph -Scopes User.Read.All
Get-MgUserPowerShell is ideal for:
- Admin automation
- Reporting
- Bulk operations
Microsoft provides SDKs that abstract raw HTTP calls.
Supported languages include:
- C# / .NET
- JavaScript / TypeScript
- Python
- Java
SDKs handle:
- Authentication
- Paging
- Serialization
| Method | Purpose |
|---|---|
| GET | Read data |
| POST | Create objects or trigger actions |
| PATCH | Update existing objects |
| DELETE | Remove objects |
Example:
PATCH /v1.0/users/{id}GET https://graph.microsoft.com/v1.0/meReturns the signed-in userβs directory object as JSON.
In Microsoft Graph, /$value tells the service:
Return the raw value of the resource, not the JSON wrapper.
It is used when the resource represents:
- A binary stream (photo, file)
- A primitive value (string, number)
- A collection of primitive values
GET /v1.0/me/photo/$value- Returns raw binary image (JPEG/PNG)
- No JSON response
- Browser downloads or renders the image
GET /v1.0/me/photos/48x48/$valueGET /v1.0/me/mailboxSettings/timeZone/$valueReturns a plain string, not JSON metadata.
GET /v1.0/me/$valueβ Invalid because /me is a complex object, not a primitive or stream.
Typical error:
{
"error": {
"code": "BadRequest",
"message": "Cannot use $value on a complex type."
}
}| Resource type | /$value supported |
|---|---|
| Binary (photo, file) | β |
| Primitive (string, int) | β |
| Primitive collection | β |
| Complex object (user) | β |
| Navigation object (manager, memberOf) | β |
| Endpoint | Result |
|---|---|
/me/photo/$value |
Raw profile image |
/me/photos/{size}/$value |
Sized photo |
/me/mailboxSettings/timeZone/$value |
Plain string |
/me/manager/$value |
β Not supported |
User.Read(basic signed-in user)User.Read.All(reading other users)
/$value = raw output
No JSON wrapper
Use for photos, files, and primitive values
Never use it on /me itself
GET /v1.0/users
GET /v1.0/groups
GET /v1.0/devices
GET /v1.0/directoryObjectsGET /v1.0/users/{id}
GET /v1.0/users/{id}/memberOf
GET /v1.0/users/{id}/transitiveMemberOf
GET /v1.0/users/{id}/manager
GET /v1.0/users/{id}/directReports
GET /v1.0/users/{id}/registeredDevices
GET /v1.0/users/{id}/ownedDevices
GET /v1.0/users/{id}/authentication/methodsGET /v1.0/groups/{id}
GET /v1.0/groups/{id}/members
GET /v1.0/groups/{id}/transitiveMembers
GET /v1.0/groups/{id}/owners
GET v/1.0/groups/$count (Count requires a consistency level header)
GET https://graph.microsoft.com/v1.0/groups/$count?$filter=securityEnabled eq true
HEADER:
ConsistencyLevel: eventual
NOTE This is a more real world scenario to pull back the count for total security groups
Get https://graph.microsoft.com/v1.0/groups/$count?$filter=startswith(displayName,'ACME')
HEADER:
ConsistencyLevel: eventual
NOTE This is a more real world scenario to pull back the count for total groups that meet a naming convention
https://graph.microsoft.com/v1.0/groups?$select=displayName
https://graph.microsoft.com/v1.0/groups?$select=displayName&$expand=owners($select=displayName,userPrincipalName)
https://graph.microsoft.com/beta/groups?$select=displayname,grouptypes&$filter=groupTypes/any(c:c eq 'DynamicMembership')
https://graph.microsoft.com/v1.0/groups?$filter=startswith(displayName,'ACME-AUTH')&$select=id,displayName
What this does
/groups β queries all groups
$filter=startswith(displayName,'ACME-AUTH') β returns only groups whose names start with ACME-AUTH
$select=id,displayName β returns only: id (object ID)/displayName
Have to switch to Beta to report on Group Owner value
https://graph.microsoft.com/beta/groups/0e4b5629-83d8-4aae-a5cb-5f0c31836116?$expand=owners
##Grab the user account object ID: Cant patch a group owner with UserPrincipalName
https://graph.microsoft.com/beta/users/jhope@acmebaseline.onmicrosoft.com?$select=id
##Now its multiple steps to patch the odata with the updated owner
POST /v1.0/groups/{GROUP_OBJECT_ID}/owners/$ref
> Replace Group Object with the ID Above
Request body update with odata and user object id:
{
"@odata.id": "https://graph.microsoft.com/v1.0/users/USER_OBJECT_ID"
}
{
"@odata.id": "https://graph.microsoft.com/v1.0/users/eaf72a07-8d1f-4324-b8dd-35d906b86d6d"
}
Check for the updated group owner information
GET https://graph.microsoft.com/beta/groups/0e4b5629-83d8-4aae-a5cb-5f0c31836116?$expand=owners
How to filter better for just the Owner Display name and id
https://graph.microsoft.com/beta/groups/0e4b5629-83d8-4aae-a5cb-5f0c31836116?$select=id,displayName&$expand=owners($select=id,displayName)
NOTE: Groups self service sign up features:
https://learn.microsoft.com/en-us/entra/identity/users/groups-self-service-management?WT.mc_id=Portal-Microsoft_AAD_IAM#group-settings
Locate the Group to convert:
https://graph.microsoft.com/v1.0/groups?$filter=startswith(displayName,'AD')&$select=id,displayName
Document Group ID: (AD-AVDUsers)
GET https://graph.microsoft.com/v1.0/groups/abc11e5a-7aa8-4412-932d-f6d7c946cf7e/onPremisesSyncBehavior?$select=isCloudManaged
fce75b28-01cd-4270-b529-4989b1daf0db
Change the SOA from OnPrem to Cloud
PATCH https://graph.microsoft.com/v1.0/groups/abc11e5a-7aa8-4412-932d-f6d7c946cf7e/onPremisesSyncBehavior
REQUEST BODY:
{
"isCloudManaged": true
}
Group SOA https://learn.microsoft.com/en-us/entra/identity/hybrid/how-to-group-source-of-authority-configure
https://graph.microsoft.com/beta/groups?$select=displayName,groupTypes&$filter=groupTypes/any(c:c eq 'DynamicMembership')This filter means:
- Return only groups where the
groupTypescollection contains the valueDynamicMembership. - This query retrieves only dynamic groups from Microsoft Entra ID.
- The
groupTypesproperty is not a single value, it is a collection (array). - Examples of values returned by Microsoft Graph:
"groupTypes": []"groupTypes": ["Unified"]"groupTypes": ["DynamicMembership"]"groupTypes": ["Unified", "DynamicMembership"]- Because
groupTypesis a collection, you cannot filter it like this:
groupTypes eq 'DynamicMembership'- OData requires evaluating each element in the collection, which is why the
any()function is required.
groupTypes/any(c:c eq 'DynamicMembership')
| Component | Description |
|---|---|
| groupTypes | The collection property on the group object |
| any(...) | OData function that evaluates elements in a collection |
| c | Temporary variable representing each element |
| c eq 'DynamicMembership' | Condition applied to each element |
How to read this expression:
- For each value
cingroupTypes, return the group if any value equalsDynamicMembership. - If at least one element matches, the group is included in the response.
This query returns:
- Dynamic Security Groups
- Dynamic Microsoft 365 Groups
Both group types include the following value:
"groupTypes": ["DynamicMembership"]Microsoft 365 dynamic groups may also include:
"groupTypes": ["Unified", "DynamicMembership"]All Dynamic Groups
groupTypes/any(c:c eq 'DynamicMembership')Microsoft 365 (Unified) Groups Only
groupTypes/any(c:c eq 'Unified')Dynamic Microsoft 365 Groups Only
groupTypes/any(c:c eq 'Unified') and groupTypes/any(c:c eq 'DynamicMembership')Non-Dynamic Groups
not(groupTypes/any(c:c eq 'DynamicMembership'))The any() function is used throughout Microsoft Graph when filtering collection properties, including:
assignedLicenses/any(...)proxyAddresses/any(...)members/any(...)authenticationMethods/any(...)
Understanding any() allows you to:
- Reverse engineer Entra ID, Intune, and Microsoft 365 portal behavior
- Write precise and safe Microsoft Graph queries
- Avoid targeting unintended objects
- Confidently filter large datasets at scale
groupTypesis a collection, not a single valueany()checks whether at least one element matches a condition- This query returns only dynamic groups
- Mastering
any()is essential for effective Microsoft Graph filtering
GET /v1.0/applications
GET /v1.0/applications/{id}GET /v1.0/servicePrincipals
GET /v1.0/servicePrincipals/{id}
GET /v1.0/servicePrincipals/{id}/appRoleAssignments
GET /v1.0/servicePrincipals/{id}/oauth2PermissionGrantsGET /v1.0/identity/conditionalAccess/policies
GET /v1.0/identity/conditionalAccess/namedLocations
GET /v1.0/identity/conditionalAccess/authenticationStrengthshttps://graph.microsoft.com/v1.0/identity/conditionalAccess/policies
Response: Returns all Conditional Access policies with full details including:
Policy ID, display name, state (enabled/disabled/report-only)
Conditions (users, groups, applications, locations, platforms, etc.)
Grant controls (MFA, compliant device, approved app, etc.)
Session controls (sign-in frequency, persistent browser, etc.)
Authentication strength requirements
?$select=id,displayName,state
?$filter=state eq 'enabled'
(https://graph.microsoft.com/beta/identity/conditionalAccess/policies?$select=id,displayName,state&$filter=startswith(displayName,'ACME')&$orderby=displayName)
Youβre running into a Microsoft Graph beta limitation / bug, not a syntax issue on your side.
For Conditional Access policies, the /beta/identity/conditionalAccess/policies endpoint does not reliably enforce startswith() server-side. When this happens, Graph returns all policies and applies only partial or no filtering internally β which is why youβre seeing policies that do not start with ACME.
Key point (important)
There is currently no 100% reliable server-side way to return only CA policies whose displayName starts with a string.
> **Rule**: If the Entra blade is under **Protection**, the Graph path usually starts with `/identity`.
GET /v1.0/authenticationMethodsPolicy
GET /beta/authenticationMethodsPolicy
GET /beta/policies/authenticationMethodsPolicyPolicies/AuthenticationMethodsPolicy
**This endpoint returns a single singleton policy, not a collection.**
So:
β $filter
β $select for sub-objects
β βenabled onlyβ
β¦are not supported, because there is only one policy object per tenant.
Getting Familiar with different Authentication types
https://learn.microsoft.com/en-us/graph/api/resources/authenticationmethod?view=graph-rest-beta
GET /beta/authenticationMethodsPolicy/authenticationMethodConfigurations
GET /beta/authenticationMethodsPolicy/authenticationMethodConfigurations/FIDO2
GET /beta/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator
GET /beta/authenticationMethodsPolicy/authenticationMethodConfigurations/temporaryAccessPass
GET /beta/authenticationMethodsPolicy/authenticationMethodConfigurations/sms
GET /beta/authenticationMethodsPolicy/authenticationMethodConfigurations/voice
GET /beta/authenticationMethodsPolicy/authenticationMethodConfigurations/email
GET /beta/authenticationMethodsPolicy/authenticationMethodConfigurations/softwareOath
GET /beta/authenticationMethodsPolicy/authenticationMethodConfigurations/hardwareOath
GET /beta/authenticationMethodsPolicy/authenticationMethodConfigurations/x509Certificate
authenticationMethodsPolicy
βββ authenticationMethodConfigurations
βββ fido2
βββ microsoftAuthenticator
βββ temporaryAccessPass
βββ softwareOath
βββ hardwareOath
βββ sms
βββ voice
βββ email
βββ x509Certificate
π Permissions required
Read: Policy.Read.AuthenticationMethod
Write: Policy.ReadWrite.AuthenticationMethod
(Global Admin or Authentication Policy Admin role required)
GET /v1.0/users/{id}/authentication/methodsGET /v1.0/auditLogs/signIns
GET /v1.0/auditLogs/directoryAuditsGET /v1.0/reports/authenticationMethodsUserRegistrationDetails
GET /v1.0/reports/credentialUserRegistrationDetails
GET /v1.0/reports/signInActivityGET /v1.0/identityGovernance/accessReviews/definitions
GET /v1.0/identityGovernance/accessReviews/instancesGET /v1.0/identityGovernance/entitlementManagement/catalogs
GET /v1.0/identityGovernance/entitlementManagement/accessPackagesGET /v1.0/organization
GET /v1.0/domains
GET /v1.0/directoryRoles
GET /v1.0/subscribedSkus| Entra Portal Area | Likely Graph Root |
|---|---|
| Users / Groups | /users, /groups |
| Enterprise Apps | /servicePrincipals |
| App Registrations | /applications |
| Protection | /identity |
| Policies | /policies, /authenticationMethodsPolicy |
| Reports | /reports |
| Logs | /auditLogs |
- Identify the Entra blade (Users, Protection, Identity, Policies)
- Open Graph Explorer and start with
/beta - Inspect the response for
@odata.type - Validate properties in
$metadata - Confirm permissions in Graph Explorer
- Prefer
/v1.0for automation when available - Track beta β v1.0 promotion
- Open https://entra.microsoft.com
- Open Browser DevTools β Network
- Filter for
graph.microsoft.com - Navigate to the blade
- Copy the
GETrequest backing the UI - Paste into Graph Explorer or PowerShell
| Data Type | Permission |
|---|---|
| Users | User.Read.All |
| Groups | Group.Read.All |
| Directory | Directory.Read.All |
| Policies | Policy.Read.All |
| Auth Methods | AuthenticationMethod.Read.All |
| Logs | AuditLog.Read.All |
| Reports | Reports.Read.All |
- Most Entra innovation appears in /beta first
$metadatais always authoritative- Portal network calls reveal undocumented APIs
Audience: Entra ID engineers, identity architects, security engineers
Maintenance Tip: Review this document quarterly and diff /beta/$metadata for new resource types
This document explains what the Microsoft Graph $metadata endpoint is, how to read it, and how to translate metadata into practical OData query usage when working with Microsoft Entra (Azure AD) resources.
The $metadata endpoint exposes the entire service schema for Microsoft Graph using the OData v4 EDMX (Entity Data Model XML) format.
GET https://graph.microsoft.com/v1.0/$metadata
GET https://graph.microsoft.com/beta/$metadata
It describes:
- Entity types (users, groups, devices, etc.)
- Properties and their data types
- Navigation properties (relationships)
- Inheritance
- Collections vs singletons
- Actions and functions
Think of $metadata as the authoritative contract for Graph.
You use metadata to:
- Discover all properties (even undocumented ones)
- Understand relationships between resources
- Determine what can be selected, expanded, or filtered
- Build SDKs, schemas, or automation safely
- Explain why a query fails (unsupported filters/orderby)
The Entra Admin Center is built directly on this schema.
The metadata document is XML and follows this hierarchy:
Edmx
βββ DataServices
βββ Schema (Namespace="microsoft.graph")
βββ EntityType
βββ ComplexType
βββ EnumType
βββ EntityContainer
Each EntityType maps to a Graph resource.
<EntityType Name="user" BaseType="graph.directoryObject">
<Property Name="displayName" Type="Edm.String" />
<Property Name="accountEnabled" Type="Edm.Boolean" />
<Property Name="userPrincipalName" Type="Edm.String" />
<NavigationProperty Name="memberOf" Type="Collection(graph.directoryObject)" />
</EntityType>/users
/users/{id}
Every <Property> element is selectable.
<Property Name="displayName" Type="Edm.String" />GET /users?$select=id,displayNameIf it appears in metadata, it can be selected.
| EDM Type | Meaning | OData impact |
|---|---|---|
Edm.String |
Text | Filterable sometimes |
Edm.Boolean |
true/false | Often filterable |
Edm.DateTimeOffset |
Timestamp | Filterable & sortable |
Edm.Guid |
Object ID | Filterable |
Collection(...) |
Array | Limited filter support |
Navigation properties define relationships.
<NavigationProperty Name="memberOf" Type="Collection(graph.directoryObject)" />GET /users/{id}/memberOfor
GET /users/{id}?$expand=memberOf
β οΈ $expandis heavily restricted in Graph and often capped or blocked.
Many Entra objects inherit from directoryObject.
<EntityType Name="user" BaseType="graph.directoryObject" />This means users inherit:
iddeletedDateTime
Available to all directory objects.
The EntityContainer defines top-level Graph paths.
<EntityContainer Name="GraphService">
<EntitySet Name="users" EntityType="graph.user" />
</EntityContainer>Maps directly to:
/users
Metadata also defines callable operations.
<Action Name="assignLicense" IsBound="true">POST /users/{id}/assignLicenseIf it exists in metadata β it exists in Graph.
| Metadata element | OData feature |
|---|---|
| Property | $select, $filter |
| NavigationProperty | $expand, child endpoints |
| EntitySet | Root endpoint |
| EntityType | Resource schema |
| Action | POST operation |
| Function | GET operation |
Important limitation:
Metadata shows what exists β not what is indexed.
So even if a property exists:
$filtermay fail$orderbymay fail$expandmay be blocked
Example:
<Property Name="accountEnabled" Type="Edm.Boolean" />But:
$filter=accountEnabled eq true β
$orderby=accountEnabled βIndexing is a service-level decision, not metadata.
| Version | Purpose |
|---|---|
| v1.0 | Production-supported schema |
| beta | Preview, experimental, incomplete |
Always compare:
/v1.0/$metadata
/beta/$metadata
Beta often exposes:
- New authentication methods
- Passkey / FIDO2 extensions
- Governance features
- Inspect
$metadata - Identify EntityType
- Identify Properties & NavigationProperties
- Build
$selectfirst - Add
$filter - Assume client-side
$orderby - Follow
@odata.nextLink
$metadata= schema truth- OData = query language
- Graph = restricted OData implementation
- Portal = Graph + client-side logic
If you understand $metadata, you can:
- Predict Graph behavior
- Reverse engineer portal calls
- Avoid unsupported queries
- Build resilient Entra automation
This document explains how Microsoft Intune (device management) endpoints are modeled in Microsoft Graph, how to read the metadata, and how to safely use OData query options against Intune resources.
It is intentionally parallel to the Entra OData guide, but focused on:
deviceManagement/*- Intune-backed resources
- Intune-specific OData constraints
All Intune APIs live under the deviceManagement namespace in Microsoft Graph.
https://graph.microsoft.com/v1.0/deviceManagement
https://graph.microsoft.com/beta/deviceManagement
Unlike Entra directory objects, Intune data is service-backed, not directory-backed.
This distinction explains why:
$orderbyoften works in Intune$filteris more permissive$expandis still limited
GET https://graph.microsoft.com/v1.0/$metadata
GET https://graph.microsoft.com/beta/$metadata
Search within metadata for:
Namespace="microsoft.graph"
EntityType Name="managedDevice"
EntityType Name="deviceConfiguration"
All Intune entities are defined here.
| EntityType | Graph endpoint | Portal blade |
|---|---|---|
managedDevice |
/deviceManagement/managedDevices |
Devices β All devices |
deviceConfiguration |
/deviceManagement/deviceConfigurations |
Devices β Configuration profiles |
deviceCompliancePolicy |
/deviceManagement/deviceCompliancePolicies |
Devices β Compliance policies |
mobileApp |
/deviceManagement/mobileApps |
Apps β All apps |
deviceManagementScript |
/deviceManagement/deviceManagementScripts |
Devices β Scripts |
deviceHealthScript |
/deviceManagement/deviceHealthScripts |
Devices β Proactive remediations |
<EntityType Name="managedDevice">
<Property Name="id" Type="Edm.String" />
<Property Name="deviceName" Type="Edm.String" />
<Property Name="operatingSystem" Type="Edm.String" />
<Property Name="osVersion" Type="Edm.String" />
<Property Name="complianceState" Type="graph.complianceState" />
<Property Name="managementAgent" Type="graph.managementAgentType" />
<NavigationProperty Name="users" Type="Collection(graph.user)" />
</EntityType>Every <Property> is selectable.
GET /deviceManagement/managedDevices?
$select=id,deviceName,operatingSystem,complianceStateBest practice:
- Always
$select - Intune objects are large
Intune supports filtering on many properties.
GET /deviceManagement/managedDevices?
$filter=operatingSystem eq 'Windows'$filter=complianceState eq 'compliant'$filter=startswith(deviceName,'AVD')Enums (like complianceState) are defined in metadata as EnumType.
Unlike Entra directory objects, Intune supports server-side sorting.
GET /deviceManagement/managedDevices?
$orderby=deviceName asc- Property to be scalar
- No complex navigation expansion
Default page size is 100 (varies by endpoint).
"@odata.nextLink": "https://graph.microsoft.com/..."Rules:
- Always follow
nextLink - Never assume
$topreturns everything
Navigation properties define supported child routes.
<NavigationProperty Name="deviceCompliancePolicyStates"
Type="Collection(graph.deviceCompliancePolicyState)" />GET /deviceManagement/managedDevices/{id}/deviceCompliancePolicyStatesIntune strongly prefers child endpoints over $expand.
Some Intune resources support $expand, but many do not.
GET /deviceManagement/managedDevices?$expand=usersCommon outcomes:
- Partial expansion
- Throttling
- UnsupportedQuery errors
β‘οΈ Prefer separate calls.
Actions are POST operations defined in metadata.
<Action Name="syncDevice" IsBound="true" />POST /deviceManagement/managedDevices/{id}/syncDevicePortal buttons almost always map to actions.
Assignments are modeled as child collections, not properties.
GET /deviceManagement/mobileApps/{id}/assignmentsSame pattern for:
- Configuration profiles
- Compliance policies
- Scripts
| Version | Reality |
|---|---|
| v1.0 | Stable, lagging features |
| beta | Required for most new Intune features |
Examples only in beta:
- Endpoint Privilege Management
- Advanced reporting
- Some remediation APIs
| Issue | Cause |
|---|---|
| UnsupportedQuery | $expand or invalid filter |
| Throttling | Large tenant + no $select |
| Missing data | Not following nextLink |
| Enum filter fails | Wrong enum string |
GET /deviceManagement/managedDevices?
$select=id,deviceName,operatingSystem,complianceState
&$filter=operatingSystem eq 'Windows'
&$orderby=deviceNameThen:
- Page with
nextLink - Join related data client-side
| Aspect | Entra | Intune |
|---|---|---|
| Backend | Directory | Service DB |
$orderby |
Rare | Common |
$filter |
Restricted | Flexible |
$expand |
Limited | Very limited |
| Pagination | Required | Required |
- Intune Graph is OData-friendly but opinionated
- Metadata tells you what exists, not limits
- Prefer child endpoints over
$expand - Always
$selectand page
- Annotated metadata walkthrough for
managedDevice - Assignment model deep dive
- Portal blade β Graph β metadata mapping
- PowerShell SDK vs raw REST comparison
Understanding Intune metadata + OData gives you portal-level automation without guessing.
Example Usage
- Scopes required:
Pulling all powershell scripts from Intune using the API
https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts
https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts/{deviceManagementScript-id}$select=scriptContent
Here you would copy the script content from its base64 encoding into an editor
https://www.base64decode.org/
This would give you the content of the script for review
Working Example
https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts/c7cd4ba5-ccbf-4c9a-9be5-e22cda7379b0?$select=scriptContent
In Microsoft Graph, the ? indicates the start of query options for an HTTP request. Everything after ? modifies how data is returned, not what endpoint you are calling.
GET https://graph.microsoft.com/v1.0/users?$select=id,displayName/usersβ resource path (what you are querying)?β start of query string$selectβ OData query option
HTTP URLs follow a standard structure:
/path?queryKey=value&queryKey=value
In Microsoft Graph:
?starts the query section&chains multiple query options
GET /v1.0/users?$select=id,displayName,userPrincipalName&$top=10| Query Option | Purpose | Example |
|---|---|---|
$select |
Return specific properties | ?$select=id,displayName |
$filter |
Filter results | ?$filter=accountEnabled eq true |
$expand |
Include related objects | ?$expand=memberOf |
$top |
Limit results | ?$top=25 |
$orderby |
Sort results | ?$orderby=displayName |
$count |
Include count | ?$count=true |
GET /v1.0/usersReturns many default properties per user, resulting in a larger payload.
GET /v1.0/users?$select=id,displayName,userPrincipalNameReturns only the properties you explicitly request.
Benefits:
- Smaller response payloads
- Faster queries
- Clear, intentional documentation
-
$selectdoes not grant or change permissions -
Some properties:
- Require additional permissions
- Are not selectable on certain endpoints
-
$select=*is not supported in Microsoft Graph
/users β what data you are requesting
? β how the data should be returned
$select=prop β which fields are included
&$filter=... β which records are returned
### Example: Select Specific User Properties
```http
GET /v1.0/users?$select=id,displayName,userPrincipalNameDescription: Returns a list of users with only ID, display name, and user principal name.
Permissions Required:
User.Read.All
Notes:
- Use
$selectto reduce payload size - Combine with
$filterfor targeted queries
---
## π Summary
- `?` starts the query string in a Graph request
- `$select` controls which properties are returned
- Using `$select` improves performance and clarity
- Always pair `$select` with the minimum required permissions
---
**Audience**: Entra ID engineers, security engineers, Graph API consumers
**Recommended Use**: Internal documentation, team wikis, API reference guides
This document provides a concise reference for the main HTTP methods used in Microsoft Graph, their purposes, and behavior.
- Purpose: Retrieve data from a resource.
- Idempotent: β (safe to call multiple times without changing server state)
- Request Body: Not typically used
- Response: Returns the resource(s) in JSON format
Example:
GET /v1.0/users?$select=displayName,userPrincipalName- Purpose: Create a new resource or invoke an action.
- Idempotent: β (calling multiple times may create multiple resources)
- Request Body: Required, contains data for creation or action parameters
- Response: Returns the created resource or action result
Example:
POST /v1.0/groups
Content-Type: application/json
{
"displayName": "New Team",
"mailEnabled": false,
"mailNickname": "newteam",
"securityEnabled": true
}- Purpose: Replace an existing resource entirely.
- Idempotent: β (replacing the resource with the same data multiple times has no additional effect)
- Request Body: Required, must contain full resource representation
- Response: Usually returns
204 No Content
Example:
PUT /v1.0/groups/{id}
Content-Type: application/json
{
"displayName": "Updated Team Name",
"mailEnabled": false,
"mailNickname": "updatedteam",
"securityEnabled": true
}- Purpose: Update parts of an existing resource.
- Idempotent: β (updating the same properties with same values multiple times has no effect)
- Request Body: Contains only the fields to update
- Response: Usually returns
204 No Content
Example:
PATCH /v1.0/groups/{id}
Content-Type: application/json
{
"displayName": "Partially Updated Name"
}- Purpose: Remove a resource.
- Idempotent: β (deleting the same resource multiple times has no effect)
- Request Body: Not used
- Response: Usually returns
204 No Content
Example:
DELETE /v1.0/groups/{id}| Method | Purpose | Idempotent | Body Required | Response |
|---|---|---|---|---|
| GET | Retrieve resource(s) | β | No | JSON data |
| POST | Create resource / invoke action | β | Yes | Created resource / action result |
| PUT | Replace resource entirely | β | Yes | 204 No Content |
| PATCH | Update part of resource | β | Yes | 204 No Content |
| DELETE | Remove resource | β | No | 204 No Content |
Notes:
- Idempotent methods are safe for retries.
- POST is used for creation and actions that may have side effects.
- PATCH is preferred for partial updates to reduce payload and avoid overwriting unchanged properties.
- Always check required permissions for each operation in Microso






