-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Update spe MigrationAPI #11020
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Steve Pucelik (Spucelik)
wants to merge
2
commits into
SharePoint:main
Choose a base branch
from
Spucelik:update-spe-MigrationAPI
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+388
−0
Open
Update spe MigrationAPI #11020
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
388 changes: 388 additions & 0 deletions
388
docs/embedded/build/Migrate content into SharePoint Embedded.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,388 @@ | ||
| --- | ||
| title: Migrate content with the migration API | ||
| description: Prepare migration manifests and import content into SharePoint Embedded containers with Microsoft Graph. | ||
| ms.date: 09/03/2026 | ||
| ms.reviewer: troys | ||
| ms.author: stpuceli | ||
| ms.localizationpriority: high | ||
| ai-usage: ai-assisted | ||
| --- | ||
|
|
||
| # Migrate content with the migration API | ||
|
|
||
| **Applies to:** SharePoint Embedded via Microsoft Graph v1.0 | ||
|
|
||
| <!-- agent: | ||
| task_type: how-to | ||
| audience: developer | ||
| outcome: Prepare migration manifests, import content into a SharePoint Embedded container, and monitor the migration job. | ||
| next: ../publish/prepare-customer-installation.md | ||
| --> | ||
|
|
||
| Use the SharePoint Embedded migration API to import large content sets into a target container. The workflow stages content and metadata in temporary Azure Blob Storage containers, then runs an asynchronous migration job. | ||
|
|
||
| This guide explains how to prepare SharePoint deployment manifests, provision temporary storage, submit a migration job, monitor progress, and remove a queued job. | ||
|
|
||
| ## Understand the migration workflow | ||
|
|
||
| The SharePoint Embedded migration workflow has five stages: | ||
|
|
||
| 1. Provision SharePoint-managed Azure Blob Storage containers for content and metadata. | ||
| 1. Prepare deployment manifests and upload the migration package to the temporary containers. | ||
| 1. Submit a migration job for the target SharePoint Embedded container. | ||
| 1. Poll the job's progress events until the job completes or reports an error. | ||
| 1. Delete a migration job if you need to remove it while it's queued. | ||
|
|
||
| The Azure Blob Storage containers are temporary intermediary storage. Creating a migration job schedules the import; it doesn't import the content synchronously. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| Before you start, collect or configure these inputs: | ||
|
|
||
| - A target SharePoint Embedded container ID. | ||
| - A Microsoft Entra application that has `FileStorageContainer.Selected` access to the target container. | ||
| - A work or school account for delegated access, or an application identity for app-only access. | ||
| - A migration package generator that creates valid SharePoint deployment manifests. | ||
| - A process that uploads content and metadata to Azure Blob Storage by using shared access signature (SAS) URLs. | ||
| - Source identifiers, timestamps, authors, and editor values that you want to preserve. | ||
|
|
||
| Personal Microsoft accounts aren't supported. The least-privileged permission for both delegated and application access is `FileStorageContainer.Selected`. | ||
|
|
||
| For SharePoint Embedded authentication and permissions, see [Authentication and permissions](../plan/authentication-permissions.md). | ||
|
|
||
| ## Provision temporary migration containers | ||
|
|
||
| Provisioning creates separate Azure Blob Storage containers for file data and migration metadata. The response also contains the Base64-encoded AES-256-CBC encryption key used by the migration package. | ||
|
|
||
| Send this request without a request body: | ||
|
|
||
| ```http | ||
| POST https://graph.microsoft.com/v1.0/storage/fileStorage/containers/<container-id>/provisionMigrationContainers | ||
| Authorization: Bearer <access-token> | ||
| ``` | ||
|
|
||
| Replace `<container-id>` with the target SharePoint Embedded container ID. Replace `<access-token>` with a Microsoft Graph access token. | ||
|
|
||
| A successful request returns `200 OK`: | ||
|
|
||
| ```json | ||
| { | ||
| "@odata.type": "#microsoft.graph.sharePointMigrationContainerInfo", | ||
| "dataContainerUri": "https://<storage-host>/data?<sas-token>", | ||
| "metadataContainerUri": "https://<storage-host>/metadata?<sas-token>", | ||
| "encryptionKey": "<base64-aes-256-cbc-key>" | ||
| } | ||
| ``` | ||
|
|
||
| The response values have these purposes: | ||
|
|
||
| | Property | Purpose | | ||
| | --- | --- | | ||
| | `dataContainerUri` | SAS URL for the Azure Blob Storage container that holds file content. | | ||
| | `metadataContainerUri` | SAS URL for the Azure Blob Storage container that holds migration manifests and metadata. | | ||
| | `encryptionKey` | Base64-encoded AES-256-CBC key for encrypted migration content. | | ||
|
|
||
| Verify that the SAS URLs grant read and write access. Keep them valid for at least 12 hours so the migration job can read the complete package. | ||
|
|
||
| If the request returns `429 Too Many Requests` with `RetryAfterDelay` and `activityLimitReached`, wait and retry with backoff. | ||
|
|
||
| For the complete contract, see [Provision migration containers](/graph/api/filestoragecontainer-provisionmigrationcontainers). | ||
|
|
||
| ## Prepare the migration manifests | ||
|
|
||
| The migration manifests describe each object, its relationships, its content file, and the metadata to preserve. Generate manifests programmatically so repeated identifiers stay consistent. | ||
|
|
||
| A file commonly requires two related objects: | ||
|
|
||
| - An `SPFile` object for the file content and file-level metadata. | ||
| - An `SPListItem` object for the corresponding list item and fields. | ||
|
|
||
| The file ID must match the list item's `DocId`. Values such as `ParentWebId`, `ParentWebUrl`, list IDs, folder IDs, authors, and timestamps must also match across related elements. | ||
|
|
||
| ### Get list and web identifiers | ||
|
|
||
| Get the target drive root to resolve the list and web identifiers: | ||
|
|
||
| ```http | ||
| GET https://graph.microsoft.com/v1.0/drives/<drive-id>/root?$select=sharepointIds,webUrl | ||
| Authorization: Bearer <access-token> | ||
| ``` | ||
|
|
||
| Replace `<drive-id>` with the target container's drive ID. | ||
|
|
||
| Map the response to the manifest properties: | ||
|
|
||
| | Manifest property | Microsoft Graph response property | | ||
| | --- | --- | | ||
| | `ListId` | `sharepointIds.listId` | | ||
| | `ListFolderId` | `sharepointIds.listItemUniqueId` | | ||
| | `ParentWebId` | `sharepointIds.webId` | | ||
| | `ParentWebUrl` | The container site URL derived from `sharepointIds.siteUrl` and the target path. | | ||
|
|
||
| The expected result is a `driveItem` response that contains `sharepointIds`. If these values are missing, verify that the drive ID belongs to the target SharePoint Embedded container. | ||
|
|
||
| ### Get a parent folder identifier | ||
|
|
||
| List an existing folder or create the destination folder through Microsoft Graph. Read the folder's `eTag`, and use the GUID inside the braces as `ParentFolderId`. | ||
|
|
||
| For example, this `eTag`: | ||
|
|
||
| ```text | ||
| "{86EC9BA4-D929-441A-87CA-F4B2164D6439},3" | ||
| ``` | ||
|
|
||
| produces this manifest value: | ||
|
|
||
| ```text | ||
| 86EC9BA4-D929-441A-87CA-F4B2164D6439 | ||
| ``` | ||
|
|
||
| Don't include the braces, quotation marks, comma, or version number. | ||
|
|
||
| For folder operations, see [Manage files and folders](manage-files.md). | ||
|
|
||
| ### Preserve file system metadata | ||
|
|
||
| Populate the manifest from the source system's metadata. The migration service uses these properties to preserve file dates and identities: | ||
|
|
||
| | Manifest property | Source value | | ||
| | --- | --- | | ||
| | `TimeCreated` | Original file creation timestamp. | | ||
| | `TimeLastModified` | Original file modification timestamp. | | ||
| | `Author` | Source author identifier represented in the migration package. | | ||
| | `ModifiedBy` | Source editor identifier represented in the migration package. | | ||
|
|
||
| If the package generator substitutes the migration time or migration identity, the imported file doesn't retain its original system metadata. | ||
|
|
||
| ### Create the object manifest | ||
|
|
||
| The following abbreviated example shows the relationship between an `SPFile` object and its `SPListItem`. Replace every placeholder with a value from the source system or target container. | ||
|
|
||
| ```xml | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <SPObjects xmlns="urn:deployment-manifest-schema"> | ||
| <SPObject | ||
| Id="<file-id>" | ||
| ObjectType="SPFile" | ||
| ParentId="<parent-folder-id>" | ||
| ParentWebId="<parent-web-id>" | ||
| ParentWebUrl="<parent-web-url>" | ||
| Url="<absolute-file-url>"> | ||
| <File | ||
| Url="<server-relative-file-url>" | ||
| Id="<file-id>" | ||
| ParentWebId="<parent-web-id>" | ||
| ParentWebUrl="<parent-web-url>" | ||
| Name="<file-name>" | ||
| ListItemIntId="<list-item-integer-id>" | ||
| ListId="<list-id>" | ||
| ParentId="<parent-folder-id>" | ||
| TimeCreated="<source-created-timestamp>" | ||
| TimeLastModified="<source-modified-timestamp>" | ||
| Version="<file-version>" | ||
| FileValue="<content-blob-name>" | ||
| FileSize="<file-size-bytes>" | ||
| Author="<source-author-id>" | ||
| ModifiedBy="<source-editor-id>" /> | ||
| </SPObject> | ||
|
|
||
| <SPObject | ||
| Id="<list-item-id>" | ||
| ObjectType="SPListItem" | ||
| ParentId="<list-id>" | ||
| ParentWebId="<parent-web-id>" | ||
| ParentWebUrl="<parent-web-url>" | ||
| Url="<absolute-file-url>"> | ||
| <ListItem | ||
| FileUrl="<server-relative-file-url>" | ||
| DocType="File" | ||
| ParentFolderId="<parent-folder-id>" | ||
| Order="<list-item-order>" | ||
| Id="<list-item-id>" | ||
| ParentWebId="<parent-web-id>" | ||
| ParentListId="<list-id>" | ||
| Name="<file-name>" | ||
| DirName="<server-relative-folder-url>" | ||
| IntId="<list-item-integer-id>" | ||
| DocId="<file-id>" | ||
| Version="<file-version>" | ||
| Author="<source-author-id>" | ||
| ModifiedBy="<source-editor-id>" | ||
| TimeLastModified="<source-modified-timestamp>" | ||
| TimeCreated="<source-created-timestamp>"> | ||
| <Fields /> | ||
| </ListItem> | ||
| </SPObject> | ||
| </SPObjects> | ||
| ``` | ||
|
|
||
| The placeholders represent these values: | ||
|
|
||
| | Placeholder | Value | | ||
| | --- | --- | | ||
| | `<file-id>` | Unique ID for the file. Reuse it as the list item's `DocId`. | | ||
| | `<list-item-id>` | Unique ID for the corresponding list item. | | ||
| | `<parent-folder-id>` | GUID extracted from the destination folder's `eTag`. | | ||
| | `<parent-web-id>` | `sharepointIds.webId` for the target drive root. | | ||
| | `<parent-web-url>` | URL of the target SharePoint Embedded container site. | | ||
| | `<absolute-file-url>` | Full destination URL for the file. | | ||
| | `<server-relative-file-url>` | File path within the target document library. | | ||
| | `<server-relative-folder-url>` | Parent folder path within the target document library. | | ||
| | `<file-name>` | Destination file name. | | ||
| | `<list-item-integer-id>` | Integer ID assigned to the list item in the package. | | ||
| | `<list-id>` | `sharepointIds.listId` for the target drive root. | | ||
| | `<list-item-order>` | List item order value generated for the package. | | ||
| | `<file-version>` | Version value represented by the migration package. | | ||
| | `<content-blob-name>` | Name of the staged data blob that contains the file bytes. | | ||
| | `<file-size-bytes>` | Source file size in bytes. | | ||
| | `<source-created-timestamp>` | Original creation time in an accepted date-time format. | | ||
| | `<source-modified-timestamp>` | Original modification time in an accepted date-time format. | | ||
| | `<source-author-id>` | Author identity mapping used by the migration package. | | ||
| | `<source-editor-id>` | Editor identity mapping used by the migration package. | | ||
|
|
||
| Validate the manifest against the `urn:deployment-manifest-schema` schema before upload. A validation failure means the package isn't ready to submit. | ||
|
|
||
| ## Stage content and metadata | ||
|
|
||
| Upload file content to the container identified by `dataContainerUri`. Upload the manifests and related metadata to the container identified by `metadataContainerUri`. | ||
|
|
||
| Complete the staging upload before you create the migration job. Confirm these conditions: | ||
|
|
||
| - Every `FileValue` points to an uploaded data blob. | ||
| - Manifest identifiers remain consistent across related objects. | ||
| - The manifests pass schema validation. | ||
| - The SAS URLs still have at least 12 hours of validity. | ||
| - The encryption key used for staged content matches the key returned during provisioning. | ||
|
|
||
| An incomplete or inconsistent package can create a job that later reports object-level errors. | ||
|
|
||
| ## Submit the migration job | ||
|
|
||
| Create the migration job after all content and metadata are staged: | ||
|
|
||
| ```http | ||
| POST https://graph.microsoft.com/v1.0/storage/fileStorage/containers/<container-id>/migrationJobs | ||
| Authorization: Bearer <access-token> | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "containerInfo": { | ||
| "dataContainerUri": "https://<storage-host>/data?<sas-token>", | ||
| "metadataContainerUri": "https://<storage-host>/metadata?<sas-token>", | ||
| "encryptionKey": "<base64-aes-256-cbc-key>" | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| Use the values returned by the provisioning request. A successful request returns `201 Created` and the migration job ID: | ||
|
|
||
| ```json | ||
| { | ||
| "id": "<migration-job-id>" | ||
| } | ||
| ``` | ||
|
|
||
| Persist `<migration-job-id>` with the target container ID. Both values are required to monitor or delete the job. | ||
|
|
||
| If the API returns `migrationBadRequest` with `invalidAzureResource`, provision new migration containers and restage the package. An invalid or expired SAS URL commonly causes this error. | ||
|
|
||
| For the complete contract, see [Create a SharePoint migration job](/graph/api/filestoragecontainer-post-migrationjobs). | ||
|
|
||
| ## Monitor migration progress | ||
|
|
||
| Progress events show when the job queues, starts, processes objects, reports errors, and completes. Events remain available for four days, so persist the event stream while you poll. | ||
|
|
||
| Send this request: | ||
|
|
||
| ```http | ||
| GET https://graph.microsoft.com/v1.0/storage/fileStorage/containers/<container-id>/migrationJobs/<migration-job-id>/progressEvents | ||
| Authorization: Bearer <access-token> | ||
| ``` | ||
|
|
||
| Replace `<migration-job-id>` with the ID returned when you created the job. | ||
|
|
||
| Inspect these event types: | ||
|
|
||
| | Event type | Meaning | | ||
| | --- | --- | | ||
| | `sharePointMigrationJobQueuedEvent` | The service accepted and queued the job. | | ||
| | `sharePointMigrationJobStartEvent` | The job started or restarted. | | ||
| | `sharePointMigrationJobProgressEvent` | The job reports processed files, bytes, objects, errors, warnings, retries, and completion state. | | ||
| | `sharePointMigrationJobErrorEvent` | The job reports an error for the package or an object. | | ||
| | `sharePointMigrationJobCancelledEvent` | The job was canceled. | | ||
|
|
||
| A `200 OK` response doesn't mean that the migration succeeded. Inspect `totalErrors`, `isCompleted`, and every `sharePointMigrationJobErrorEvent`. | ||
|
|
||
| Follow `@odata.nextLink` until the response doesn't include another page. You can also pass the returned `$skipToken` value explicitly. | ||
|
|
||
| If the API returns `migrationNotFound` with `jobProgressExpired`, the four-day event retention period has ended. Use the telemetry that your migration process persisted. | ||
|
|
||
| For the complete contract, see [List migration progress events](/graph/api/sharepointmigrationjob-list-progressevents). | ||
|
|
||
| ## Delete a queued migration job | ||
|
|
||
| Delete a migration job when you need to remove it before processing: | ||
|
|
||
| ```http | ||
| DELETE https://graph.microsoft.com/v1.0/storage/fileStorage/containers/<container-id>/migrationJobs/<migration-job-id> | ||
| Authorization: Bearer <access-token> | ||
| ``` | ||
|
|
||
| A successful request returns `204 No Content`. | ||
|
|
||
| If the API returns `migrationNotFound` with `jobNotFound`, verify both IDs. The job might already be deleted or no longer available for removal. | ||
|
|
||
| For the complete contract, see [Delete a SharePoint migration job](/graph/api/sharepointmigrationjob-delete). | ||
|
|
||
| ## Troubleshoot migration errors | ||
|
|
||
| Migration API errors include a top-level code and an `innerError` object. Persist `request-id` and `client-request-id` because support uses them to correlate failures. | ||
|
|
||
| Use this table for common failures: | ||
|
|
||
| | HTTP status | Error codes | Action | | ||
| | --- | --- | --- | | ||
| | `429` | `RetryAfterDelay`, `activityLimitReached` | Wait, then retry with backoff. | | ||
| | `400` | `migrationBadRequest`, `invalidAzureResource` | Provision new temporary containers, restage the package, and submit a new job. | | ||
| | `404` | `migrationNotFound`, `jobProgressExpired` | Read persisted telemetry because progress events expired after four days. | | ||
| | `404` | `migrationNotFound`, `jobNotFound` | Verify the container and job IDs, then check whether the job was deleted. | | ||
|
|
||
| Also inspect job-level events when the progress request succeeds. A migration can return `200 OK` while its event stream contains fatal errors. | ||
|
|
||
| ## Validate the migration | ||
|
|
||
| Validate the destination before you retire or change the source system: | ||
|
|
||
| 1. Compare the expected object count with `objectsProcessed`. | ||
| 1. Confirm that `totalErrors` is zero, or account for every reported error. | ||
| 1. Compare representative file sizes and versions. | ||
| 1. Verify destination folder paths and list item metadata. | ||
| 1. Confirm that `TimeCreated`, `TimeLastModified`, `Author`, and `ModifiedBy` match the source values. | ||
| 1. Open representative files through the SharePoint Embedded application. | ||
| 1. Persist the final event page and correlation IDs with the migration record. | ||
|
|
||
| The migration is complete when the final progress event has `isCompleted` set to `true` and your destination validation passes. | ||
|
|
||
| ## Pre-migration checklist | ||
|
|
||
| Use this checklist before a production migration: | ||
|
|
||
| - [ ] Select delegated access for a signed-in migration tool or application access for a background service. | ||
| - [ ] Grant `FileStorageContainer.Selected` access to the target container. | ||
| - [ ] Confirm the target SharePoint Embedded container ID. | ||
| - [ ] Provision the data and metadata containers. | ||
| - [ ] Verify that SAS URLs grant read and write access. | ||
| - [ ] Verify that SAS URLs remain valid for at least 12 hours. | ||
| - [ ] Resolve all list, web, file, and folder identifiers. | ||
| - [ ] Preserve source timestamps and identity mappings. | ||
| - [ ] Validate manifests against the deployment schema. | ||
| - [ ] Upload every content blob referenced by `FileValue`. | ||
| - [ ] Implement progress-event pagination and telemetry persistence. | ||
| - [ ] Implement retry and backoff handling. | ||
| - [ ] Test the queued-job deletion path. | ||
|
|
||
| ## Next steps | ||
|
|
||
| - Review the [Microsoft Graph migration API overview](/graph/api/resources/sharepointmigration-api-overview). | ||
| - Use the [Microsoft Graph API reference links](../reference/graph-api-links.md) for other SharePoint Embedded operations. | ||
| - [Prepare your app for customer installation](../publish/prepare-customer-installation.md). | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Title should be descriptive to say this is about SPE... the current title isn't descriptive enough