Teams to Teams (cross-tenant) migration
A reference for moving Microsoft Teams content between two Microsoft 365 tenants: teams, channels, channel messages with original timestamps, channel files on the backing SharePoint site, members, and guests. This page covers the credential shape on both sides, how the destination team is built in migration mode, how user identity is mapped across tenants, and the handling of private channels and embedded tenant-specific URLs.
Why cross-tenant Teams migration is special
Unlike a SharePoint or file-class migration, Teams chat history cannot be recreated by copying bytes. Microsoft's Teams Migration API is the only supported path that lets historical messages land with their original timestamps and sender. The destination team must be created in a special migration mode state, have the history written in, and then be flipped to the active state. MigrationFox drives that sequence end-to-end.
Supported scope
| Item | Carried across? | Notes |
|---|---|---|
| Team structure (name, description) | Yes | Created automatically, or you can pre-provision the destination team and point the job at it. |
| Standard channels | Yes | Channel names and descriptions are recreated. Ordering follows the source. |
| Private channels | Yes, with caveats | See Private channel migration. |
| Channel messages | Yes | Original timestamp and sender preserved through the Teams Migration API. |
| Files shared in channels | Yes | Migrated as companion SharePoint file jobs to the destination team's backing site. |
| Channel tabs | Partial | See Tabs and apps. |
| Apps installed in the team | Partial | Microsoft-first apps (Planner, OneNote, Lists) are handled as part of the team; third-party app install state is not carried over. |
| Members and owners | Yes, via user mapping | Members are added to the destination team after import mode completes. |
| Guest users | Yes, with re-invite | See Guest users and B2B. |
| Meeting history, recordings, 1:1 chats | No | Out of scope of the Teams Migration API. 1:1 chats stay with the source user; recordings live in each user's OneDrive (migrate per user via file migration). |
Prerequisites
Azure AD app with Teamwork.Migrate.All
You need an Azure AD app registration on both the source and the destination tenant. The simplest approach is to reuse your MigrationFox Microsoft credential on each side.
Permissions (Application, not Delegated):
Teamwork.Migrate.All— required on the destination tenant to create teams in migration mode and import messages.Team.ReadBasic.All,Channel.ReadBasic.All,ChannelMessage.Read.All— required on the source tenant to enumerate teams and read channel history.Sites.ReadWrite.All— on both tenants, so channel files can move through each team's backing SharePoint site.
Admin consent must be granted on each tenant after adding the permissions. Delegated tokens are not accepted by the Teams Migration API — app-only is the only supported path.
Source UPN → destination UPN
Source and destination tenants have different domains, so a given person has two different UPNs. Prepare a mapping list before running: john@source-company.com → john@dest-company.com.
The wizard accepts the mapping as a CSV upload or a paste-in list. Unmapped senders fall back to a default imported-user identity, which is usually undesirable — fix the mapping up front. Unmapped members simply are not added to the destination team (no error, but review the report).
How the migration runs
- Source scan. MigrationFox enumerates the source team: channels, messages, members, tabs, and the backing SharePoint site.
- Destination provisioning. The wizard creates the destination team in migration mode (or attaches to a pre-provisioned team still in that state). Migration mode is the Microsoft-documented flag that allows writing messages with historical timestamps — a team in active state cannot accept backfilled history.
- Channel creation. Channels are recreated in the same order, with names and descriptions preserved.
- Message import. Messages are written through the Teams Migration API with their original sender (resolved from the mapping), original timestamp, and attachment references.
- File companion jobs. For each channel, the backing SharePoint folder is queued as a separate file migration job so attachments and shared documents land on the destination team's site.
- Complete migration. Once messages and files are imported, the team is flipped from migration mode to active. Members are added, and the team becomes usable.
URL rewriting in embedded links
Messages frequently contain links to files, SharePoint pages, and other Teams resources. Those links are tenant-scoped — they point at source-company.sharepoint.com or teams.microsoft.com/l/entity/... with a tenant ID in the path. If left untouched, those links would 404 or silently resolve against the wrong tenant after migration.
During message import MigrationFox rewrites tenant-host strings in message bodies to match the destination tenant where there is a 1:1 source-to-destination mapping:
- SharePoint host rewrite —
source-company.sharepoint.com→dest-company.sharepoint.comin href and src attributes. - Teams deep-link tenant ID rewrite — the tenant ID embedded in
teams.microsoft.com/l/...deep links is swapped for the destination tenant ID. - Channel and team references in deep links (group ID, channel ID) are rewritten to the newly created destination IDs.
External links (public websites, SaaS URLs not bound to the source tenant) are left as-is. Links pointing at resources that were not part of the migration (e.g. a SharePoint site that is not being moved) are also left as-is — they will still work cross-tenant only if guest access is configured for that resource.
Guest users and B2B conversion
Every team has members and guests. Members are in-tenant users; guests are external B2B identities from other tenants or consumer accounts.
- In-tenant members — added to the destination team after migration mode completes, using the source → destination UPN mapping.
- Guest users — guests exist as B2B identity objects in the source tenant. On the destination side, those same external identities need to be invited into the destination tenant as B2B guests before they can be added to the destination team. The wizard produces a guest re-invite list for each team: a flat list of external email addresses the destination tenant has not yet invited. Run a B2B bulk invite on the destination tenant, then resume the migration — the guests will be added to the team automatically.
- Guest authorship — messages authored by guests in the source tenant retain their original name and attribution on import only if the same external identity has been B2B-invited into the destination. Otherwise guest messages are attributed to a generic imported-user identity.
Plan guest invites before you cut over
The simplest path: run a practice import, export the guest-invite list from the job report, bulk-invite those guests into the destination tenant in advance, then run the real migration. Guests with no invite on the destination side end up as orphan attribution rows — not broken, but a cosmetic problem.
Private channel migration
Private channels in Teams have their own SharePoint site (a separate site collection from the parent team's backing site). That means a private channel migration is effectively two operations joined together:
- Channel + messages — handled by the Teams Migration API, same path as standard channels.
- Files — queued as a companion SharePoint migration job against the private channel's own site collection, not the parent team's.
Membership of a private channel is a strict subset of team membership. The wizard preserves private-channel membership using the same UPN mapping; users who are not mapped are not added to the private channel and its message history still imports (with their source-side attribution resolved only if they appear in the mapping).
Tabs and apps
- File tabs (pinned folders / documents from the backing SharePoint site) are recreated when the underlying file migration completes — the tab points at the new destination URL after URL rewriting.
- Wiki tabs are deprecated by Microsoft and not recreated.
- Planner and OneNote tabs — Planner plans do not move with the team automatically; OneNote notebooks stored on the team's SharePoint site move with the file companion job.
- Third-party app tabs (custom apps, connectors) are not installed into the destination team. A report of source-team app installs is produced so you can reinstall the ones that matter.
Known limits
- Imported messages render as “imported.” The Teams UI tags every message written through the migration API. Full text, timestamp, sender preserved; just visually marked.
- Emoji reactions and thread reply structure do not carry over. The migration API does not accept reaction payloads and flattens threaded replies into chronological order.
- 1:1 and group chats are not in scope. Microsoft's migration API is channel-only. 1:1 chat history is bound to the individual user's mailbox and does not move cross-tenant through this path.
- Meeting recordings live in the organiser's OneDrive — move per user via a file migration, not via the Teams migration.
- Power Automate flows bound to a team do not migrate automatically. Treat the flow inventory separately using the Power Platform inventory report.
- Channel email addresses are regenerated; the source-side
...teams.msemail stops working after cutover.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Destination team cannot accept messages: “team not in migration mode” | The team was switched to active too early, or an existing active team was targeted directly. | Either create a new team through the wizard, or use the PowerShell cmdlet Microsoft provides to set an existing team back into migration mode. Active teams cannot be backfilled. |
| Messages import under a generic “imported-user” identity instead of the original sender | Source UPN is not present in the user mapping, or destination UPN does not exist on the destination tenant. | Export the mapping report from the job page, fix unmatched rows, and re-run on a fresh team. Already-imported messages keep the attribution they landed with. |
| Embedded SharePoint links in messages still point at the source tenant | URL rewriting only rewrites host strings that have a direct mapping to the destination. Links pointing at sites that were not part of the migration are left alone. | Either include those sites in a separate SharePoint migration, or accept that external-to-migration links will require guest access on the source tenant. |
| Guest users don't appear in the destination team after migration | The external identities have not been B2B-invited into the destination tenant yet. | Pull the guest re-invite list from the job report, run a B2B bulk invite on the destination tenant, then re-run the membership sync step. |
| Private channel imports but its files are missing | Private channels store files in their own site collection. The companion file job runs against that separate site and can fail independently. | Check the file companion job's status on the job detail page. Typical cause is missing Sites permission against the private channel's site URL. |
HTTP 403 from the source tenant on /beta/teams/{id}/channels/{id}/messages |
The source app lacks ChannelMessage.Read.All, or admin consent was never granted. |
Add the permission in Azure AD, grant admin consent, wait a minute, rerun. |
| Team creation fails on the destination with “group already exists” | A team with the same alias already exists on the destination tenant. | Either rename the destination team in the wizard, or delete the orphan group on the destination before re-running. |
Related
- Slack to Teams migration — the same Teams Migration API, different source
- SharePoint Site Migration — the backing sites that hold channel files