SharePoint Embedded

Building Your First SharePoint Embedded Application: Container Types, Permissions, and Microsoft Graph

Building Your First SharePoint Embedded Application: Container Types, Permissions, and Microsoft Graph

Building Your First SharePoint Embedded Application: Container Types, Permissions, and Microsoft Graph

The previous two articles in our Q2 2026 SharePoint Embedded series have explained what SharePoint Embedded is and when to choose it over WOPI. This article moves from architecture to implementation. It is a hands-on SharePoint Embedded implementation guide that takes a developer from a clean slate to a working application that creates containers, manages files, and launches Office editing — through Microsoft Graph, with the correct SharePoint Embedded container types and Microsoft Graph permissions in place.

This is a dense, technical article. It is intended for developers who have read the foundational explainer and are now scoping or building the first SharePoint Embedded integration in their organisation. We assume comfort with Microsoft Entra ID app registrations, OAuth 2.0, and Microsoft Graph at a general level. We do not assume any prior SharePoint Embedded experience.

The Architectural Picture in One Diagram

A working SharePoint Embedded application has four moving parts:

┌─────────────────────────┐
│ Your Application        │
│  - SPA / web frontend   │
│  - Backend service      │
│  - Optional Office.js   │
│    add-in surface       │
└──────────┬──────────────┘
           │ Microsoft Graph (delegated + app permissions)
           ▼
┌─────────────────────────────────────────────────────────────┐
│ Microsoft Entra ID                                          │
│  - Your Application Registration (multi-tenant)             │
│  - Per-customer admin consent                               │
└──────────┬──────────────────────────────────────────────────┘
           │
           ▼
┌─────────────────────────────────────────────────────────────┐
│ SharePoint Embedded Container Type (registered to your app) │
│  - Defines per-container permissions model                  │
│  - Authorised by each consuming tenant once                 │
└──────────┬──────────────────────────────────────────────────┘
           │
           ▼
┌─────────────────────────────────────────────────────────────┐
│ Containers (instantiated per workspace / customer / project)│
│  - Files, coauthoring, sensitivity labels, Copilot, Purview │
└─────────────────────────────────────────────────────────────┘

Each layer has a small, well-defined set of responsibilities. The order of implementation matters — you cannot create a container without a container type, and you cannot register a container type without an Entra ID application — so this article walks through the layers in the order you will build them.

Prerequisites

Before starting, you need:

  • A Microsoft 365 tenant that you control. This is the application tenant under which you will register the container type and from which you will own the SharePoint Embedded billing relationship. For ISVs this is your corporate Microsoft 365 tenant; for internal-use enterprise applications it is your organisation’s tenant.
  • An Azure subscription linked to that tenant. SharePoint Embedded billing flows through Azure consumption.
  • PowerShell with the SharePoint Embedded module installed. Container type registration is currently performed via PowerShell (PnP.PowerShell and the SharePoint Embedded administration module). The Microsoft Graph API for container type management is gradually expanding, but PowerShell remains the canonical first-step path.
  • A development tenant for testing. You should not test container creation against your production application tenant. Maintain a separate consuming tenant for end-to-end testing — at minimum a Microsoft 365 developer programme tenant.

Once these are in place, the steps below take a typical implementation team a working week to a working fortnight, depending on the complexity of the consuming application.

Step 1: Register the Application in Microsoft Entra ID

Begin in the Entra ID admin centre or via the Microsoft Graph admin API. Create a new application registration with the following properties:

  • Multi-tenant audience. Even if you initially deploy in a single tenant, register the application as multi-tenant from the start — adding multi-tenancy later is more disruptive than including it from the beginning.
  • Redirect URIs for your single-page application or web app, configured for the appropriate platform (SPA for an MSAL.js client, Web for a confidential client).
  • API permissions including the Microsoft Graph permissions that SharePoint Embedded uses: FileStorageContainer.Selected (delegated and application), and any Files.* permissions your application requires. The Selected permissions are critical — these are the permissions that allow your application to act on containers of types you have registered, without granting broad access across the consuming tenant.

A few important details:

Application secrets and certificates. For the backend service component of your application, configure a client certificate rather than a client secret where possible. SharePoint Embedded operations frequently use the application identity (rather than a delegated user identity), and certificate-based authentication is the recommended posture for production.

Token configuration. Configure the optional claims to include the tid (tenant ID) claim in tokens. Your application will frequently need to act on a per-tenant basis, and having the tenant identity surfaced explicitly in tokens simplifies routing logic.

Branding. Set the application’s name, logo, publisher domain, and (where available) verified publisher status. Consuming tenants will see this branding during the consent flow, and a verified publisher badge materially improves the consent experience for enterprise administrators.

Step 2: Register a Container Type

A container type is the descriptor that links your Entra ID application to a class of containers. It is registered once per application, in your application tenant, using PowerShell.

The PowerShell flow is approximately:

Connect-SPOService -Url https://your-tenant-admin.sharepoint.com

New-SPOContainerType `
    -ContainerTypeName "AcmeProductWorkspaces" `
    -OwningApplicationId "<your-app-registration-id>" `
    -ApplicationRedirectUrl "https://your-app.example.com/auth/callback" `
    -BillingClassification Standard

# Capture the container type ID returned by the registration

The output of this registration is a container type ID — a GUID that uniquely identifies the container type within Microsoft. Save this ID securely. It is referenced from every subsequent operation that creates or manipulates containers.

A few important properties of the container type:

The container type is owned by your application registration. Only your application can create containers of this type. This is the core isolation property that makes SharePoint Embedded a viable model for ISVs — your container type is yours, not exposed to other applications.

The billing classification is set at registration time. Standard billing flows through the application tenant’s Azure subscription. Trial classifications are available for evaluation work but cannot be promoted to production without a re-registration; choose intentionally.

The application redirect URL is consulted during the consuming-tenant authorisation flow. It must be a publicly resolvable URL.

Step 3: Authorise the Container Type in a Consuming Tenant

Once the container type is registered, each consuming customer organisation must authorise it. This is a one-time consent flow performed by an Entra ID administrator in the consuming tenant.

The flow has two distinct parts.

Part one: standard Entra ID admin consent. A tenant administrator in the consuming organisation grants consent to your multi-tenant application registration in their tenant. This is the same consent flow that any multi-tenant Entra ID application uses.

Part two: container type authorisation. This is specific to SharePoint Embedded. After the standard admin consent, the tenant administrator must execute a container-type-specific authorisation that grants your application permission to create containers of that container type in that consuming tenant. This is performed via PowerShell or via a programmatic admin API:

Connect-SPOService -Url https://consuming-tenant-admin.sharepoint.com

Register-SPOContainerType `
    -ContainerTypeId "<your-container-type-id>" `
    -OwningApplicationId "<your-app-registration-id>"

The container type registration in the consuming tenant must complete before your application can create containers there. The two-part flow exists because SharePoint Embedded deliberately requires explicit consuming-tenant agreement to host containers — it is not implied by the standard Entra ID consent.

For ISVs deploying at scale, the container type authorisation is one of the steps that benefits most from a polished onboarding experience. Microsoft offers the Microsoft 365 Container Types administration UI and programmatic interfaces; build your customer onboarding around these so a consuming tenant administrator can authorise your application end-to-end without leaving your product.

Step 4: Create a Container

With the container type registered and authorised in the consuming tenant, your application can now create containers. The Graph API endpoint is:

POST https://graph.microsoft.com/v1.0/storage/fileStorage/containers

Body:

{
  "displayName": "Acme Project — Northgate Manufacturing",
  "description": "Project workspace for Northgate engagement",
  "containerTypeId": "<your-container-type-id>"
}

The response includes the container’s ID, its drive ID (for Graph drive operations), and its initial state. You can then operate on the container as you would any other Graph drive — listing items, uploading files, creating folders, and so on:

GET    https://graph.microsoft.com/v1.0/drives/{driveId}/items/{itemId}
PUT    https://graph.microsoft.com/v1.0/drives/{driveId}/items/{itemId}/content
POST   https://graph.microsoft.com/v1.0/drives/{driveId}/items/{itemId}/children
DELETE https://graph.microsoft.com/v1.0/drives/{driveId}/items/{itemId}

For most ISVs, container creation is triggered by application events: a customer creates a new project, a new workspace, a new contract folder. The application backend creates the container, stores the container ID in the application database alongside the corresponding business object, and from that point on the container is just another resource the application manages.

Step 5: Manage Container Permissions

SharePoint Embedded container permissions are managed through a dedicated permissions API. The model uses container-level permissions that are granted to identities — typically users, but also groups and service principals — with specific roles.

POST https://graph.microsoft.com/v1.0/storage/fileStorage/containers/{containerId}/permissions

Body:

{
  "roles": ["writer"],
  "grantedToV2": {
    "user": {
      "userPrincipalName": "alice@northgate.example.com"
    }
  }
}

The supported roles are reader, writer, manager, and owner. The model is intentionally narrower than full SharePoint permissions — SharePoint Embedded is designed for the ISV model, not the organisational document library model, and the permission surface reflects that.

A few critical points:

Permissions are managed by your application, not by the consuming tenant administrator. Your application is responsible for keeping container permissions consistent with its own business model. A user who is added as a project member in your application should be granted writer permission on the corresponding container; a user who leaves the project should have the permission removed.

Permissions are user-identified, not application-identified. The user is granted permission on the container, and Office editing operations performed by that user enforce the granted permission. This is the property that makes SharePoint Embedded coauthoring work cleanly — Office sees the user’s permission state directly.

Sensitivity labels and Microsoft Purview integration apply automatically. If the consuming tenant has configured sensitivity labels and your container falls within their scope, the labels are enforced without your application doing anything specifically. This is one of the largest practical benefits of SharePoint Embedded over a custom WOPI host: information protection just works.

Step 6: Launch Office Editing

The final step in the basic flow is launching Office editing for a document inside a container. SharePoint Embedded uses Office for the web hosted by Microsoft, with the document loaded directly from the container. Your application’s role is to construct the correct URL and present it to the user.

The simplest pattern is to use the Graph drive item’s webUrl property:

GET https://graph.microsoft.com/v1.0/drives/{driveId}/items/{itemId}

The response includes a webUrl that, when opened in a browser, launches Office for the web with the document loaded. For a more polished experience, your application can construct the URL programmatically with explicit edit-vs-view mode parameters and an embedded experience hint:

https://{tenantHost}/_layouts/15/Doc.aspx?sourcedoc={fileId}&action=edit&Embed=1

The exact URL conventions evolve; consult the current Microsoft Graph documentation for SharePoint Embedded URL construction. The important architectural point is that your application does not implement the document editing surface itself. Office for the web does. Your application launches it; Microsoft handles the rest.

For applications that want the editing experience embedded in their own UI rather than a separate tab, the recommended approach is an iframe with the constructed URL, scoped appropriately for your application’s content security policy. SharePoint Embedded’s editing surface supports iframe embedding without the additional configuration required for some other Microsoft 365 surfaces.

Step 7: Wire Up Change Notifications

Production applications need to react to changes in container state — files added, edited, deleted; permissions changed; coauthoring sessions completing. SharePoint Embedded supports change notifications via Microsoft Graph subscriptions:

POST https://graph.microsoft.com/v1.0/subscriptions

Body:

{
  "changeType": "updated",
  "notificationUrl": "https://your-app.example.com/webhooks/graph",
  "resource": "/drives/{driveId}/root",
  "expirationDateTime": "2026-05-15T18:00:00Z",
  "clientState": "secretClientStateValue"
}

Subscription expiration management is the operational discipline that catches most teams out: subscriptions must be renewed before they expire, the renewal endpoint requires the same authentication context that created the subscription, and missed renewals result in silent loss of notifications. Build the renewal cycle into your application’s scheduled jobs from the start — this is not an afterthought.

For per-container subscriptions at scale, consider the volume implications. A naïve implementation might create one subscription per container per change type, which scales poorly. Microsoft Graph supports drive-level and tenant-level subscriptions that aggregate change events; use these where the granularity fits your application.

Step 8: Stand Up Local Development

Local development against SharePoint Embedded requires a few specific arrangements:

  • A development tenant as outlined in the prerequisites.
  • A separate Entra ID application registration for development, with redirect URIs pointing to your local development environment (http://localhost:3000/... for typical SPA development).
  • A separate container type registered in the development tenant, distinct from the production container type. Do not mix development and production container types — the consuming tenant authorisations are separate, and conflating them will produce confusing failure modes.
  • Tunnel configuration if you need Microsoft Graph webhook subscriptions to deliver to your local environment. ngrok or equivalent tunnelling tools work cleanly with the Graph subscription model.

Once configured, the development inner loop is straightforward: change code, hit your local server, run Graph operations against the development container type, observe results in the development tenant.

Step 9: Plan for Production Deployment

Production deployment introduces a few additional considerations.

Certificate-based authentication for the backend. Replace any client secrets used during development with X.509 certificates managed through Azure Key Vault. This is standard practice for any Graph-integrated production service and is non-negotiable for SharePoint Embedded production deployments.

Throttling and retry handling. Microsoft Graph throttles aggressive callers. Your application must implement retry-after handling correctly, with exponential backoff on transient failures and surfacing of permanent failures to your application logic. The Microsoft Graph SDKs include throttling-aware HTTP clients; use them rather than implementing your own.

Per-tenant rate planning. Operations against a specific consuming tenant share a tenant-level rate budget. High-volume applications should distribute work across consuming tenants and avoid bursty patterns.

Telemetry and observability. Instrument your Graph calls with the request IDs and client-request-id headers that Microsoft Graph supports. When a Graph operation fails in production, having the request ID makes the difference between a tractable Microsoft support case and a frustrating dead end.

Cost monitoring. Set up Azure Cost Management views for your SharePoint Embedded consumption (storage, transactions, bandwidth). Alert on unexpected ramp. The consumption model is predictable but not free, and a runaway integration bug can produce a surprising invoice.

Step 10: Compliance Integration

Once the basic flow is working, the final step is wiring up the compliance and information protection capabilities that SharePoint Embedded gives you for free.

Sensitivity labels. Configure your container types so that consuming tenant sensitivity labels apply to documents within containers. The default behaviour for most container types is to respect tenant labels; verify this against your tenant’s information protection policy.

Retention. SharePoint Embedded containers participate in Microsoft Purview retention policies if configured. Documents in containers can be subject to retention holds, expiration, and disposition reviews exactly as documents in SharePoint or OneDrive.

Microsoft Purview integration. For consuming tenants that use Microsoft Purview, containers are visible to the relevant Purview surfaces (Data Lifecycle Management, Records Management, Insider Risk Management). This is the property that makes SharePoint Embedded acceptable in regulated environments — the compliance posture inherits from the consuming tenant rather than requiring your application to reimplement it.

Audit logs. Container operations are recorded in the consuming tenant’s unified audit log. For organisations subject to audit obligations, this is exactly the surface their auditors expect to see.

Common Implementation Mistakes

We have observed a few patterns repeatedly across SharePoint Embedded implementations.

Treating the container type as an afterthought. The container type is the central design artefact in your SharePoint Embedded integration. Decisions baked into the container type — the permissions model, the billing classification — are difficult to change later. Spend disproportionate design time on the container type before writing the first line of code.

Skipping the consuming-tenant authorisation step in development. Developers who skip the consuming-tenant authorisation in their development tenant produce code that “works” against simplified test rigs and fails immediately in real consuming tenants. Always test against a fully authorised tenant.

Treating Graph permissions as global rather than Selected. Container type-scoped (Selected) permissions are the right model for SharePoint Embedded. Requesting broad Files.ReadWrite.All is unnecessary, alarms enterprise consent reviews, and is harder to defend during admin consent flows.

Underinvesting in the consuming-tenant onboarding flow. The consuming-tenant authorisation is, for most consuming customers, their first impression of your application’s professionalism. A clunky PowerShell-script-based onboarding leaves a different impression than a polished in-app flow that walks the administrator through consent and authorisation in five minutes.

Where to Go From Here

This article gives you a working SharePoint Embedded application. From here, the next areas of investment for most product teams are:

  • Multi-region container placement for international users.
  • Custom Office add-ins loaded into the embedded editing experience for product-specific functionality.
  • Copilot integration to surface AI capabilities over container content.
  • Migration from a custom WOPI host if you have one — covered in our forthcoming article.

McKenna Consultants has been delivering Microsoft document integration solutions for two decades. We are now building SharePoint Embedded applications for ISVs and enterprise customers across the UK, drawing on our deep WOPI experience and our extensive Microsoft Graph practice. If your team is starting a SharePoint Embedded build and would like an experienced partner — or an architectural review of work already in flight — contact us to discuss the engagement.

Have a question about this topic?

Our team would be happy to discuss this further with you.