The 403 You Get When You Do Everything Right
You have done everything right. You registered an app in Microsoft Entra ID, assigned permissions, and received admin consent. You call the Retrieval API from your background service — the same kind of service that calls dozens of other Microsoft Graph endpoints every day — and you get a 403 Forbidden.
No misconfigured scope. No missing consent. Your service principal is valid. The request is well-formed. Yet the response is still a 403.
The root cause is not a configuration error. The Retrieval API does not support application permissions. Neither does the Search API. These AI-powered surfaces are delegated-only — they must be called on behalf of a signed-in user with a real user identity in the token. This is a deliberate design constraint: Copilot’s permission-trimmed retrieval respects the user’s own access boundaries, and those boundaries cannot be evaluated without a user context in the request.
This is the first wall developers hit when building Copilot API integrations. It is not the only one.
Note: If your tenant operates on GCC-High or DoD, all AI-powered Copilot APIs are currently unavailable. Verify availability against the official national cloud deployments page before proceeding with roadmap planning.
This post maps out the auth model, permission scopes, app registration choices, and SDK options before you write your first integration call. It is a decision-support guide — not a tutorial. If you have not read Post 01 yet, it establishes what Copilot APIs are, where they live under graph.microsoft.com, and which surfaces are GA versus preview. This post assumes that foundation and builds on it.
After reading this post, you will be able to:
- ✅ Select the correct auth flow (delegated, app-only, or On-Behalf-Of) for your specific Copilot API integration scenario
- ✅ Configure your Entra ID app registration with the right credential type,
signInAudience, and token acquisition pattern - ✅ Request the least-privileged permissions per API surface using the complete scope reference in this post
- ✅ Pass the pre-go-live readiness checklist for auth, permissions, and credentials before your first production deployment
The Auth Model You Know — and the Four Constraints That Break It
Copilot APIs use the same authentication infrastructure as every other Microsoft Graph API. If you have integrated with Graph before, the fundamentals are identical:
- Microsoft Entra ID (formerly Azure AD) handles identity and token issuance
- MSAL-issued Bearer tokens are passed in the
Authorization: Bearer {token}header on every request - The same app registration in the Microsoft Entra admin center is used — there is no separate Copilot registration portal
- The same consent framework applies — scopes are listed in the Microsoft Graph permissions catalog, and the same
/adminconsentendpoint grants them - The same Graph SDK works — the
@microsoft/microsoft-graph-client,Microsoft.GraphNuGet package, and their counterparts in Go, Java, Python, PHP, and PowerShell all support Copilot API endpoints
What is different is concentrated in four constraints that break common Graph integration assumptions:
What IS different about Copilot APIs:
These four constraints are not edge cases — they affect the most common enterprise integration patterns. The rest of this post unpacks each one.
💡 Insight: The delegated-only restriction on Retrieval and Search is not a temporary preview limitation. It is an intentional design choice: the AI retrieval engine enforces the user’s own file and site permissions. There is no admin override that bypasses this — if you need background retrieval without a user context, use the AI Interactions Change Notifications (tenant-wide) or Teams Export APIs instead.
What this means for you: If your integration architecture assumes a service principal can call AI-powered retrieval, redesign the auth layer now — before you build anything else.
Which Permission Gets You Which API: The Complete Scope Reference
Use this section as a reference each time you start a new Copilot API integration. For each API surface, the table below shows whether delegated, application (app-only), or both access types are supported — including the least-privileged scope and whether admin consent is required.
The table below is the primary reference deliverable of this post. Per-API nuances that require more than a table cell are covered in the subsections immediately after.
| API Surface | Status | Delegated (Work/School) | Application | Admin Consent | Key Note |
|---|---|---|---|---|---|
| Retrieval API | GA (v1.0 + beta) | ✅ Files.Read.All + Sites.Read.All | ❌ Not supported | Yes | Both scopes required together for SharePoint/OneDrive content |
| Search API | ⚠️ PREVIEW (beta only) | ✅ Files.Read.All + Sites.Read.All | ❌ Not supported | Yes | Not supported in production; beta only |
| Chat API | ⚠️ PREVIEW (beta only) | ✅ Delegated confirmed | ❓ Unconfirmed | Yes | Specific scope names unverified at research time — see note below |
| AI Interactions Change Notifications (per-user) | GA (v1.0) | ✅ AiEnterpriseInteraction.Read | ✅ AiEnterpriseInteraction.Read.User (RSC) | Yes | RSC permission; user must have Copilot Chat service plan |
| AI Interactions Change Notifications (tenant-wide) | GA (v1.0) | ❌ Not supported | ✅ AiEnterpriseInteraction.Read.All | Yes | All 6 Copilot service plan IDs required on tenant |
| AI Insights Change Notifications | ⚠️ PREVIEW (beta only) | ✅ (see note) | ✅ (see note) | Yes | Specific scope names unverified at research time — refer to API reference page |
| Meeting Insights (aiInsights) | GA (v1.0 + beta) | ✅ OnlineMeetingAiInsight.Read.All | ✅ OnlineMeetingAiInsight.Read.All | Yes | App-only requires an application access policy in addition to consent |
| Interaction Export API | GA (Teams Export) | ❌ Not supported | ✅ Chat.Read.All, ChannelMessage.Read.All, User.Read.All | Yes | Protected APIs; app-only only |
| Copilot Usage Reports | GA (v1.0 + beta) | ✅ Reports.Read.All | ✅ Reports.Read.All | Yes | Delegated also requires a specific admin role assigned to signed-in user |
(Post 06 covers the Retrieval API in depth. Post 07 covers the Search API. Post 09 covers Meeting Insights.)
Permission Nuances by API Surface
Retrieval API — Two scopes required, not one
The most common mistake when requesting Retrieval API access is requesting only Files.Read.All. Both Files.Read.All AND Sites.Read.All are required together to retrieve SharePoint and OneDrive content. For Copilot Connectors content, use ExternalItem.Read.All instead. Neither scope alone is sufficient.
✅ Quick win: Before you request admin consent, check whether both
Files.Read.AllandSites.Read.Allare in your app registration’s API permissions list. If only one is present, the Retrieval API will return a 403 regardless of how the consent was granted.
Search API — ⚠️ PREVIEW: Beta endpoint only
⚠️ PREVIEW: The Search API is available only on the
/betaendpoint (https://graph.microsoft.com/beta/copilot/search). It must not be used in production applications. Use the/v1.0Retrieval API for production semantic retrieval scenarios.
Chat API — ⚠️ PREVIEW: Permission scopes unverified
⚠️ PREVIEW: The Chat API is beta-only. Delegated flow is confirmed. The specific permission scope names required could not be verified from accessible documentation at research time (reference pages returned 404 — see research.md §8.1). Whether application permissions are supported is also unconfirmed (§8.2). Refer to the current API reference page for the exact scopes before requesting consent.
AI Insights Change Notifications — ⚠️ PREVIEW: Scope names unverified
⚠️ PREVIEW: AI Insights Change Notifications is a beta-only surface. The specific permission scopes could not be verified at research time (§8.3). Refer to the current API reference page for scope names before registering a subscription.
Meeting Insights — Application access policy is mandatory for app-only
Granting OnlineMeetingAiInsight.Read.All as an application permission is not sufficient on its own. Tenant administrators must also create an application access policy and grant it to the specific users whose meeting insights the application needs to access. Standard application role consent alone will not work. See the Allow applications to access online meetings on behalf of a user documentation for setup instructions.
Copilot Usage Reports — Admin role is required for delegated access
The Reports.Read.All scope is necessary but not sufficient for delegated Usage Reports access. The signed-in user must also hold one of the following admin roles: Company Administrator, AI Administrator, Exchange Administrator, SharePoint Administrator, Lync Administrator, Teams Service Administrator, Teams Communications Administrator, Global Reader, Usage Summary Reports Reader, or Reports Reader. Scope and role are both required.
What this means for you: Pull the Master Permission Table before every new integration — the combination requirements and admin consent flags change per API surface, and a single missing scope or role will produce a 403 with no obvious error message pointing to the gap.
App Registration: One Portal, One Resource, Three Credential Choices
No Separate Registration Portal
There is no Copilot-specific app registration portal or distinct identity infrastructure. You use the Microsoft Entra admin center — the same registration you would create for any Microsoft Graph integration. Copilot API permissions appear in the standard Microsoft Graph permissions catalog under API permissions.
All Copilot API permissions are registered under the Microsoft Graph resource (https://graph.microsoft.com) — not a separate Copilot resource. When acquiring tokens, the audience is the standard Graph application ID (00000003-0000-0000-c000-000000000000).
App Registration Setup — Four Steps
Step 1 — Register the app
Navigate to the Microsoft Entra admin center → Identity → Applications → App registrations → New registration. Name the app and set a redirect URI if your integration uses delegated (user-interactive) flows. Daemon/background app-only flows do not require a redirect URI.
Step 2 — Set signInAudience to work/school accounts only
Set signInAudience to work/school accounts only (AzureADMyOrg for single-tenant, AzureADMultipleOrgs for multi-tenant). Personal Microsoft accounts are rejected by every Copilot API. Selecting “personal accounts” during registration will not cause a visible error at registration time — it will fail silently at runtime when users authenticate.
Step 3 — Choose credential type
See the table below to select the correct credential for your deployment stage.
| Credential Type | When to Use | Security Posture | Notes |
|---|---|---|---|
| Client Secret | Development and testing only | ⚠️ Lower — secret can leak if exposed | Max lifetime: 24 months. Microsoft recommends < 12 months. Rotate before expiry. |
| Certificate | Production server-side apps | ✅ Recommended — public key uploaded to Entra, private key stays local | X.509 certificate; supports automated rotation with Azure Key Vault |
| Federated Identity Credential | GitHub Actions, Azure workloads, Kubernetes | ✅ Recommended — no secret to manage | Uses external OIDC tokens; no stored credential in Entra; best for CI/CD and cloud-native workloads |
For production Copilot API integrations, migrate away from client secrets. If your deployment uses GitHub Actions or runs on Azure infrastructure, federated identity credentials eliminate secret rotation entirely.
Step 4 — Configure token acquisition
Use the endpoints below based on your auth flow. For delegated flows, list the explicit scopes your integration needs. For app-only flows, always use .default — it requests all pre-consented application permissions and individual scope names are not valid in the client credentials request.
Delegated flow (user interactive — Auth Code grant):
POST https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/tokenContent-Type: application/x-www-form-urlencodedclient_id={clientId}&client_secret={secret}&grant_type=authorization_code&code={auth_code}&redirect_uri={redirect_uri}&scope=Files.Read.All Sites.Read.All
App-only flow (Client Credentials grant):
POST https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/tokenContent-Type: application/x-www-form-urlencodedclient_id={clientId}&client_secret={secret}&grant_type=client_credentials&scope=https://graph.microsoft.com/.default
💡 Insight: The
.defaultscope for app-only flows is not a shortcut — it is the required format. Passing individual permission names in a client credentials request will fail. The.defaultsuffix on the Graph resource URI is how the identity platform signals “give me all pre-consented application permissions for this app.”
What this means for you: Complete Steps 1–4 once per integration project and document your credential type decision — migrating from client secret to certificate in production is possible but requires a deployment window, so choosing the right type at registration time saves a future change.
Four Integration Scenarios, Four Auth Flows — and the One Constraint That Rules Them All

Alt text: Decision tree mapping four integration scenarios — user-facing app, SPA, web API, background service — to their recommended OAuth 2.0 flows and supported Copilot API surfaces
The four most common Copilot API integration scenarios each map to a distinct auth flow. Choosing the wrong flow is the primary source of 403 errors and dead-end integration designs.
The table below maps each scenario to its recommended flow and the Copilot API surfaces that flow can reach.
Auth Flow Scenario Table
| Scenario | Recommended Flow | Auth Type | Supported Copilot APIs |
|---|---|---|---|
| User-facing web app calling Retrieval, Search, or Chat | Authorization Code + PKCE (for SPA) | Delegated | Retrieval, Search ⚠️, Chat ⚠️ |
| Web API acting on behalf of a signed-in user | On-Behalf-Of (OBO) | Delegated | Retrieval, Search ⚠️, Meeting Insights |
| Background compliance or export service (no user context) | Client Credentials | Application (app-only) | AI Interactions Export, Meeting Insights (with policy), Usage Reports |
| Admin or reporting dashboard | Client Credentials or Auth Code with admin role | Application or Delegated | Usage Reports, Copilot Policy Settings |
The constraint that rules the table: Retrieval, Search, and Chat cannot appear in any app-only row. These surfaces require a real user identity in the token. For background services that need AI-powered retrieval, there is no direct workaround — you must use delegated flows with stored refresh tokens, or use the AI Interactions Change Notifications (tenant-wide) or Teams Export APIs for data access patterns that do not require a per-user delegated call.
Auth Flows That Are NOT Supported
These flows are deprecated across Microsoft Graph and are not available for Copilot APIs:
- ❌ Implicit grant flow — deprecated; do not use, even for SPAs
- ❌ Resource Owner Password Credentials (ROPC/username-password) — not supported
- ❌ ADAL (Azure AD v1.0 library) — legacy library; migrate to MSAL before integrating Copilot APIs
Azure.Identity Credential Class Reference
The Graph SDK’s auth providers are built on Azure.Identity, which wraps MSAL and surfaces credential classes for each scenario:
| Credential Class | Flow | Best For |
|---|---|---|
AuthorizationCodeCredential | Auth Code + PKCE | Web apps, SPAs |
OnBehalfOfCredential | On-Behalf-Of (OBO) | Web APIs calling Copilot APIs on behalf of users |
ClientSecretCredential | Client Credentials | Daemon/background apps (app-only) — dev/test |
ClientCertificateCredential | Client Credentials with cert | Production daemon apps |
DeviceCodeCredential | Device Code | CLI tools, headless environments |
InteractiveBrowserCredential | Interactive Browser | Desktop apps |
What this means for you: Match your scenario row in the Auth Flow Scenario Table to the credential class above — the two tables together give you the complete implementation target for your specific integration type.
SDK, MSAL, or Raw HTTP: Which One Belongs in Your Integration
Three options exist for calling Copilot API endpoints. The right choice depends on your integration context — not personal preference.
The table below compares all three options by what you get and who owns the production concerns.
SDK Comparison Table
| Option | What You Get | When to Use | Owner of Retry / Token Refresh |
|---|---|---|---|
| Microsoft Graph SDK (recommended) | Automatic token refresh via MSAL, built-in 429 retry with Retry-After handling, batch support, request logging middleware | Most production apps; any app that also calls other Graph APIs | SDK handles it |
| MSAL + Direct HTTP | Full control over request construction; MSAL manages token acquisition and caching | When you cannot take a Graph SDK dependency, or your HTTP client is already established | You own retry; MSAL owns token refresh |
| Direct HTTP (no SDK/MSAL) | Simplest setup; any HTTP client works | Scripting, prototyping, CLI tools, one-off queries | You own both retry and token management |
For production server-side apps, the Graph SDK is the right default. It handles the 429/Retry-After pattern automatically for non-batched requests. If your integration already uses the Graph SDK for other endpoints, there is no added cost to using it here.
SDK Packages by Language
| Language | Package | Install |
|---|---|---|
| .NET | Microsoft.Graph (v1.0), Microsoft.Graph.Beta (beta) | NuGet |
| Go | github.com/microsoftgraph/msgraph-sdk-go | go get |
| Java | com.microsoft.graph:microsoft-graph | Maven / Gradle |
| JavaScript / TypeScript | @microsoft/microsoft-graph-client | npm |
| PHP | microsoft/microsoft-graph | Composer |
| PowerShell | Microsoft.Graph | PowerShell Gallery |
| Python | msgraph-sdk | pip |
Retrieval API Call — HTTP Reference Shape
This is the minimal request shape for calling the Retrieval API. It is not a complete implementation — it is the orientation target for understanding headers and body structure:
POST https://graph.microsoft.com/v1.0/copilot/retrievalAuthorization: Bearer {access_token}Content-Type: application/json{ "queryString": "How to set up corporate VPN?", "dataSource": "sharePoint"}
Use {access_token} from a delegated MSAL-issued token. Application tokens will receive a 403. The queryString field is limited to 1,500 characters and must be a single sentence — full query syntax and response handling are covered in Post 06 (Retrieval API deep dive).
Batching Note
Both the Retrieval API and the Search API support the $batch endpoint (POST https://graph.microsoft.com/$batch) with up to 20 requests per batch call. Batching is the primary pattern for staying within rate limits when an application needs to make multiple retrieval or search calls in sequence. Throttled sub-requests within a batch response (HTTP 429) are not automatically retried by the Graph SDK — you must handle those manually.
What this means for you: If you choose the Graph SDK, you still own the retry loop for batched sub-requests — the SDK’s automatic retry only applies to individual (non-batched) calls. Build that retry handler into your batch processing layer from day one.
Pre-Go-Live Checklist: Auth, Permissions, and Credentials
Complete this checklist before go-live on any Copilot API integration. Reference the Master Permission Table in the “Which Permission Gets You Which API” section for scope names as you work through each item.
Registration and Credentials
- [ ] Register the Entra ID app using the Microsoft Entra admin center — no separate Copilot portal exists
- [ ] Set
signInAudienceto work/school accounts only — personal Microsoft accounts are not supported by any Copilot API - [ ] Use a certificate or federated identity credential for production (not a client secret)
- [ ] If using a client secret for dev/test, set the expiry to less than 12 months and schedule rotation
Permissions and Consent
- [ ] Request only the least-privileged permissions per API surface (use the Master Permission Table above)
- [ ] For Retrieval API: request both
Files.Read.AllANDSites.Read.All— not one or the other - [ ] Obtain tenant admin consent for all required scopes before go-live — no user self-consent is possible
- [ ] For Meeting Insights with app-only: create and assign an application access policy in addition to granting the application permission
- [ ] For Usage Reports with delegated access: verify the signed-in user holds a required admin role (see the Permission Nuances section above)
Token and SDK
- [ ] Implement MSAL with a persistent distributed token cache (Redis, SQL) for server-side apps
- [ ] Never acquire a new token on every request — verify MSAL cache is in use
- [ ] For app-only flows, use
https://graph.microsoft.com/.defaultas the scope — not individual permission names
With this checklist complete, you have the auth and permissions foundation in place for every subsequent Copilot API integration in this series.
Now What? Your Next Three Steps
- Register your Entra ID app and request permission consent — use the Master Permission Table to select the exact scopes for your target API surface, then submit the list to your tenant admin for a single consent grant before you write any integration code.
- Design your auth flow using the scenario table — match your integration type (user-facing app, web API, background service, or admin dashboard) to the correct OAuth 2.0 flow and credential class before committing to an implementation pattern.
- Run through the Pre-Go-Live Checklist before your first deployment — print or copy the Registration, Permissions, and Token sections and track each item as a gate; a missed item here produces a 403 that has no self-describing error message pointing to the gap.
How to Navigate This Series
This series runs 14 posts across three phases:
- Phase 1 — Foundation (Posts 01–04): Landscape overview, auth and permissions, rate limits and national cloud readiness, governance and admin reporting
- Phase 2 — API Deep Dives (Posts 05–10): Usage Reports, Retrieval API, Search API, Chat API, Meeting Insights, AI Interactions Change Notifications
- Phase 3 — Production Patterns (Posts 11–14): Integration patterns, compliance and export, testing and monitoring, what is next
By role:
- Developers building user-facing apps: → Post 01 → Post 02 → Post 03 → Post 06 → Post 07
- Architects and platform engineers: → Post 01 → Post 02 → Post 03 → Post 04 → Post 05
- IT admins and governance owners: → Post 01 → Post 02 → Post 04 → Post 09
The immediate next post is Post 03 — Rate Limits, Throttling, and National Cloud Readiness. It covers the production constraints every Copilot API integration must handle before go-live: per-user throttling thresholds, 429 retry patterns, token caching, and the full national cloud availability matrix for GCC, GCC-High, and DoD environments.
References
- Copilot APIs Overview — https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/copilot-apis-overview
- Retrieval API Reference (permissions, rate limits, national cloud availability) — https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/api/ai-services/retrieval/copilotroot-retrieval
- Retrieval API Overview (known limitations, licensing, best practices) — https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/api/ai-services/retrieval/overview
- Search API Reference (permissions, beta-only status) — https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/api/ai-services/search/copilotroot-search
- Search API Overview (restrictions, rate limits, file types) — https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/api/ai-services/search/overview
- Chat API Overview (known limitations, preview status) — https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/api/ai-services/chat/overview
- AI Interactions Change Notifications (permission scopes, RSC, service plan IDs) — https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/api/ai-services/change-notifications/aiinteraction-changenotifications
- Meeting Insights API — List aiInsights (permissions, app access policy requirement) — https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/api/ai-services/meeting-insights/onlinemeeting-list-aiinsights
- Teams Meeting AI Insights developer overview (license requirements, limitations) — https://learn.microsoft.com/en-us/microsoftteams/platform/graph-api/meeting-transcripts/meeting-insights
- Copilot Usage Reports — getMicrosoft365CopilotUserCountSummary (admin role requirement) — https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/api/admin-settings/reports/copilotreportroot-getmicrosoft365copilotusercountsummary
- Interaction Export API (Teams Export) — https://learn.microsoft.com/en-us/microsoftteams/export-teams-content
- Authentication and Authorization Basics (Graph) — https://learn.microsoft.com/en-us/graph/auth/auth-concepts
- Register an Application with Microsoft Identity Platform — https://learn.microsoft.com/en-us/graph/auth-register-app-v2
- Get Access Without a User (app-only flow, `.default` scope) — https://learn.microsoft.com/en-us/graph/auth-v2-service
- Microsoft Graph Permissions Reference — https://learn.microsoft.com/en-us/graph/permissions-reference
- Allow Applications to Access Online Meetings on Behalf of a User — https://learn.microsoft.com/en-us/graph/cloud-communication-online-meeting-application-access-policy
- Microsoft Graph SDK Installation — https://learn.microsoft.com/en-us/graph/sdks/sdk-installation
- Choose a Microsoft Graph Authentication Provider — https://learn.microsoft.com/en-us/graph/sdks/choose-authentication-providers
- Microsoft Graph Throttling Guidance — https://learn.microsoft.com/en-us/graph/throttling
- Microsoft Graph National Cloud Deployments — https://learn.microsoft.com/en-us/graph/deployments