WYRE-AI/msp-claude-plugins/msp-claude-plugins/m365/m365/skills/api-patterns/SKILL.md
Microsoft 365 API Patterns
Microsoft Graph fundamentals shared by every M365 skill: Entra token scopes and the per-request Bearer model, OData query operators and filter syntax, @odata.nextLink pagination, delta queries for incremental sync, 429 throttling and retry behavior, JSON batching, and the common Graph error codes.
- Source repository stars
- 42
- Declared platforms
- 0
- Static risk flags
- 1
- Last source update
- 2026-08-28
- Source checked
- 2026-08-28
Decision brief
What it does: where it fits
Microsoft Graph fundamentals shared by every M365 skill: Entra token scopes and the per-request Bearer model, OData query operators and filter syntax, @odata. nextLink pagination, delta queries for incremental sync, 429 throttling and retry behavior, JSON batching, and the common Graph error codes.
Not for
- Tasks that require unconfirmed production actions or broad system permissions.
- Environments where the pinned source and install steps cannot be inspected.
Compatibility matrix
Platform support, with evidence labels
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
Inspect first. Install second.
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/WYRE-AI/msp-claude-plugins --skill "msp-claude-plugins/m365/m365/skills/api-patterns"Inspect the Agent Skill "Microsoft 365 API Patterns" from https://github.com/WYRE-AI/msp-claude-plugins/blob/5005f73ba2f52cd299f58aa6bb79f4e70ae87103/msp-claude-plugins/m365/m365/skills/api-patterns/SKILL.md at commit 5005f73ba2f52cd299f58aa6bb79f4e70ae87103. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
What the source asks the agent to do
- 01
Anti-triggers
This skill teaches you to compose Graph calls by hand. Two neighbouring plugins cover the same tenant with almost identical vocabulary, and choosing the wrong one is the most common routing mistake in the Microsoft estate:
A read-only question about one tenant — "how many users", "whoAnything spanning more than one customer tenant — fleet-wideA tenant that authenticates but returns nothing — that is an app - 02
Authentication
The Softeria MS-365 MCP server (--org-mode) accepts a Bearer token per request via the Authorization header. The token must be obtained from Microsoft Entra using the common endpoint (multi-tenant) with the following scopes:
The Softeria MS-365 MCP server (--org-mode) accepts a Bearer token per request via the Authorization header. The token must be obtained from Microsoft Entra using the common endpoint (multi-tenant) with the following sc…All Graph API calls use:Beta features (preview, subject to change): - 03
Token Scope for MSP Operations
The Softeria MS-365 MCP server (--org-mode) accepts a Bearer token per request via the Authorization header. The token must be obtained from Microsoft Entra using the common endpoint (multi-tenant) with the following scopes:
The Softeria MS-365 MCP server (--org-mode) accepts a Bearer token per request via the Authorization header. The token must be obtained from Microsoft Entra using the common endpoint (multi-tenant) with the following sc… - 04
Base URL
All Graph API calls use:
All Graph API calls use:Beta features (preview, subject to change): - 05
OData Query Parameters
Some filters require the ConsistencyLevel: eventual header and $count=true:
Some filters require the ConsistencyLevel: eventual header and $count=true:
Permission review
Static risk signals and limitations
Network access
The documentation includes network, browsing, or remote request actions.
https://graph.microsoft.com/v1.0/Network access
The documentation includes network, browsing, or remote request actions.
https://graph.microsoft.com/beta/Evidence record
Why each signal appears
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 94/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 42 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Provenance and original SKILL.md
- Repository
- WYRE-AI/msp-claude-plugins
- Skill path
- msp-claude-plugins/m365/m365/skills/api-patterns/SKILL.md
- Commit
- 5005f73ba2f52cd299f58aa6bb79f4e70ae87103
- License
- Apache-2.0
- Collected
- 2026-08-28
- Default branch
- main
View the original SKILL.md
Microsoft Graph API Patterns
Overview
Microsoft Graph is the unified REST API surface for all M365 services (users, mail, calendar, Teams, OneDrive, security). All M365 MCP tools ultimately make Graph calls. Understanding Graph's OData query syntax, pagination model, throttling behavior, and auth patterns is essential for building reliable M365 workflows.
Anti-triggers
This skill teaches you to compose Graph calls by hand. Two neighbouring plugins cover the same tenant with almost identical vocabulary, and choosing the wrong one is the most common routing mistake in the Microsoft estate:
- A read-only question about one tenant — "how many users", "who
has no MFA registered", "which licences are unassigned". The Graph
Enterprise MCP answers these from a vetted query catalogue, so nobody
hand-writes a
$filter; use themicrosoft-graphplugin'smicrosoft-graph-queryingskill. Hand-writing a Graph URL when that server is connected is the exact error pattern it exists to prevent. - Anything spanning more than one customer tenant — fleet-wide
standards, BPA drift, GDAP, or a packaged action such as offboard /
reset MFA / revoke sessions. Use the
cippplugin, which carries the multi-tenant scope and per-tenant audit trail this plugin does not. - A tenant that authenticates but returns nothing — that is an app
registration and admin-consent problem, not a query-syntax problem;
use
microsoft-graph-connection.
The short rule: ask one tenant → microsoft-graph; change one tenant
→ this plugin; do either across the fleet → cipp.
Authentication
Token Scope for MSP Operations
The Softeria MS-365 MCP server (--org-mode) accepts a Bearer token per request via the Authorization header. The token must be obtained from Microsoft Entra using the common endpoint (multi-tenant) with the following scopes:
| Scope | Purpose |
|---|---|
https://graph.microsoft.com/.default | All Graph permissions granted to app |
openid | ID token for tenant ID extraction |
profile | User profile claims |
offline_access | Refresh token for session persistence |
Base URL
All Graph API calls use:
https://graph.microsoft.com/v1.0/
Beta features (preview, subject to change):
https://graph.microsoft.com/beta/
OData Query Parameters
| Parameter | Purpose | Example |
|---|---|---|
$select | Return only specified fields | $select=id,displayName,email |
$filter | Filter results | $filter=accountEnabled eq true |
$search | Full-text search (mailboxes, users) | $search="displayName:Smith" |
$orderby | Sort results | $orderby=displayName asc |
$top | Limit results per page | $top=100 |
$skip | Skip N results | $skip=100 |
$count | Include total count | $count=true |
$expand | Include related entities | $expand=manager |
Filter Syntax
eq equal $filter=accountEnabled eq true
ne not equal $filter=jobTitle ne 'Manager'
gt/lt greater/less $filter=createdDateTime gt 2024-01-01T00:00:00Z
ge/le >=, <= same but inclusive
and/or logical $filter=dept eq 'IT' and accountEnabled eq true
not negation $filter=not startsWith(mail,'test')
startsWith prefix match $filter=startsWith(displayName,'J')
endsWith suffix match $filter=endsWith(mail,'@contoso.com')
contains substring $filter=contains(jobTitle,'Manager')
any/all collection ops $filter=assignedLicenses/any(x:x/skuId eq '<guid>')
Advanced Queries (Require ConsistencyLevel: eventual)
Some filters require the ConsistencyLevel: eventual header and $count=true:
GET /v1.0/users?$filter=assignedLicenses/$count eq 0&$count=true&ConsistencyLevel: eventual
Pagination
Graph uses server-side pagination. Always check for @odata.nextLink in responses.
Standard Pagination Loop
1. Make initial request with $top=100
2. If response contains @odata.nextLink → follow it
3. Repeat until no @odata.nextLink
Response with more pages:
{
"@odata.context": "...",
"@odata.nextLink": "https://graph.microsoft.com/v1.0/users?$skiptoken=abc123",
"value": [...]
}
Response — last page:
{
"@odata.context": "...",
"value": [...]
}
The Softeria MCP server handles pagination automatically for supported operations.
Delta Queries (Incremental Sync)
Delta queries return only changed items since the last sync — ideal for regular polling.
Initial Delta Request
GET /v1.0/users/delta?$select=id,displayName,userPrincipalName,accountEnabled
Response includes a @odata.deltaLink after the last page — store this.
Subsequent Delta Requests
GET {deltaLink}
Returns only users added, modified, or deleted since the delta token was issued. Deleted users have "@removed": { "reason": "deleted" } in the response.
Throttling and Retry
Graph throttles requests at both per-app and per-tenant levels. Throttled responses return 429 Too Many Requests.
Retry-After Header
Always check the Retry-After header on 429:
HTTP/1.1 429 Too Many Requests
Retry-After: 15
Wait the specified seconds before retrying.
Graph Throttle Limits (Approximate)
| Resource | Limit |
|---|---|
| Per app per tenant | 10,000 req/10 min |
| Per user | 3,000 req/10 min |
| Mail search | 10 concurrent |
| Reports | 1 req/15 min per report |
Best Practices
- Use
$selectto request only needed fields (reduces payload + throttle pressure) - Use
$filterserver-side rather than fetching all and filtering in code - Use delta queries for sync operations instead of polling all items
- Batch unrelated requests (see below) to reduce round-trips
Batch Requests
Combine up to 20 independent Graph calls into one HTTP request:
POST /v1.0/$batch
Content-Type: application/json
{
"requests": [
{
"id": "1",
"method": "GET",
"url": "/users/[email protected]?$select=displayName,accountEnabled"
},
{
"id": "2",
"method": "GET",
"url": "/users/[email protected]?$select=displayName,accountEnabled"
}
]
}
Response:
{
"responses": [
{ "id": "1", "status": 200, "body": { "displayName": "Alice", "accountEnabled": true } },
{ "id": "2", "status": 200, "body": { "displayName": "Bob", "accountEnabled": false } }
]
}
Use for fetching details on multiple known user IDs simultaneously.
Common Error Codes
| HTTP | Code | Meaning | Fix |
|---|---|---|---|
| 400 | Request_BadRequest | Malformed OData filter | Check filter syntax |
| 401 | InvalidAuthenticationToken | Token expired or malformed | Re-authenticate |
| 403 | Authorization_RequestDenied | Missing Graph permission | Add scope, re-consent |
| 404 | Request_ResourceNotFound | Object doesn't exist | Check GUID/UPN |
| 429 | ActivityLimitReached | Throttled | Wait Retry-After seconds |
| 500 | ServiceInternalServerError | Graph outage | Retry with backoff |
| 503 | ServiceUnavailable | Transient | Retry with backoff |
Useful Graph Explorer
For testing queries interactively: https://developer.microsoft.com/graph/graph-explorer
Log in with a test M365 account to explore API responses before writing code.
Related Skills
- M365 Users - User query examples
- M365 Security - Audit log query patterns
- M365 Mailboxes - Search and KQL syntax
Frequently asked questions
What to verify before installation and use
What does the Microsoft 365 API Patterns source document cover?
Microsoft Graph fundamentals shared by every M365 skill: Entra token scopes and the per-request Bearer model, OData query operators and filter syntax, @odata. nextLink pagination, delta queries for incremental sync, 429 throttling and retry behavior, JSON batching, and the common Graph error codes.
How do I install Microsoft 365 API Patterns?
The source record exposes this install command: npx skills add https://github.com/WYRE-AI/msp-claude-plugins --skill "msp-claude-plugins/m365/m365/skills/api-patterns". Inspect the command and pinned source before running it.
Which permission-related actions were detected?
Static rules flagged network in the source; the page lists the matching lines and excerpts.
Alternatives
Compare before choosing
garrytan/gbrain
bulk-ingestion
End-to-end discipline for turning any large data source (audio libraries, email takeouts, document corpora, chat exports, API dumps) into brain pages at scale. The lifecycle spine: SCHEMA → ACCESS → TRIAL → EVALUATE → IMPROVE → CODIFY → TEST → SKILLIFY → BULK → MONITOR. State is tracked in a durable JSON manifest (see MANIFEST-PATTERN.md) so any crash, session boundary, or subagent fan-out resumes from ground truth instead of memory.
alirezarezvani/claude-skills
app-store-optimization
App Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklist
dotnet/skills
migrate-vstest-to-mtp
Migrates .NET test projects from VSTest to Microsoft.Testing.Platform (MTP). Use when user asks to "migrate to MTP", "switch from VSTest", "enable Microsoft.Testing.Platform", "use MTP runner", set OutputType=Exe only for test projects in Directory.Build.props, or mentions EnableMSTestRunner, EnableNUnitRunner, or UseMicrosoftTestingPlatformRunner. USE FOR: MTP behavioral differences vs VSTest (exit code 8, zero tests discovered, --ignore-exit-code, TESTINGPLATFORM_EXITCODE_IGNORE); centralizing
oaustegard/claude-skills
featuring
Generate hierarchical _FEATURES.md files that describe what a codebase DOES from a user/consumer perspective, anchored to source symbols via tree-sitting. Supports large complex codebases through feature-driven decomposition into sub-feature files. Uses a multi-pass synthesis: orientation → detail → overview rewrite. Use when someone says "what does this do", "document features", "feature inventory", "_FEATURES.md", or needs to understand a codebase's purpose before modifying it. Complements tre