A developer builds an SPFx web part that calls the Retrieval API from a document library page. Delegated permissions are approved, admin consent is granted, and in the dev tenant it works exactly as documented: a user asks a question, the web part returns grounded results from SharePoint. Encouraged, the same developer is then asked to extend the solution into a tenant-wide Copilot activity dashboard, subscribing to AI Interactions Change Notifications across every user in the tenant. No configuration of the manifest makes that second request succeed — the tenant-wide subscription resource requires AiEnterpriseInteraction.Read.All, an application-only permission, and SPFx has no way to obtain one.
In a parallel project, an architect reasons from a plausible premise: SPFx can call Microsoft Graph, Copilot APIs live under the Graph namespace, therefore SPFx can call Copilot APIs. That premise is true for some APIs this series has covered and categorically false for others — and the difference has nothing to do with an API’s maturity or documentation quality. It comes down to where the calling code runs, and what kind of credential it can hold.
After reading this post, you will be able to:
- ✅ State, for any Copilot API, whether it is directly callable from SPFx or requires a backend service — using the underlying permission-type rule rather than memorizing a table
- ✅ Implement the
AadHttpClient-to-backend pattern for the Copilot APIs SPFx cannot reach directly, including which credential flow the backend should use - ✅ Evaluate SharePoint Copilot Apps (preview) as an integration option — what it solves, what it still requires a backend for, and what “preview” means operationally
- ✅ Apply a supported-vs-risky checklist to a real SPFx-plus-Copilot-API design before writing code
Why SPFx Can Never Hold an Application Permission — and Why That Fact Decides Your Architecture
SPFx runs entirely as client-side JavaScript in the browser DOM, with no server-side component — a web part executes in the same page context as any other script on the site. Application permissions require a client secret or certificate proving the app’s own identity, and browser-delivered JavaScript can’t hold that secret securely: anything shipped to the browser is visible in developer tools. SPFx therefore uses the OAuth implicit flow rather than client credentials — MSAL.js has been unsupported in SPFx since v1.4.1 — and its only supported paths, AadHttpClient and MSGraphClientV3, operate through one shared identity: the SharePoint Online Client Extensibility Entra ID service principal, provisioned automatically in every tenant.
That shared principal has a consequence architects often hit unexpectedly: permissions granted through SPFx apply to every SPFx solution in the tenant, not only the one that requested them. Granting Files.Read.All to one web part grants it to all SPFx code in the tenant — no per-solution isolation, and MSGraphClientV3 carries the identical constraint.
This is the rule every table later in this post applies: if a Copilot API’s only path to a capability is an application permission, SPFx cannot reach it — regardless of manifest configuration or admin consent.
What this means for you: before evaluating any Copilot API for an SPFx solution, ask one question first — does the capability I need have a delegated permission path at all? If the answer is no, the rest of the design conversation is about the backend, not the web part.
Five Copilot APIs, One Boundary: What SPFx Can Call Directly
Applying that single rule API by API produces the table worth bookmarking from this entire series — the cross-API view that no individual Copilot API’s documentation page provides on its own, because each page covers only its own permissions.
| API / Path | Delegated Permission | Application Permission | SPFx-Callable Directly? |
|---|---|---|---|
| Retrieval API | Yes — Files.Read.All + Sites.Read.All (SharePoint/OneDrive) or ExternalItem.Read.All (connectors) | No | Yes |
| Chat API (beta) | Yes — multiple delegated scopes required together | No | Technically yes, practically no — a multi-permission grant makes admin consent and scope management impractical for a web part; see Post 07 for the GA Work IQ alternative |
Meeting Insights (callAiInsight) | Yes — OnlineMeetingAiInsight.Read.All | Yes — gated by an admin-configured Application Access Policy | Delegated path: yes. Application path: no — backend only. See Post 08 |
| Change Notifications — per-user subscriptions | Yes — AiEnterpriseInteraction.Read | Yes — AiEnterpriseInteraction.Read.User (resource-specific consent) or .Read.All | Yes to create the subscription — see the note below |
| Change Notifications — tenant-wide subscriptions | Not supported | Yes — AiEnterpriseInteraction.Read.All only | No — backend only, no exceptions. See Post 09 |
The Meeting Insights application path is the same one that requires a tenant admin to configure an Application Access Policy before an app-only call succeeds — a governance step that parallels the admin-approval pattern the Package Management API uses for agent lifecycle actions, covered in Post 05. Both are cases where an application permission exists on paper but only functions once an administrator has separately turned a key.
Note: The per-user Change Notifications path shows “SPFx-callable” in the permission column, but that column only describes who can create the subscription. Subscribing to Graph change notifications requires supplying a
notificationUrl— a persistently reachable HTTPS endpoint that Microsoft Graph calls to deliver each notification payload. Browser-hosted SPFx code cannot serve that role, regardless of permission type: a web part closes when the user navigates away. So even the delegated, SPFx-callable per-user subscription path is not self-contained in the browser in practice — the subscription can be created with a token obtained through SPFx, but a backend listener is still required to receive anything. This is reasoning from the documented subscription mechanics in Post 09, not a single cited Microsoft statement about SPFx specifically.
💡 Insight: The table above will still be correct for a Copilot API this series has not covered, because it is not really five separate rules — it is one rule applied five times. Delegated-only means SPFx-direct is on the table; application-only, or application-required for the capability you need, means backend, full stop. That single mechanical fact, not the maturity or documentation quality of any given API, is what decides SPFx-callability going forward.
What this means for you: screenshot this table, but internalize the rule behind it — the moment a future Copilot API ships, you can classify it correctly without waiting for a blog post to tell you.
The Pattern Microsoft Actually Documents: SPFx → AadHttpClient → Backend → Application Credentials
For everything the table above marks backend-only, Microsoft has already documented the architecture — not as a Copilot-specific pattern, but as the general SPFx enterprise-API pattern that Copilot APIs slot into like any other Entra ID-secured resource. The backend registers as its own Entra ID application, separate from the SharePoint Online Client Extensibility principal SPFx itself uses. SPFx calls it through AadHttpClient, configured with the backend’s Application ID URI as the resource — declared via webApiPermissionRequests in package-solution.json — requesting a scope such as user_impersonation. AadHttpClient acquires and attaches the token automatically, so the resulting request looks like any other bearer-token call to an enterprise API:
GET /api/copilot/insights HTTP/1.1Host: contoso-copilot-backend.azurewebsites.netAuthorization: Bearer {token-scoped-to-backend-app-id-uri}Accept: application/json
The backend then chooses per call: exchange the incoming token on behalf of the signed-in user (OBO), preserving per-user scope for the Meeting Insights delegated path or per-user Change Notifications — or use its own application credentials (client credentials flow) for calls that only support application permissions, such as tenant-wide Change Notifications or the Meeting Insights application-access-policy path. One backend process can combine both roles.
Note: No single Microsoft document says “here is how to call Copilot APIs from SPFx.” This architecture combines two independently documented patterns — the SPFx-to-enterprise-API pattern and each Copilot API’s own permission table — consistent with both but not itself a Microsoft-published, explicitly-supported combination. Treat it as sound engineering derived from official sources, not a citation to a page that doesn’t exist.
What this means for you: design the backend as its own Entra ID app from day one, even for a solution that starts with only one backend-required Copilot API call — the OBO-versus-client-credentials decision belongs at the architecture stage, not retrofitted once a second call type shows up.
SharePoint Copilot Apps (Preview): Microsoft’s Own Answer to “How Do I Package SPFx With Copilot?”
One place Microsoft has started closing the gap officially is SharePoint Copilot Apps: a .sppkg package bundling SPFx client-side components — built on BaseCopilotComponent rather than BaseClientSideWebPart — with a declarative agent definition in one deployable unit. The declarative agent becomes discoverable inside Microsoft 365 Copilot; the SPFx component renders as interactive UI inside that conversation, in inline (default) or fullscreen display mode. For the inner development loop, the Copilot Workbench, at /_layouts/15/copilotworkbench.aspx on any SharePoint site, loads a component served from localhost via heft start --nobrowser.
Deployment differs most sharply from the declarative agents built through Copilot Studio (Post 12): deploying the .sppkg to the app catalog and selecting Add to Teams automatically syncs the declarative agent to the tenant’s agent catalog — no separate Agent Registry submission, the distinct governance surface Post 12 covers for Copilot Studio agents. For a maker already comfortable with the app catalog cycle, that is a materially lighter admin path.
⚠️ Preview: SharePoint Copilot Apps are in public preview as of this post’s draft date (verified fresh against current documentation) and are explicitly flagged as subject to change — do not use them in production. No Microsoft 365 Copilot license is required during preview, but that may change at general availability, and the feature cannot be published to Microsoft AppSource or the commercial marketplace while in preview — deployment is limited to your own tenant’s app catalog.
Note: As of the SPFx 1.24 beta.3 release notes (August 27, 2026), Microsoft has signaled that this capability will most likely be renamed Copilot Components at general availability — the final naming decision has not yet been announced. This post uses “SharePoint Copilot Apps,” the name in effect at the time of research; expect the GA name to differ. The underlying model (
.sppkgpackaging,BaseCopilotComponent, the Copilot Workbench, the declarative-agent-plus-SPFx-UI pattern) is unaffected by the rename.
💡 Insight: SharePoint Copilot Apps solve distribution and packaging — shipping SPFx UI and a declarative agent together with automatic tenant sync — not the permission constraint from earlier in this post. A Copilot component inside a Copilot App still runs under the standard SPFx delegated-only model, so one that needs an application-permission Copilot API still needs a backend proxy — the same architecture, in a different package.
What this means for you: treat SharePoint Copilot Apps as the packaging answer, not a permission-model exception — evaluate it for how it ships and distributes your UI, and still design the backend proxy for anything application-permission-gated.
Where the Official Client Libraries Fit — and Where They Don’t (Yet)
Microsoft also publishes Copilot APIs Client Libraries — purpose-built SDKs for C#, TypeScript, and Python, distinct from the general Microsoft Graph SDK covered in Post 02, adding Copilot-specific request builders and models the Graph SDK lacks. They ship as part of the Microsoft 365 Agents SDK with built-in retry handling, secure redirects, and payload compression, and are published in the microsoft/Agents-M365Copilot repository on GitHub.
These are a backend-side tool, not an SPFx tool — the sample authentication providers make that plain: ClientSecretCredential for daemon services (the credential type SPFx categorically cannot hold) and OnBehalfOfCredential for the OBO pattern from the previous section, giving the backend typed request builders for Retrieval, Chat, Meeting Insights, and Change Notifications calls in place of raw HTTP.
⚠️ Preview: The Copilot APIs Client Libraries are preview regardless of whether the underlying endpoint is
/v1.0or/beta— Microsoft’s own guidance is not to use them in production on that basis alone, since a/v1.0endpoint reached through a preview SDK doesn’t inherit GA stability from the endpoint.
What this means for you: reach for these libraries in the backend layer past a proof of concept, but keep the preview status in mind for any production timeline — the same discipline this series applies to every /beta endpoint applies here to the tooling itself.
Beyond SPFx: Teams Apps, Custom Web Apps, and Backend Daemons
SPFx is the sharpest illustration of the permission boundary because it has zero flexibility on it, but it is one of several client surfaces that reach Copilot APIs, and the same decision governs all of them.
Teams apps call Copilot APIs using Teams SSO, a delegated token through the Teams admin center’s app-approval process — a distinct governance surface from the SharePoint admin center path that governs SPFx permissions. Custom web apps use standard MSAL patterns instead: authorization code flow with PKCE for browser-side apps, client credentials flow for backend services — the same Graph namespace and authentication model as any other Graph call, so guidance from Posts 02 through 09 applies unchanged.
Backend and daemon services are the workhorse for every application-permission Copilot API path in this post — tenant-wide Change Notifications and the Meeting Insights application-access-policy path both run here on client credentials. A backend can also double as an OBO proxy, the same role it plays in the SPFx architecture above.
Post 07 covers the Work IQ Chat API as the GA-recommended path for new development, distinct from the Graph beta Chat API in this post’s matrix. Its authentication model matters for the backend question here: Work IQ uses Entra ID delegated authentication only. Requests run in the context of a signed-in user, OBO flows are explicitly supported for server-side callers, and application-only authentication is explicitly not supported — the permissions reference lists only a delegated entry for WorkIQAgent.Ask, with no application-permission row. In practice, a backend can call Work IQ via the same OBO pattern used elsewhere in this post, but it cannot call Work IQ as an unattended daemon, the way it can call tenant-wide Change Notifications with pure application credentials. Regardless of which client surface a solution starts from, the same delegated-versus-application decision determines the architecture — SPFx is only the surface with no flexibility left on it.
What this means for you: when scoping a multi-surface solution, do the delegated-versus-application classification once per Copilot API call, not once per client surface — the answer travels with the API, not with where the UI happens to run.
The Governance You Don’t Have to Build: Security Controls That Apply Automatically
Five controls apply automatically to every Copilot API call in this post’s architecture, regardless of client surface, with no developer action required: conditional access, sensitivity-label enforcement, permission trimming, Microsoft Purview audit logging, and Responsible AI (RAI) content validation — the same platform-level safeguard this series first named in Post 01. None of this is something the reader builds; it is inherited from the Microsoft 365 compliance layer, the same way Post 11 described declarative agents inheriting that posture. The one control the developer does own is least-privilege scope selection — granting only the permissions the solution actually needs, tying back to the matrix earlier in this post.
What this means for you: stop budgeting engineering time for conditional access, label enforcement, or audit logging on Copilot API calls — that time is better spent narrowing which permissions your app registration actually requests.
One Architecture Diagram Microsoft Hasn’t Published — So Here’s the Synthesis, Labeled as Such
No single Microsoft-published diagram shows a “UI client plus API backend plus Graph Copilot endpoints” pattern end to end. The closest official content is three separate things: the Copilot APIs app-registration chain, the SPFx AadHttpClient enterprise-API pattern, and each individual API’s permission table. The diagram below combines those three documented pieces into one picture — this is original synthesis grounded in the documented pieces above, not an official Microsoft reference architecture — and it should be read and cited that way.
[Image needs manual upload: images/spfx-backend-copilot-architecture.png — Original synthesis, not an official Microsoft reference architecture. Three-lane diagram: SPFx Web Part, Backend Service, Copilot API Surface.]
The diagram’s three lanes map onto the sections above: the SPFx lane is Section 2’s permission boundary in visual form, the backend lane is Section 4’s AadHttpClient-to-backend pattern, and the Copilot API surface lane is the matrix from Section 3. One optional capstone extension carries the same honesty framing: a combined flow inside the backend lane calling the Retrieval API, a Copilot connector, and Meeting Insights together to assemble one enriched response. Each API is individually documented in this series (Posts 06, 08, and 10), but the combined flow is not itself a Microsoft-documented pattern — it is a further application of the same synthesis, not a new claim of official support.
What this means for you: cite this diagram as a synthesis of documented pieces in any design review — never as a Microsoft reference architecture — and pull the individual pieces (the AadHttpClient pattern, each API’s permission table) from their own official pages when a reviewer asks for a primary source.
Supported vs Risky: A Design-Review Checklist for SPFx and Copilot API Integrations
Five patterns are supported by documentation this post has traced directly; four patterns are risky enough that a design review should stop and reconsider before proceeding.
| Supported (documented patterns) | Risky / Not Recommended |
|---|---|
SPFx calling the Retrieval API directly via delegated permissions (Files.Read.All, Sites.Read.All) | Storing a client secret or client credential in SPFx web part code — structurally impossible, so any design implying it is outside the documented SPFx model |
SPFx calling a custom backend via AadHttpClient, with the backend handling OBO or client credentials downstream | Using SPFx to subscribe to tenant-wide Change Notifications — blocked by permission type, not a style choice; no configuration makes it work |
A backend daemon calling tenant-wide Change Notifications with AiEnterpriseInteraction.Read.All | Calling the Chat API (Graph beta or Work IQ) from an unattended daemon context — no application-permission path exists for either |
| A Teams app calling Chat or Retrieval via Teams SSO delegated token | Treating the Copilot APIs Client Libraries or SharePoint Copilot Apps as production-ready during preview |
| A custom web app calling Copilot APIs via authorization code flow with MSAL | Assuming a delegated Change Notifications subscription is self-contained in the browser — the receiving endpoint still needs a backend |
✅ Quick win: Before scaffolding any SPFx-plus-Copilot-API solution, run every planned API call through the Section 3 matrix and mark each one SPFx-direct or backend-required. That single pass, done before the first line of manifest or backend code, is what prevents discovering a hard permission wall mid-build — the exact failure this post opened with.
What this means for you: put this table directly into your next design-review document — it is written to be quoted, not paraphrased.
Now What? Your Next Three Steps
- Run your SPFx-plus-Copilot-API design through the Section 3 matrix before writing code — identify every Copilot API call the solution needs and mark each one SPFx-direct or backend-required.
- Design the backend service now for anything marked backend-required — register it as its own Entra ID application, decide OBO versus client credentials per call, and build it with the Copilot APIs Client Libraries (preview caveat noted) or the standard Graph SDK.
- Test SharePoint Copilot Apps in the Copilot Workbench in a dev tenant if your solution has a Copilot-conversation-surface requirement — it is preview, but it is the closest thing Microsoft ships today to an official SPFx-plus-Copilot packaging model.
How to Navigate This Series
This is the last post in the 13-post series. There is no next post — what follows is the full map.
The full index, by phase:
- Phase 1 — Foundations and Governance
- Post 01 — The API landscape: what Copilot APIs are, when to choose them over Graph CRUD, Azure OpenAI + custom RAG, or Copilot Studio
- Post 02 — Auth, permissions, SDK patterns, and production readiness
- Post 03 — Rate limits, error handling, and national cloud readiness
- Post 04 — The Copilot Usage Reports API for tenant adoption data
- Phase 2 — Building with the Core APIs
- Post 05 — Managing Copilot apps and agents as an admin: the Package Management API (preview)
- Post 06 — The Retrieval API: grounded search without building a RAG pipeline
- Post 07 — The Chat API: Work IQ (GA) versus Graph beta, and which one to build against
- Post 08 — The Meeting Insights API and its delegated-versus-application permission split
- Post 09 — AI Interactions Change Notifications (preview): subscribing to Copilot activity
- Phase 3 — Agents and Extensibility
- Post 10 — Copilot connectors: two connector types, three mandatory labels, one admin step most deployments miss
- Post 11 — Declarative agents versus custom engine agents: the licensing inversion
- Post 12 — Building agents in Microsoft Copilot Studio: knowledge, tools, MCP, and the Agent Registry
- Post 13 — This post: SPFx, the permission boundary, and enterprise integration patterns
By role:
- IT admin or Copilot deployment lead: → Post 01 → Post 02 → Post 03 → Post 04, ending at Post 13 for the integration picture once governance is in place
- Developer building on the Copilot API: → Post 01 → the specific API post your scenario needs (Posts 05–09) → Post 13 for how it fits into a real client surface
- Architect or maker choosing an extensibility path: → Post 01 → Post 11 → Phase 2 and 3 as needed → Post 13 as the closing reference
For anything that changes after this post publishes — a preview surface reaching GA, a new permission on a Copilot API, a schema revision — the Microsoft Graph “what’s new” page is the living source of truth this series has pointed to throughout.
Closing the loop on Post 01’s promise: Post 01 promised a practical, role-sequenced series, honest about what is GA, what is preview, and what is not yet there — here is the tally at the close. GA today: the Retrieval API, the Meeting Insights delegated path, the Copilot Usage Reports API, Copilot connectors, the declarative-versus-custom-engine taxonomy, and the core Copilot Studio authoring platform including MCP. Still preview: the Chat API under Graph beta, the Package Management API, AI Interactions Change Notifications, SharePoint Copilot Apps, and the Copilot APIs Client Libraries. Nothing here was softened for being the finale — the same GA-or-preview discipline this series opened with is the discipline it closes with.
References
All claims in this post trace to the following official Microsoft documentation:
- Overview of the SharePoint Framework (SPFx) — browser-side execution model, no server-side component — https://learn.microsoft.com/en-us/sharepoint/dev/spfx/sharepoint-framework-overview
- Connect to Entra ID-secured APIs in SharePoint Framework solutions (AadHttpClient) — OAuth implicit flow, MSAL.js unsupported since v1.4.1, SharePoint Online Client Extensibility principal, tenant-wide permission grant — https://learn.microsoft.com/en-us/sharepoint/dev/spfx/use-aadhttpclient
- Use AadHttpClient to connect to enterprise APIs in SPFx — backend app registration,
webApiPermissionRequestspattern — https://learn.microsoft.com/en-us/sharepoint/dev/spfx/use-aadhttpclient-enterpriseapi - Use MSGraphClientV3 to connect to Microsoft Graph in SPFx — delegated-only Graph calls from SPFx — https://learn.microsoft.com/en-us/sharepoint/dev/spfx/use-msgraph
- Microsoft 365 Copilot APIs Overview — app registration chain, enterprise integration surfaces (Teams, custom web apps, backend daemons) — https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/copilot-apis-overview
- Security and authentication for Microsoft 365 Copilot APIs — conditional access, sensitivity labels, permission trimming, Purview auditing, secure grounding — https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/copilot-apis-security-authentication
- Microsoft 365 Copilot Retrieval API Overview — delegated-only permissions, rate limit, licensing — https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/api/ai-services/retrieval/overview
- Microsoft 365 Copilot Chat API Overview (Preview) — delegated-only permissions, licensing, known limitations — https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/api/ai-services/chat/overview
- Get change notifications for Copilot AI interactions using Microsoft Graph — per-user vs tenant-wide subscription resource paths, permission tables — https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/api/ai-services/change-notifications/aiinteraction-changenotifications
- Graph APIs to Fetch Meeting Insights (Teams platform docs) — callAiInsight resource, delegated and application permissions, Application Access Policy requirement — https://learn.microsoft.com/en-us/microsoftteams/platform/graph-api/meeting-transcripts/meeting-insights
- List aiInsights (Copilot extensibility reference) — endpoint and permissions — https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/api/ai-services/meeting-insights/onlinemeeting-list-aiinsights
- Overview of SharePoint Copilot Apps — preview status, BaseCopilotComponent, display modes, deployment via app catalog, Copilot Workbench, no-license-during-preview, marketplace restriction — https://learn.microsoft.com/en-us/sharepoint/dev/spfx/copilot/overview-copilot-apps
- Microsoft 365 Copilot APIs Client Libraries (Preview) — C#/TypeScript/Python SDKs, preview status, authentication provider patterns — https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/sdks/api-libraries
- Microsoft Graph change notifications (webhooks) overview — standard subscription and
notificationUrlpattern — https://learn.microsoft.com/en-us/graph/webhooks - Microsoft 365 Copilot APIs Terms of Use — https://learn.microsoft.com/en-us/legal/m365-copilot-apis/terms-of-use
- Microsoft Work IQ API Overview — authentication and security model: Entra ID delegated authentication, OBO flows supported, application-only authentication not supported — https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/work-iq/api-overview
- Work IQ API permissions reference —
WorkIQAgent.Askpermission table, delegated-only, no application-permission entry — https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/work-iq/permissions