CRM migration
Field-level mapping, validation, and rollback between Odoo CRM and HubSpot. We move data and schema; workflows are rebuilt natively in HubSpot.
Odoo CRM
Source
HubSpot
Destination
Compatibility
14 of 15
objects map 1:1 between Odoo CRM and HubSpot.
Complexity
BStandard
Timeline
48–72 hours
Try the reverse
Overview
Odoo CRM stores contacts and companies in a single res.partner model with a type flag distinguishing individuals from organizations. Deals live in crm.lead with a kanban-stage field that maps directly to HubSpot deal pipelines and stages. HubSpot separates contacts and companies into distinct objects, requires a primary company association per contact, and models deals with a mandatory pipeline + stage pair and a closedate field. We extract Odoo data via the XML-RPC / JSON-RPC external API (available on Odoo Enterprise; Odoo Community uses direct PostgreSQL reads), then map res.partner records into HubSpot contacts and companies, crm.lead records into HubSpot deals, and crm.activity records into HubSpot engagement logs (calls, emails, meetings, tasks, notes). Custom fields on crm.lead and res.partner migrate as HubSpot custom properties. Odoo workflow rules, automation actions, and server actions do not migrate — those must be rebuilt in HubSpot's workflow builder. Our migration runs a sample pass against a HubSpot sandbox before committing the full load, and a 24–48 hour delta-pickup window captures any records modified in Odoo during the cutover.
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.
Source platform
Odoo CRM platform overview
Scorecard, SWOT, gotchas, and pricing for Odoo CRM.
Destination platform
HubSpot platform overview
Scorecard, SWOT, gotchas, and pricing for HubSpot.
Data migration guide
The complete HubSpot migration guide
Data model, import mechanisms, field mapping strategy, pitfalls, and cutover — by the engineers running it.
Source platform guide
Odoo CRM migration guide
Understand the data you're exporting from Odoo CRM before mapping it.
Destination checklist
HubSpot migration checklist
Pre- and post-cutover tasks for moving onto HubSpot.
Source checklist
Odoo CRM migration checklist
Exit checklist for unwinding your Odoo CRM setup cleanly.
Why teams make this switch
Leaving
What's pushing teams away
Choosing
What's pulling them in
Object mapping
Each row shows how a Odoo CRM object lands in HubSpot, including any object-level transformations, lookup resolution, or schema-design dependencies.
Typical mapping — final map is confirmed during the sample migration step.
Odoo CRM
res.partner (is_company = True)
HubSpot
Company
1:1Odoo companies stored in res.partner with is_company=True map directly to HubSpot Company records. Odoo's street, city, country, phone, website fields on the partner record map to HubSpot's address properties and Website field. Parent-company hierarchies in Odoo (parent_id on res.partner) map to HubSpot's parent company association.
Odoo CRM
res.partner (is_company = False)
HubSpot
Contact
1:1Odoo individual contacts (is_company=False) map to HubSpot Contact records. The contact's email, phone, mobile, job title (function field in Odoo), and address properties migrate as HubSpot contact properties. Odoo's parent_id on a contact record determines the HubSpot primary CompanyId association.
Odoo CRM
crm.lead (type = 'lead' or 'opportunity')
HubSpot
Deal
many:1Odoo's crm.lead serves both lead and opportunity records. We map all crm.lead records to HubSpot Deal objects regardless of Odoo's type flag. Odoo's type distinction is preserved as a HubSpot custom property (lead_type__c) since HubSpot does not have a native equivalent split between lead and deal.
Odoo CRM
crm.stage
HubSpot
Deal Pipeline Stage
1:1Odoo stage names (New, Qualified, Proposal, Won, Lost, etc.) map value-by-value to HubSpot Deal stage names within a designated pipeline. We create the HubSpot pipeline before migration and apply stage name mappings per stage_id in Odoo's crm.stage table. Stage sequence order is preserved.
Odoo CRM
crm.team
HubSpot
Team / User Assignment
1:1Odoo's crm.team records map to HubSpot user team assignments. Team members are resolved by email match against HubSpot users, ensuring that owner assignments translate correctly across platforms. Unmatched team assignments are flagged in the pre-migration audit report so the team can pre-create HubSpot users or assign a fallback owner before the migration run begins.
Odoo CRM
crm.activity (category = 'call')
HubSpot
Call
1:1Odoo activities with category='call' migrate as HubSpot Call engagement records. Original call date, duration (x_duration in Odoo), summary (note field), and owner are preserved. Calls are associated to the corresponding HubSpot contact and deal via the Odoo's res.partner and crm.lead linkages.
Odoo CRM
crm.activity (category = 'email')
HubSpot
Odoo email activities migrate as HubSpot Email engagement records. The email subject, body (mail.message body), timestamp, and direction (inbound/outbound) are mapped to HubSpot email properties. Thread associations from Odoo's mail.thread model are preserved via the HubSpot associations API, ensuring conversation continuity is maintained across the platform migration.
Odoo CRM
crm.activity (category = 'meeting')
HubSpot
Meeting
1:1Odoo meeting activities map to HubSpot Meeting records with original start/end timestamps, title (summary field), and body preserved for complete meeting history. Odoo's calendar.event records (if used for scheduled meetings) are also mapped to HubSpot Meetings with the same property set, maintaining calendar context within the CRM.
Odoo CRM
crm.activity (category = 'note' or generic note)
HubSpot
Note
1:1Odoo notes and generic activities without a specific category migrate as HubSpot Notes, preserving the note body, author, and timestamp for historical reference. Notes are associated to the corresponding HubSpot contact, company, or deal record via the associations API after parent records are migrated.
Odoo CRM
sale.order / account.move (quotation state)
HubSpot
Quote
1:1Odoo quotations (sale.order in draft or sent state) map to HubSpot Quote records with line items, quantities, and pricing transferred from sale.order.line to HubSpot Quote line items. Odoo's discount fields and tax handling require value-mapping per product configuration to ensure pricing accuracy is maintained in the HubSpot quote records.
Odoo CRM
ir.attachment
HubSpot
File
1:1Odoo attachments on crm.lead and res.partner records migrate as HubSpot Files. We download each attachment from Odoo's filestore and re-upload to HubSpot's file storage, preserving filename, mime type, and original upload date. Files are associated to the target record after upload.
Odoo CRM
Odoo custom fields on crm.lead
HubSpot
Contact/Deal Custom Properties
1:1Odoo custom fields on crm.lead (x_studio_*, x_custom_*) migrate as HubSpot custom properties on Deal. Field type translation: char → string, integer/float → number, boolean → bool, date → date, datetime → datetime, selection → enumeration. Odoo many2one fields map to HubSpot string (ID reference) or require a lookup table.
Odoo CRM
Odoo custom fields on res.partner
HubSpot
Contact/Company Custom Properties
1:1Odoo custom fields on res.partner migrate as HubSpot custom properties on Contact or Company depending on whether the field is defined on individual contact records or company records. Selection fields become HubSpot enumeration properties with exact value lists preserved from the Odoo selection field options.
Odoo CRM
mail.message (thread messages on crm.lead)
HubSpot
Email / Note
1:1Odoo's mail.message records on crm.lead objects (internal notes and emails) migrate as HubSpot Notes or Email engagement records based on message type classification. Email subtype messages become HubSpot Emails with full body and headers preserved, while note subtype messages become Notes for internal reference. Author and create date are preserved on both record types.
Odoo CRM
crm.lost_reason
HubSpot
Deal: Closed Lost (custom field)
1:1Odoo's crm.lost_reason model stores named loss reasons per stage. These map to a HubSpot custom pick-list property (lost_reason__c) on the Deal object for consistent loss reason tracking. Each named Odoo reason becomes a HubSpot enumeration value so reporting on loss reasons remains consistent across the migrated dataset.
| Odoo CRM | HubSpot | Compatibility | |
|---|---|---|---|
| res.partner (is_company = True) | Company1:1 | Fully supported | |
| res.partner (is_company = False) | Contact1:1 | Fully supported | |
| crm.lead (type = 'lead' or 'opportunity') | Dealmany:1 | Fully supported | |
| crm.stage | Deal Pipeline Stage1:1 | Fully supported | |
| crm.team | Team / User Assignment1:1 | Fully supported | |
| crm.activity (category = 'call') | Call1:1 | Fully supported | |
| crm.activity (category = 'email') | Email1:1 | Fully supported | |
| crm.activity (category = 'meeting') | Meeting1:1 | Fully supported | |
| crm.activity (category = 'note' or generic note) | Note1:1 | Fully supported | |
| sale.order / account.move (quotation state) | Quote1:1 | Fully supported | |
| ir.attachment | File1:1 | Fully supported | |
| Odoo custom fields on crm.lead | Contact/Deal Custom Properties1:1 | Fully supported | |
| Odoo custom fields on res.partner | Contact/Company Custom Properties1:1 | Fully supported | |
| mail.message (thread messages on crm.lead) | Email / Note1:1 | Fully supported | |
| crm.lost_reason | Deal: Closed Lost (custom field)1: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.
Odoo CRM gotchas
Odoo.sh version gating blocks assisted migrations from trial
Enterprise modules fail to install on Community after database restore
Custom module view inheritance breaks between Odoo major versions
Custom fields risk losing their application context on Community
API access for Community is gated behind the Custom Plan
HubSpot gotchas
Marketing Contacts billing model is migration-critical
Feature tier gating is not visible until onboarding
Mandatory onboarding fees inflate year-one cost
HubSpot CSV importer cannot migrate engagements or attachments
Custom objects require Enterprise and a pre-existing schema
Pair-specific challenges
Migration approach
Audit Odoo data model and extract schema
FlitStack connects to Odoo (via external API for Enterprise/Custom Plan, or via read-only PostgreSQL access for Community) and pulls the complete schema: all res.partner fields, all crm.lead fields, crm.stage definitions, crm.team records, crm.activity types, and ir.model.fields for custom field names and types. We generate a data audit report showing record counts per object, custom field inventory, blank/null rates, and parent-child relationship depth. This audit identifies Odoo Community database access requirements and flags any fields that cannot be extracted via standard API methods.
Map schema and configure HubSpot destination
We translate Odoo's object model to HubSpot objects (res.partner → Contact + Company, crm.lead → Deal, crm.activity → Call/Email/Meeting). Custom fields from Odoo are created as HubSpot custom properties with appropriate type translations. We create the HubSpot Deal Pipeline and stages using Odoo's crm.stage names as the source. Owner resolution by email is configured: Odoo user IDs are matched against HubSpot user emails, and unmatched owners are flagged with a fallback assignment recommendation.
Migrate companies first, then contacts, then deals
HubSpot requires Companies to exist before Contacts can associate via associatedcompanyid, and Contacts to exist before Deals can associate contact roles. We sequence the migration: (1) all res.partner records where is_company=True migrate as HubSpot Companies, (2) all res.partner records where is_company=False migrate as HubSpot Contacts with primary company associations resolved, (3) all crm.lead records migrate as HubSpot Deals with contact associations and stage mapping. Activities and attachments migrate after parent records are in place, maintaining referential integrity throughout.
Run a sample migration with field-level verification
A representative slice — typically 200–500 records covering the range of contact types, deal stages, and activity categories — migrates to a HubSpot sandbox or test portal. We generate a field-level diff report comparing Odoo source values against the migrated HubSpot values for every mapped field. You review the diff and confirm field mapping correctness, lost-reason value coverage, owner resolution rates, and date preservation before the full run commits.
Execute full migration with delta-pickup cutover window
The full dataset migrates to HubSpot with real-time progress tracking and QA checkpoints after each object batch. During the migration, your Odoo team continues working. After the primary migration completes, a 24–48 hour delta-pickup window captures any Odoo records created or modified during the cutover, applying the same field mappings and transformations. An audit log records every upsert, association, and transformation. If reconciliation identifies issues, one-click rollback reverts the HubSpot environment to the pre-migration state.
Post-migration validation and workflow rebuild handoff
FlitStack runs automated validation scripts comparing record counts, field completeness, and association integrity between the Odoo snapshot and HubSpot state. Spot-check verification covers deals at each stage, contacts with attachments, and activity logs. We deliver an export of your Odoo workflow and automation definitions as a structured reference document for your HubSpot admin to use when rebuilding rules in HubSpot's workflow builder. A 30-day post-migration support window covers any data discrepancies discovered after go-live.
Platform deep dives
Odoo CRM
Source
Strengths
Weaknesses
HubSpot
Destination
Strengths
Weaknesses
Complexity grading
Standard CRM migration. 1 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 Odoo CRM and HubSpot.
Object compatibility
1 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
Odoo CRM: Not publicly documented; no published rate limit found in Odoo's official developer documentation.
Data volume sensitivity
Odoo CRM 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 Odoo CRM to HubSpot migration scoping. Not seeing yours? Book a call.
Walk through your Odoo CRM to HubSpot migration with a real engineer — 30 minutes, free, written quote within 24 hours.
Book a free 30 minute consultationAdjacent paths
Other ways to leave Odoo CRM
Other ways to arrive at HubSpot
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.