Microsoft Graph 403 or 429? One's a consent problem, the other has a Retry-After you must honor
Microsoft Graph returns a 403 or a 429, and the difference matters enormously: one you fix with permissions, the other you fix by waiting exactly as long as Graph tells you. Retrying the wrong one wastes attempts or gets you throttled harder.
403 is consent, not throttling
A 403 Authorization_RequestDenied means your app lacks the required permission — a missing Graph scope (delegated vs application), un-consented admin permission, or a conditional-access block. Retrying never fixes a 403. Add the scope and admin-consent it. A 404 can also mean a permission is hiding the resource, not that it's missing.
429 has a mandatory Retry-After
A 429 is throttling and comes with a mandatory Retry-After header — honor it exactly, don't substitute your own backoff guess. If it's 429_AppResourceUnitDaily, you've hit a per-app daily quota (spread load or request more). Batch with $batch to reduce throttling.
Two more Graph quirks: newly-granted permissions propagate asynchronously, so a 401/403 right after a grant may resolve on its own in minutes. And a 429 can even accompany a successful write on some Outlook endpoints — check the response, don't assume the 429 means it failed.
Snapback's microsoft-graph family separates the consent-fix from the honor-Retry-After path so an agent doesn't retry a 403 forever or ignore the wait on a 429.
Machine-readable guide: https://snapback.sh/llms.txt · Tool discovery: https://snapback.sh/.well-known/mcp.json · MCP endpoint: https://api.snapback.sh/mcp. Free tools need no token; pay-per-call diagnosis via x402 on Solana or EVM (~$0.0032 USDC).