CRM migration
Field-level mapping, validation, and rollback between OPEX 365 CRM and Salesforce Sales Cloud. We move data and schema; workflows are rebuilt natively in Salesforce Sales Cloud.
OPEX 365 CRM
Source
Salesforce Sales Cloud
Destination
Compatibility
7 of 12
objects map 1:1 between OPEX 365 CRM and Salesforce Sales Cloud.
Complexity
BStandard
Timeline
4-8 weeks
Overview
Moving from OPEX 365 CRM to Salesforce is a schema translation exercise as much as a data move. OPEX 365 CRM stores records on Microsoft Dataverse, which uses polymorphic Activity Party references that can point a single activity to a Contact, Account, Lead, or User without a fixed target type. Salesforce uses strict WhoId and WhatId fields that require the target type to be known at insert time. We run a referential integrity pass that resolves every polymorphic party reference before import, creating placeholder records for any missing targets so that activity history does not become orphaned. Notes and email attachments require a separate extraction step because annotation entity content is base64-encoded in Dataverse and not included in standard API responses. We extract annotation records using the RetrieveContent放电 API, stage the binary content separately, and remap file references to Salesforce's ContentDocumentLink model during import. Workflows, Power Automate flows, and Dataverse plugins do not migrate; we deliver a written inventory for the customer's admin to rebuild in Salesforce Flow.
Every standard and custom field arrives verified.
AI proposes the map; you confirm before any record moves.
Parent–child, lookups, and ownership stay linked.
Calls, emails, meetings — with original timestamps.
Documents, uploads, and inline notes move with the record.
Why teams make this switch
Leaving
What's pushing teams away
Choosing
What's pulling them in
Object mapping
Each row shows how a OPEX 365 CRM object lands in Salesforce Sales Cloud, including any object-level transformations, lookup resolution, or schema-design dependencies.
Typical mapping — final map is confirmed during the sample migration step.
OPEX 365 CRM
Contact
Salesforce Sales Cloud
Lead or Contact
1:manyOPEX 365 CRM Contact records with a null or unqualified lead status map to Salesforce Lead. Contacts with an associated Account and a qualified lifecycle stage map to Salesforce Contact under the resolved Account. We preserve the original Dataverse contactid as a custom field opex_contact_id__c for cross-reference audit and any future bi-directional sync requirements.
OPEX 365 CRM
Account
Salesforce Sales Cloud
Account
1:1OPEX 365 CRM Account maps directly to Salesforce Account using accountid as the dedupe key. Parent account hierarchy migrates via the ParentId field. Industry classification, annual revenue, number of employees, and address fields map to their typed Salesforce equivalents. Account is created before Contact import so that AccountId is resolved at the moment of Contact insert.
OPEX 365 CRM
Opportunity
Salesforce Sales Cloud
Opportunity
1:1OPEX 365 CRM Opportunity maps to Salesforce Opportunity. Pipeline and stage names are captured from Dataverse processstage or custom pipeline/stage metadata and mapped to Salesforce StageName after the target Record Type and Sales Process are configured. Estimated close date maps to CloseDate and Amount maps to Amount. We preserve the original opex_opportunity_id__c cross-reference field.
OPEX 365 CRM
Pipeline and Stage
Salesforce Sales Cloud
Record Type + Sales Process
lossyEach distinct OPEX 365 CRM pipeline becomes a Salesforce Record Type on Opportunity, with a corresponding Sales Process that whitelists only the relevant stage values. Stage probability percentages migrate from Dynamics stage probability metadata to Salesforce StageProbability. Closed-Won and Closed-Lost stage names are preserved for reporting continuity.
OPEX 365 CRM
Lead
Salesforce Sales Cloud
Lead
1:1OPEX 365 CRM Lead maps directly to Salesforce Lead when a separate Lead object exists in the source environment. Lead status, lead quality score, and source campaign attribution migrate to custom fields if the destination Salesforce org does not have matching standard fields.
OPEX 365 CRM
Case (Incident)
Salesforce Sales Cloud
Case
1:1OPEX 365 CRM Cases (incidents) map to Salesforce Case. Case priority, status, subject, and description migrate directly. We resolve the regardingobjectid reference to link the Case to the correct Account or Contact in Salesforce. Entitlement and SLA associations are preserved as custom fields since Salesforce Service Cloud entitlement management requires separate configuration.
OPEX 365 CRM
Product
Salesforce Sales Cloud
Product2
1:1OPEX 365 CRM Product records map to Salesforce Product2. The product number or SKU maps to ProductCode. Product bundle structures (productpricelevel entities) are decomposed: the parent bundle migrates as a Product2 and child items migrate as related Product2 records with a custom bundle_parent__c lookup field, since Salesforce OpportunityLineItems do not natively support nested bundles.
OPEX 365 CRM
User / Owner
Salesforce Sales Cloud
User
1:1OPEX 365 CRM Dataverse User records are resolved against Salesforce Users by email address. The destination User must be provisioned before migration begins. Any owner reference in the source that does not resolve to a Salesforce User goes to a reconciliation queue. Inactive users from Dynamics are created as inactive Salesforce Users to preserve historical assignment on audit records.
OPEX 365 CRM
ActivityPointer
Salesforce Sales Cloud
Task, Event, EmailMessage
1:manyOPEX 365 CRM ActivityPointer records are split by activitytypecode: email records migrate to Salesforce EmailMessage; phone call and task records migrate to Task with TaskSubtype set; meeting and appointment records migrate to Event. Each activity is resolved to its WhoId and WhatId in Salesforce using the Activity Party resolution pass before insert. ActivityDateTime preserves the original timestamp for timeline ordering.
OPEX 365 CRM
ActivityParty
Salesforce Sales Cloud
EventRelation or TaskWho relation
lossyThe Dataverse ActivityParty entity is polymorphic: a single activityparty record can reference Contact, Account, Lead, or User via partyid. We resolve each reference to its target type and Salesforce ID before importing the parent Activity. Missing target records are created as placeholder Contacts with a flag indicating they require manual review post-migration. Event attendees create EventRelation records in Salesforce.
OPEX 365 CRM
Annotation (Notes and Attachments)
Salesforce Sales Cloud
ContentDocument, ContentVersion, Note
1:manyOPEX 365 CRM annotation records require a separate extraction pipeline. The Dataverse RetrieveContent放电 API is called per annotation to extract the base64-encoded file body, which is stored in FlitStack AI staging blob storage. During Salesforce import, ContentVersion records are created with the binary body and linked via ContentDocumentLink to the parent record (Contact, Account, Opportunity, Case). Text notes migrate as Salesforce Note objects. This two-phase approach is required because standard Dataverse API responses do not include attachment bodies.
OPEX 365 CRM
Custom Entity
Salesforce Sales Cloud
Custom Object
1:1Any Dataverse entity beyond the standard Contact, Account, Opportunity, Case, and Activity objects is enumerated during pre-migration schema discovery via the EntityDefinitions endpoint. Each custom entity migrates to a Salesforce Custom Object with the __c API name suffix. Custom attributes are mapped to typed Salesforce fields. Lookup relationships to standard objects are resolved via the same parent-record lookup sequence used for standard objects. Custom entities with polymorphic lookups require the same disambiguation pass as ActivityParty.
| OPEX 365 CRM | Salesforce Sales Cloud | Compatibility | |
|---|---|---|---|
| Contact | Lead or Contact1:many | Fully supported | |
| Account | Account1:1 | Fully supported | |
| Opportunity | Opportunity1:1 | Fully supported | |
| Pipeline and Stage | Record Type + Sales Processlossy | Fully supported | |
| Lead | Lead1:1 | Fully supported | |
| Case (Incident) | Case1:1 | Fully supported | |
| Product | Product21:1 | Fully supported | |
| User / Owner | User1:1 | Fully supported | |
| ActivityPointer | Task, Event, EmailMessage1:many | Fully supported | |
| ActivityParty | EventRelation or TaskWho relationlossy | Fully supported | |
| Annotation (Notes and Attachments) | ContentDocument, ContentVersion, Note1:many | Fully supported | |
| Custom Entity | Custom Object1:1 | Fully supported |
Gotchas + challenges
Platform-specific issues from each side, plus the pair-specific challenges that don't show up on either platform's page on its own.
OPEX 365 CRM gotchas
Dataverse API rate limits vary by license tier
Custom entity schemas require manual enumeration
Activity Party relationships are polymorphic and fragile
Legacy attachment storage requires separate extraction
Salesforce Sales Cloud gotchas
Workflow Rules and Process Builder are retired
Bulk API batch quota exhaustion during large imports
Storage overage billing is non-obvious
Account-Contact many-to-many relationship mapping
Territory and team member import ordering dependencies
Pair-specific challenges
Migration approach
Pre-migration schema discovery and scoping
We query the Dataverse EntityDefinitions endpoint to enumerate all standard and custom entities in the source OPEX 365 CRM environment. We capture entity metadata including attribute types, required fields, and lookup relationships. We run a record-count audit across all entities to size the migration and identify entities with volumes that will trigger Dataverse service protection limits. We deliver a written schema inventory, a record count report, and a draft object mapping before any data moves. The scoping call also covers pipeline and stage enumeration, user count, case volume, and attachment estimate.
Salesforce destination schema design
We design the Salesforce destination schema in a Sandbox org. This includes provisioning custom objects and fields (with __c API names matched to Dataverse entity names), configuring Record Types and Sales Processes per OPEX 365 CRM pipeline, and setting up the Lead-Contact split rule based on the source contact lifecycle stage or lead qualification status. We coordinate with the customer's Salesforce admin to ensure the migration user has the necessary Bulk API permissions, Field-Level Security access, and that validation rules are identified for temporary bypass during the import phase.
Sandbox migration and reconciliation
We execute a full migration into a Salesforce Sandbox using production-like data volumes. The customer's RevOps lead reconciles record counts against the source Dataverse query results, spot-checks 25-50 records per object for field-level accuracy, and validates that parent-child relationships are intact (Account on Contact, Opportunity on Line Items, Account on Case). Any mapping corrections are applied to the migration scripts before production migration begins. Activity Party resolution is validated by spot-checking activity timelines for a sample of Contacts and Accounts.
Activity Party resolution and annotation extraction
We run the referential integrity pass that resolves every Dataverse ActivityParty polymorphic partyid to a typed Salesforce WhoId or WhatId. Missing target records are created as placeholder Contacts flagged for manual review. In parallel, we extract annotation entity file bodies via the RetrieveContent放电 API and stage binary content in FlitStack AI blob storage. These two pre-processing steps produce the import-ready activity dataset and the staged attachment package that are consumed during the production migration phase.
Production migration in dependency order
We run production migration in strict record-dependency order: Salesforce Users (validated against the source owner reconciliation list), Accounts (from Dataverse Account), Contacts (with AccountId resolved), Leads, Opportunities (with AccountId, OwnerId, and RecordTypeId resolved), Products and PricebookEntries, Cases, Activity history (Tasks, Events, EmailMessages via Bulk API 2.0 with parent-record lookup resolution), Custom Objects, and finally ContentDocument and ContentVersion attachments. Each phase emits a row-count reconciliation report before the next phase begins. Dataverse API rate-limit headers govern the pacing of each phase.
Cutover, delta migration, and Workflow inventory handoff
We freeze Dataverse writes during the cutover window, run a final delta migration of any records created or modified during the migration sequence, then enable Salesforce as the system of record. We deliver the Workflow and Power Automate inventory document to the customer's admin team within 48 hours of cutover. We support a one-week hypercare window to resolve reconciliation issues raised by the customer's teams. We do not rebuild OPEX 365 CRM workflows or Power Automate flows as Salesforce Flow inside the migration scope; that is a separate engagement or an internal admin task.
Platform deep dives
OPEX 365 CRM
Source
Strengths
Weaknesses
Salesforce Sales Cloud
Destination
Strengths
Weaknesses
Complexity grading
Standard CRM migration. 3 of 8 objects need a mapping; the rest are 1:1.
Overall complexity
Standard migration
Derived from compatibility, mapping clarity, API constraints, and data volume across OPEX 365 CRM and Salesforce Sales Cloud.
Object compatibility
3 of 8 objects need a mapping; the rest are 1:1.
Field mapping clarity
Field mapping is derived from defaults — final spec confirmed during the sample migration.
Timeline complexity
8-object category — typical timelines run 2–7 days end-to-end.
API constraints
OPEX 365 CRM: Varies by license tier and environment; not publicly documented for all tiers.
Data volume sensitivity
OPEX 365 CRM exposes a bulk API — large-volume migrations stream efficiently.
Estimator
Rule-based pricing — no per-record fees, no manual quotes. Migrations over 2M records are scoped individually.
Step 1
Pick a category, then your source and destination platforms.
Category
FAQ
Answers to the questions buyers ask most during OPEX 365 CRM to Salesforce Sales Cloud migration scoping. Not seeing yours? Book a call.
Walk through your OPEX 365 CRM to Salesforce Sales Cloud migration with a real engineer — 30 minutes, free, written quote within 24 hours.
Book a free 30 minute consultationAdjacent paths
Other ways to leave OPEX 365 CRM
Other ways to arrive at Salesforce Sales Cloud
Ready when you are
Tell us record counts and timeline. We'll come back with a written quote inside 1 business day — no commitment, no sales pitch.