In the modern Microsoft 365 landscape, the “Portal-Clicker” is being replaced by the “Automation Architect.” Microsoft Graph is the engine behind this transformation. While legacy modules like AzureAD or MSOnline were siloed, Graph provides a single endpoint, a single authentication model, and a single data schema.
Get-MgUser -UserId "[email protected]" is actually a GET request to https://graph.microsoft.com/v1.0/users/[email protected].
1. Professional Setup & API Profiles
Before scripting, you must decide which API version to target. The SDK supports v1.0 (Production-ready) and Beta (latest preview features like Sign-in logs or specialized Teams settings).
# Switch to Beta for advanced features
Select-MgProfile -Name "beta"
# Connect with specific permissions (Scopes)
Connect-MgGraph -Scopes "User.Read.All", "Group.ReadWrite.All", "Mail.Read", "Sites.Read.All"
2. Unattended Automation (App-Only Auth)
For background tasks (Azure Automation, Task Scheduler), interactive logins are impossible. You must use an App Registration with a certificate for maximum security.
$params = @{
ClientId = "YOUR_APP_ID_GUID"
TenantId = "YOUR_TENANT_ID"
CertificateThumbprint = "A1B2C3D4E5F6G7H8I9J0"
}
Connect-MgGraph @params
3. Service Deep-Dives: Read & Write
A. Entra ID: OData Filtering Mastery
A true deep dive requires moving beyond Where-Object. Filter at the source to prevent script lag and memory exhaustion.
# Efficient: Server-side filtering for active Finance users
$Filter = "Department eq 'Finance' and AccountEnabled eq true"
$Users = Get-MgUser -Filter $Filter -All -Property "Id", "DisplayName", "JobTitle"
B. Microsoft Teams: Resource Provisioning
Creating a Team is a multi-step process. In Graph, you often create a Group first and then “Team-enable” it.
$teamBody = @{
DisplayName = "New Project Team"
"[email protected]" = "https://graph.microsoft.com/v1.0/teamsTemplates('standard')"
}
New-MgTeam -BodyParameter $teamBody
C. SharePoint & OneDrive: The “Drive” Logic
SharePoint Sites contain Drives (Document Libraries), which contain DriveItems (Files/Folders).
# Search for a site and list its library root
$Site = Get-MgSite -Search "Marketing"
Get-MgSiteDriveItem -SiteId $Site.Id -DriveId (Get-MgSiteDrive -SiteId $Site.Id).Id
4. Advanced Query Parameters
To optimize performance, use -ExpandProperty to join related data into a single request, avoiding multiple round-trips.
# Fetch user AND their manager in one call
$User = Get-MgUser -UserId "[email protected]" -ExpandProperty "manager"
$ManagerMail = $User.Manager.AdditionalProperties["mail"]
5. JSON Batching: Combining 20 Requests
Batching allows you to group up to 20 individual API calls into a single HTTP POST. This is essential for high-speed synchronization tools.
$batchRequest = @{
requests = @(
@{ id = "1"; method = "GET"; url = "/users/[email protected]" },
@{ id = "2"; method = "GET"; url = "/users/[email protected]" }
)
}
$BatchResult = Invoke-MgGraphRequest -Method POST -Uri "https://graph.microsoft.com/v1.0/`$batch" -Body $batchRequest
6. Delta Queries: Tracking Changes
Instead of scanning 50,000 users every hour, use **Delta Queries** to only pull objects that were created, updated, or deleted since your last sync.
# Initial sync gets the deltaLink
$Delta = Get-MgUserDelta
$SyncToken = $Delta.AdditionalProperties["@odata.deltaLink"]
# Future runs use the $SyncToken to fetch ONLY changes
$Changes = Invoke-MgGraphRequest -Method GET -Uri $SyncToken
7. Expert Error Handling
Graph errors are JSON objects. A professional script parses these to understand if a failure was due to a missing resource (404) or throttling (429).
try {
Update-MgUser -UserId "ghost-id" -Department "IT"
} catch {
$Err = $_.Exception.Message | ConvertFrom-Json -ErrorAction SilentlyContinue
Write-Error "Code: $($Err.error.code) - Message: $($Err.error.message)"
}
Summary Checklist
| Scenario | Best Practice |
|---|---|
| Large Data Sets | Use -All and -Filter. Avoid Where-Object. |
| Security | Use Certificates for Auth; use Least Privilege Scopes. |
| Speed | Use -ExpandProperty and $batch. |
| Troubleshooting | Append -Debug to see raw HTTP traffic. |















































































































































































































































