Every click you make in Intune, Entra, or SharePoint translates into an API call behind the scenes. The Microsoft Graph API is the backbone of M365 automation—a REST-based interface that exposes almost everything in your tenant as a queryable resource. If you've ever exported a compliance report from the Intune portal and wondered how to do that programmatically at scale, this is where you start.

This guide is for IT practitioners managing SMB tenants who want to move beyond portal-clicking into real automation. No theory for theory's sake—just the tools, the auth concepts, and the query patterns you'll actually use.

The Right Toolset from Day One

Trying to learn the Graph API with nothing but a browser and PowerShell is slow and painful. Three tools remove most of that friction.

Graph X-Ray is the one to install first. It's a browser extension that hooks into your F12 developer tools. Click around in the M365 portal and Graph X-Ray surfaces the exact API calls happening in the background—including ready-to-copy code snippets in PowerShell, Python, or C#. It turns the portal itself into a learning environment.

Graph Explorer (developer.microsoft.com/graph/graph-explorer) is Microsoft's native sandbox. Use it to discover endpoints, check what permissions a specific query requires, and run one-off lookups without setting up any auth. Start here when exploring an unfamiliar part of the API.

Postman becomes relevant once you're building more complex workflows—organizing requests across multiple tenants, using environment variables, or sharing a collection with your team.

For scripting, the PowerShell SDK is the natural runtime. One concrete recommendation: know why Get-MgUser often looks like it is hiding data. Directory objects such as user and group return only a limited default property set when you read them—so either pass -Property on the SDK cmdlet (the equivalent of $select) or go direct with Invoke-MgGraphRequest, which also keeps scripts portable as the SDK evolves.

Authentication: Where Most Time Gets Lost

Graph API auth is where people get stuck, and it's worth understanding properly—it directly determines what your script or app is allowed to do.

Delegated access means the API acts on behalf of a signed-in user, bounded by that user's permissions. For interactive admin sessions in PowerShell, use the default interactive browser sign-in of Connect-MgGraph. Do not reach for device code flow, however convenient it looks when you juggle separate standard and privileged admin accounts: Microsoft classes it as a high-risk, phishing-prone flow and recommends blocking it wherever possible. Since 1 July 2026 security defaults block it in new tenants, and in existing tenants that have security defaults on—so a script built on it will simply stop working.

Application access means your script authenticates as an app registration—a service principal in Entra ID—independent of any user. This is the right model for automation. Credential handling matters here: client secrets are common but need secure storage (plain text in a script file is not acceptable), certificates are a step up, and Managed Identities are the preferred choice when running from Azure resources because there's no credential to manage at all.

Principle of Least Privilege applies directly: a service principal that reads Intune device compliance data does not need User.ReadWrite.All. Scope tightly. If something goes wrong, narrow permissions limit the blast radius. This aligns with the same Zero Trust principles you apply to user access.

REST Basics and What Actually Breaks

The Graph API uses standard HTTP verbs: GET to read, POST to create, PATCH to update, DELETE to remove. The response codes are precise—pay attention to them.

200 OK means it worked. 403 Forbidden means you authenticated successfully but access was denied anyway—this is the most common early blocker, and it has two causes people confuse. Either your app registration lacks the required API permission, or—in delegated flows—the signed-in user lacks the directory role for that resource even though the permission was granted. Check both before you go adding scopes.

Permissions in Graph are explicit: declared on the app registration and then consented to. Application permissions always require admin consent. Delegated permissions may be consentable by the user for their own data—unless the permission itself is flagged as requiring admin consent (User.Read.All, for example), or your tenant's consent policy restricts user consent.

429 Too Many Requests means you're being throttled. Honour the Retry-After response header—wait exactly that many seconds and retry, which is the fastest way back. Fall back to exponential backoff only when no such header is present.

Query Patterns for Large Datasets

For anything beyond a handful of records, these four patterns matter and skipping them will cause silent data loss or unnecessary API load.

Pagination — there is no global page size. Different APIs have different defaults and maximums: GET /users, for example, returns 100 by default and at most 999 with $top (500 when signInActivity is involved). So never hard-code a number. When more records exist, the response includes @odata.nextLink with the URL for the next page—use that URL unchanged rather than picking the $skiptoken out of it, and loop until it's absent. Missing this means missing data, with no error to tell you. Watch one trap: your own headers, ConsistencyLevel among them, are not carried over to follow-up pages automatically.

Filtering ($filter) — Move filter logic to the API, not your script. If you need users in a specific department or devices with a particular compliance state, specify it in the query. Less data transferred, faster results. Some directory queries only work with the header ConsistencyLevel: eventual plus $count=true—that's the advanced query capability on directory objects.

Field selection ($select) — Request exactly the properties you need. $select=id,displayName,jobTitle returns those three fields and nothing else. The flip side matters just as much: directory objects like user and group return only a limited default property set, so $select is also how you get anything beyond that default.

Batching ($batch) — Up to 20 individual requests can be combined into a single POST to the /$batch endpoint. Useful for bulk reads instead of 20 sequential calls. Don't count on parallelism, though: without dependsOn the service is free to choose the order, for Outlook it forwards at most four requests of a batch at a time, and each request still counts individually against the throttling limits. A batch can come back 200 OK and still contain individual 429s, which nothing retries for you.

Where This Becomes Concrete

Tenant-to-tenant migration of Intune configuration profiles is one of the clearest examples—not a documented Microsoft procedure, but one I use in practice. Export a profile as JSON, strip the tenant-specific identifiers, POST it into the target tenant. That's a script, not a manual portal cycle. It integrates into a CI/CD pipeline once the service principal is configured.

Bulk account provisioning is another. Onboarding contractors, creating temporary project accounts, or running deprovision workflows triggered by HR data—all of these are Graph API calls wrapped in a script. The portal cannot do this at scale without significant manual effort and human error risk.

Where to Go Next

The Graph API documentation at learn.microsoft.com is comprehensive. Use it as a reference, not a tutorial to read sequentially. Graph X-Ray and Graph Explorer together will teach you more in an afternoon of actual work than any documentation read-through.

Start narrow: read device compliance data from Intune into a report. Get auth working cleanly, handle pagination, and build from there. The patterns repeat across every part of the API.

Frequently Asked Questions

What is the Microsoft Graph API used for?

The Microsoft Graph API is a unified REST endpoint that exposes data and actions across Microsoft 365 services—Entra ID, Intune, Exchange, SharePoint, Teams, and more. IT teams use it to automate tenant management, pull compliance reports, provision users at scale, and integrate M365 data into custom workflows without clicking through portals.

Do I need coding experience to use the Graph API?

Basic PowerShell is enough to get started. Tools like Graph Explorer let you run queries interactively with no code at all, and Graph X-Ray shows you the exact API calls the M365 portal makes. From there, wrapping calls in a PowerShell script with Invoke-MgGraphRequest is a natural next step—not a leap into software development.

What permissions does my app registration need?

It depends entirely on what you're querying. Each Graph API endpoint lists its required permissions in the documentation. Start with the narrowest scope possible—for example, DeviceManagementManagedDevices.Read.All to read Intune device data. Application permissions require admin consent; delegated permissions are bounded by the signed-in user's role. Scope tightly and review regularly.

Questions about Graph API integration or M365 automation for your MSP environment? Get in touch.