CRM migration
Field-level mapping, validation, and rollback between XSale and Twenty CRM. We move data and schema; workflows are rebuilt natively in Twenty CRM.
XSale
Source
Twenty CRM
Destination
Compatibility
8 of 11
objects map 1:1 between XSale and Twenty CRM.
Complexity
CModerate
Timeline
3-5 weeks
Overview
XSale stores data around Reps, Routes, Visits, and Orders in a schema that optimizes for mobile-first field data capture rather than relational completeness between customer records and sales outcomes. Twenty CRM is a self-hosted, open-source relational CRM that uses Contacts linked to Companies with Opportunities and a full Activity timeline. We bridge this schema gap by decomposing XSales Visit and Order records into Contact, Company, and Opportunity objects in Twenty, and by using Twenty's custom objects for Route and Visit data that does not fit the standard Contact-Account-Opportunity model. Because XSales data is heavily oriented toward field execution rather than relationship management, we flag the enrichment step explicitly and surface any custom fields the customer has added to the Order and Visit objects so nothing gets orphaned in transit. We do not migrate automations or workflow rules from XSale; we deliver a written inventory of any configured rules for the customer's admin to rebuild in Twenty's workflow builder.
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 XSale object lands in Twenty CRM, including any object-level transformations, lookup resolution, or schema-design dependencies.
Typical mapping — final map is confirmed during the sample migration step.
XSale
Rep
Twenty CRM
User
1:1XSales Rep records map to Twenty User accounts. We match by email address and map Rep display name to User displayName. Active Reps with open Route assignments become active Twenty Users; inactive Reps migrate as inactive Users so that historical records remain linked. If XSales stores rep-specific fields (territory, team, sales target), these migrate as custom User fields in Twenty.
XSale
Company (from Order or Visit)
Twenty CRM
Company
1:1XSales Order and Visit records contain a reference to the store or outlet visited or delivered to. We extract these as distinct Company records in Twenty using the outlet name, address, and any custom fields as Company fields. The XSales company identifier becomes the Twenty Company externalId for dedupe. Companies are imported first so that Contacts can be linked at insert time.
XSale
Contact (from Order or Visit)
Twenty CRM
Contact
1:1XSales Visit records may contain a contact name (store manager, buyer) alongside the company reference. We extract these as Twenty Contact records with a lookup to the parent Company. The contact name, phone, email, and title from XSales migrate to the corresponding Twenty Contact fields. If XSales stores contact-level notes from the visit, these become Note records linked to the Contact.
XSale
Route
Twenty CRM
Custom Object: Route
1:1XSales Route records (sequence of stops, assigned rep, date, status) do not map to any standard Twenty CRM object. We create a Twenty custom object named Route with fields for routeName, assignedRep (User lookup), routeDate, and status. Route is linked to the parent User via a lookup relationship. Stop-level detail (which visits compose a route) is preserved as a related list on the Route object.
XSale
Visit
Twenty CRM
Custom Object: Visit
1:1XSales Visit records capture the rep's arrival at an outlet: check-in time, GPS coordinates, visit outcome, and any notes. We create a Twenty custom object named Visit with fields for visitDate, checkInTime, checkOutTime, outcome, location (latitude/longitude), and notes. Visit links to the Company record (the outlet) and to the Contact (the person seen) via lookups, and to the parent Route if the visit is route-assigned. Custom fields on XSales Visit records (for example, shelf compliance score or audit result) migrate as custom fields on the Visit object.
XSale
Order
Twenty CRM
Opportunity
1:1XSales pre-order and delivery Order records map to Twenty Opportunity. The order amount maps to Opportunity.amount, order date maps to Opportunity.closeDate, and the order status (pending, confirmed, fulfilled) maps to Opportunity.stageName with a configured stage value set. The Company lookup links the Opportunity to the outlet. If XSales stores line items (SKUs, quantities, unit prices), these migrate as OpportunityLineItem records in Twenty. We set Opportunity.wonLostReason from XSales order cancellation reason if present.
XSale
Order Custom Fields
Twenty CRM
Custom Opportunity Fields
lossyXSales Order objects frequently carry customer-configured fields beyond the standard order data: delivery method, payment terms, special instructions, route stop number, pre-order cut-off time. We surface these fields during discovery, create corresponding custom fields on the Opportunity object in Twenty, and map each field during the Order-to-Opportunity migration step. Any field that does not fit Opportunity (for example, multi-select delivery method) is placed on the custom Visit object instead and linked via a lookup.
XSale
Visit Outcome
Twenty CRM
Activity: Task
1:1XSales Visit records with an outcome (order placed, no order, follow-up required) map to Twenty Task records linked to the Company and Contact. The visit timestamp becomes the Task ActivityDate; the outcome text becomes the Task description. This allows the activity timeline in Twenty to show the visit history alongside other activities without requiring the customer to navigate to a separate custom object.
XSale
Historical Timestamps
Twenty CRM
Activity: Task + Field Migration Audit
1:1XSales records carry createdAt and updatedAt timestamps on Rep, Route, Visit, and Order. We preserve these as custom fields on each migrated record (xsrc_created_at__c, xsrc_updated_at__c) and use them to order the migration sequence so that parent records exist before child records. In Twenty's activity-adjacent context, visit dates and order dates are preserved as the primary timeline references.
XSale
Attachment / Photo
Twenty CRM
Attachment + Note
lossyXSales Visit records may include photos (shelf compliance, store condition, delivery confirmation). We extract these as binary attachments and migrate them to Twenty as Note records with the photo embedded or linked via ContentDocument. The Note is linked to the parent Visit custom object record. Photo filenames preserve the XSales original naming convention for traceability.
XSale
Tag / Label (on Order or Visit)
Twenty CRM
Custom Field or Relation
lossyXSales may use tags or labels on Orders and Visits (for example, priority flag, seasonal label, route group). We map these based on usage frequency: tags used for filtering migrate to a multi-select custom field on the relevant object; tags used for grouping migrate to a separate custom object with a many-to-many relationship to the primary object. The customer chooses the tag strategy during discovery.
| XSale | Twenty CRM | Compatibility | |
|---|---|---|---|
| Rep | User1:1 | Fully supported | |
| Company (from Order or Visit) | Company1:1 | Fully supported | |
| Contact (from Order or Visit) | Contact1:1 | Fully supported | |
| Route | Custom Object: Route1:1 | Fully supported | |
| Visit | Custom Object: Visit1:1 | Fully supported | |
| Order | Opportunity1:1 | Fully supported | |
| Order Custom Fields | Custom Opportunity Fieldslossy | Fully supported | |
| Visit Outcome | Activity: Task1:1 | Fully supported | |
| Historical Timestamps | Activity: Task + Field Migration Audit1:1 | Fully supported | |
| Attachment / Photo | Attachment + Notelossy | Fully supported | |
| Tag / Label (on Order or Visit) | Custom Field or Relationlossy | 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.
XSale gotchas
SAP integration metadata is critical for ongoing operations
Mobile-captured data syncs from rugged devices
GPS tracking data volume is high
Catalog and brand naming inconsistency
Twenty CRM gotchas
Import order is enforced and critical
Export limited to 20,000 records and visible columns only
Soft-deleted records count toward uniqueness and trigger restores
API rate limits cap at 200 req/min on Organization tier
No native email sequences — follow-up cadences require external tools
Pair-specific challenges
Migration approach
Discovery and XSales schema audit
We audit the XSales API across all visible objects (Reps, Routes, Visits, Orders) and run a field-level introspection query to enumerate every custom field including those not returned by default. We extract a sample of 50-100 records per object to verify data quality: outlet name consistency, order status completeness, timestamp presence, and attachment availability. We pair this with a discovery call to understand which XSales features are actively used versus configured but unused. The discovery output is a written migration scope and a list of custom fields requiring mapping.
Twenty schema design and custom object creation
We design the destination schema in Twenty. This includes creating the Route and Visit custom objects with the fields surfaced during discovery, configuring the Company and Contact lookups on Visit, setting up Opportunity with the Order-mapped fields plus any custom fields from XSales, and creating the relationship between Route and Visit. We use Twenty's Settings > Data Model UI to add fields, then use the Twenty API to verify the custom object schema before data migration begins. Schema is deployed into the customer's Twenty instance before any data moves.
Company and Contact deduplication pass
We extract all distinct outlet identifiers from XSales Visit and Order records, normalize the names and addresses (removing trailing whitespace, standardizing abbreviations), and run a fuzzy-dedupe pass to consolidate duplicates before Company insert. This step is critical because XSales does not enforce unique outlet records. We present the dedupe output to the customer for approval before proceeding to import. The approved Company set is inserted first, then Contact records are linked to the matching Company.
Record migration in dependency order
We run migration in dependency order: User records (from Reps), Company records (from normalized outlet data), Contact records (linked to Companies), Route custom objects (linked to Users), Visit custom objects (linked to Route, Company, and Contact), Opportunities (from Orders, linked to Company), and OpportunityLineItems (from Order line items, linked to Opportunity). Each phase emits a row-count reconciliation report showing source count versus destination insert count before the next phase begins.
Activity and note reconstruction
Visit outcomes, notes, and any binary attachments from XSales migrate as Twenty Task records (linked to the Visit custom object) and Note records (linked to Visit, Contact, and Company). Photos attached to Visits migrate as ContentDocument records with a Note wrapper in Twenty for display in the UI. Timestamps from XSales (createdAt, updatedAt) are preserved as custom fields on each migrated record for audit.
Cutover, validation, and automation inventory handoff
We run a final reconciliation comparing XSales record counts against Twenty insert counts across all objects, then present a spot-check sample of 25-50 records to the customer's admin for sign-off. We deliver the automation inventory document listing every active XSales workflow and its recommended Twenty equivalent. We support a one-week hypercare window for reconciliation issues. We do not rebuild XSales automations in Twenty's workflow builder inside the migration scope.
Platform deep dives
XSale
Source
Strengths
Weaknesses
Twenty CRM
Destination
Strengths
Weaknesses
Complexity grading
Moderate CRM migration. 1 of 8 objects need a manual workaround.
Overall complexity
Moderate migration
Derived from compatibility, mapping clarity, API constraints, and data volume across XSale and Twenty CRM.
Object compatibility
1 of 8 objects need a manual workaround.
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
XSale: Not publicly documented — typical SaaS limits assumed and confirmed during scoping..
Data volume sensitivity
XSale doesn't expose a bulk API — REST + parallelization used for high-volume runs.
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 XSale to Twenty CRM migration scoping. Not seeing yours? Book a call.
Walk through your XSale to Twenty CRM migration with a real engineer — 30 minutes, free, written quote within 24 hours.
Book a free 30 minute consultationAdjacent paths
Other ways to leave XSale
Other ways to arrive at Twenty CRM
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.