CRM migration
Field-level mapping, validation, and rollback between Spiro and Odoo CRM. We move data and schema; workflows are rebuilt natively in Odoo CRM.
Spiro
Source
Odoo CRM
Destination
Compatibility
9 of 13
objects map 1:1 between Spiro and Odoo CRM.
Complexity
BStandard
Timeline
4-6 weeks
Overview
Moving from Spiro to Odoo CRM is a platform switch that trades Spiro's AI-driven proactive relationship tracking for Odoo's all-in-one ERP ecosystem and open-source flexibility. Spiro's three core objects (Companies, Contacts, Opportunities) map directly to Odoo CRM's Partner, Contact, and crm.lead models, but the data export path requires coordination with Spiro's Customer Success team to enable the Data Collector and provision Dropbox access. We extract all custom field definitions from Spiro's UI during discovery, pre-create matching custom fields in Odoo, then import via Odoo's XML-RPC API using batch chunking and parent-record lookup resolution. Activity history (calls, emails, meetings, tasks) migrates as Odoo mail.message and mail.activity records linked to the correct Partner and Contact. Spiro's Workflows, email sequences, and automations do not migrate; we deliver a written inventory of every active automation for the customer's admin to rebuild in Odoo Studio or with a developer.
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 Spiro object lands in Odoo CRM, including any object-level transformations, lookup resolution, or schema-design dependencies.
Typical mapping — final map is confirmed during the sample migration step.
Spiro
Company
Odoo CRM
res.partner (company type)
1:1Spiro Companies map to Odoo res.partner records with partner_type set to company. The company name, address fields, phone, website, and industry classification migrate directly. We use company name as the dedupe key during import and resolve any duplicate Spiro Companies representing the same legal entity into a single Odoo partner record with address fields merged. Spiro Company custom fields are pre-created as ir.model.fields on res.partner before import.
Spiro
Contact
Odoo CRM
res.partner (contact type)
1:1Spiro Contacts map to Odoo res.partner records with partner_type set to individual and a parent_id linking to the mapped Company partner. Name, email, phone, mobile, job title, and department migrate directly. The parent partner must exist before contact import so the parent_id foreign key is satisfied. Spiro Contact custom fields migrate to custom ir.model.fields on res.partner.
Spiro
Opportunity
Odoo CRM
crm.lead
1:1Spiro Opportunities map to Odoo crm.lead records. The Spiro Opportunity name becomes crm.lead.name; stage maps to Odoo stage_id via the stage name lookup within the target crm.team pipeline; expected_revenue and probability migrate to the Odoo fields of the same name. Close date maps to date_deadline. We flag any Spiro Opportunities with unrecognised stage names for manual Odoo stage creation before import.
Spiro
Pipeline Stage
Odoo CRM
crm.stage
lossySpiro Opportunity stage names are extracted during discovery and mapped to Odoo crm.stage records within the target crm.team. Each Spiro stage gets a corresponding Odoo stage with the same sequence order and a probability percentage matching Spiro's values. Odoo's default stages (New, Qualified, Proposal Sent, Won, Lost) are used as the base template if the Spiro pipeline stages do not map cleanly to a custom set.
Spiro
Pipeline
Odoo CRM
crm.team
lossySpiro's single workspace pipeline maps to one Odoo crm.team with the team's default stage set created in the previous step. If the customer uses Spiro's pipeline structure to separate lines of business, we create multiple crm.team records in Odoo and assign Opportunities to the correct team during import based on Spiro's pipeline assignment metadata.
Spiro
Owner / User
Odoo CRM
res.users
1:1Spiro Users map to Odoo res.users records. We match by email address during import. Any Spiro User without a matching Odoo User is held in a reconciliation queue; the customer's Odoo admin provisions the missing User before record import resumes. Owner assignments on Opportunities and Activities resolve via the User mapping at migration time.
Spiro
Activity: Email
Odoo CRM
mail.message (subtype: email)
1:1Spiro email engagements map to Odoo mail.message records with message_type=email, linked to the target res.partner via res_id and model=res.partner. Email subject, body, sender, and recipient migrate. If Spiro email sync was broken at any point (a known Spiro gotcha), those emails are absent from the export and cannot be backfilled post-migration.
Spiro
Activity: Call
Odoo CRM
mail.activity (activity_type: call)
1:1Spiro call engagements map to Odoo mail.activity records with activity_type_id referencing the built-in Call activity type. Call duration, disposition, and notes migrate to activity-specific custom fields we create on mail.activity. The activity_date_deadline is set to the original Spiro call timestamp, and the activity is linked to the res.partner Contact record.
Spiro
Activity: Meeting
Odoo CRM
mail.activity (activity_type: meeting) + calendar.event
1:1Spiro meeting engagements map to Odoo mail.activity with activity_type_id referencing the built-in Meeting type. If the customer requires full calendar event detail, we also create calendar.event records linked to the activity. Meeting title, start datetime, end datetime, location, and attendee list migrate.
Spiro
Activity: Task / Note
Odoo CRM
mail.activity (activity_type: task) or mail.message
1:1Spiro task engagements map to Odoo mail.activity with activity_type_id = Task. Spiro note engagements (free-text notes attached to a Contact or Company) map to mail.message records with subtype comment, linked to the parent res.partner. Note body migrates as plain text; any embedded file references are resolved separately.
Spiro
Attachment
Odoo CRM
ir.attachment
1:1Spiro stores attachments as linked URLs rather than embedded blobs. During migration we verify each attachment URL is reachable, download the file content, and create Odoo ir.attachment records linked to the target res.partner or crm.lead via res_id and model. If the Spiro workspace access is revoked post-migration, attachment links become orphaned. We recommend downloading critical files before the migration window closes.
Spiro
Custom Fields
Odoo CRM
ir.model.field (custom)
lossySpiro custom field definitions (on Companies, Contacts, and Opportunities) must be extracted from Spiro's UI during discovery or confirmed with a Spiro CSM since there is no documented public endpoint. We pre-create matching custom ir.model.field records in Odoo before data import begins, using field type mapping (Spiro text -> char, Spiro number -> float, Spiro date -> date, Spiro picklist -> selection). Custom field values migrate with the parent object.
Spiro
Spiro Data Collector Drop
Odoo CRM
Import batch via XML-RPC
lossySpiro's Data Collector produces CSV file drops in a Dropbox folder. We do not rely on Data Collector as the primary export path because it requires CSM enablement (adding 3-5 business days) and produces flat CSV files without relationship keys. We use Data Collector as a reference export for data validation, and we extract the primary record data directly via Spiro's internal export endpoints or UI-based extraction when available. The Odoo import runs via XML-RPC batch calls with 500-record chunks and exponential backoff on rate-limit responses.
| Spiro | Odoo CRM | Compatibility | |
|---|---|---|---|
| Company | res.partner (company type)1:1 | Fully supported | |
| Contact | res.partner (contact type)1:1 | Fully supported | |
| Opportunity | crm.lead1:1 | Fully supported | |
| Pipeline Stage | crm.stagelossy | Fully supported | |
| Pipeline | crm.teamlossy | Fully supported | |
| Owner / User | res.users1:1 | Fully supported | |
| Activity: Email | mail.message (subtype: email)1:1 | Fully supported | |
| Activity: Call | mail.activity (activity_type: call)1:1 | Fully supported | |
| Activity: Meeting | mail.activity (activity_type: meeting) + calendar.event1:1 | Fully supported | |
| Activity: Task / Note | mail.activity (activity_type: task) or mail.message1:1 | Fully supported | |
| Attachment | ir.attachment1:1 | Fully supported | |
| Custom Fields | ir.model.field (custom)lossy | Mapping required | |
| Spiro Data Collector Drop | Import batch via XML-RPClossy | 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.
Spiro gotchas
Email disconnection silently breaks activity logging
Data Collector requires CSM enablement and Dropbox access
Attachment URLs are references, not embedded files
Custom field definitions not exposed via self-service API
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
Pair-specific challenges
Migration approach
Discovery and Data Collector coordination
We audit the Spiro workspace across custom field definitions (extracted from UI or via CSM), pipeline stage names, record counts per object, and activity volume. We simultaneously coordinate with Spiro's CSM to enable Data Collector and provision Dropbox access. We confirm the Odoo deployment type (Community self-hosted, Online, or Odoo.sh) and document the import method (XML-RPC only for cloud; XML-RPC plus optional direct SQL for self-hosted). The discovery output is a written migration scope, custom field inventory, and stage probability map for customer approval.
Odoo schema setup and custom field creation
We create the Odoo custom field schema before any data import. This includes creating custom ir.model.field records on res.partner (for Contact fields), crm.lead (for Opportunity fields), and res.partner for company-level custom fields. We configure crm.team records for each pipeline, create crm.stage records with normalised probability percentages that sum to 100, and set up user access so that the migration user has write access to all target models. For self-hosted Odoo, we validate the schema in a staging database before applying to production.
Owner reconciliation and user provisioning
We extract every distinct Spiro User referenced on Contact, Company, Opportunity, and Activity records and match by email against the Odoo destination's res.users table. Any Spiro User without a matching Odoo User goes to a reconciliation queue. The customer's Odoo admin provisions missing Users (active or inactive depending on whether the original Spiro user is still active). Migration cannot proceed past record import because owner and responsible user fields are required on crm.lead and mail.activity records.
Staging migration and reconciliation
We run a full migration into the Odoo staging or sandbox environment using production-like data volume. The customer's RevOps lead reconciles record counts (Partners, Contacts, Leads/Opportunities, Activities), spot-checks 25-50 random records against the Spiro source, and validates custom field values. Any mapping corrections, stage name adjustments, or custom field type changes happen in staging before production migration begins. This step also validates that Odoo's XML-RPC rate limits (typically 1,000 requests per minute on cloud) do not cause import timeouts.
Production migration in dependency order
We run production migration in record-dependency order: res.users validation (manual provisioning confirmed), res.partner company records (from Spiro Companies), res.partner contact records (from Spiro Contacts with parent_id resolved to company), crm.team and crm.stage configuration (validated from staging), crm.lead records (from Spiro Opportunities with team_id, stage_id, and user_id resolved), mail.activity and mail.message records (batch via XML-RPC with 500-record chunks and exponential backoff), ir.attachment records (downloaded from Spiro URLs and uploaded to Odoo). Each phase emits a row-count reconciliation report before the next phase begins.
Cutover, validation, and automation handoff
We freeze Spiro writes during cutover, run a final delta migration of any records modified during the migration window, then enable Odoo as the system of record. We deliver a written inventory of every Spiro Workflow and automation with its trigger, conditions, and recommended Odoo Studio or Python equivalent. We do not rebuild Spiro automations as Odoo actions inside the migration scope; that is a separate engagement. We support a one-week hypercare window where we resolve any reconciliation issues raised by the customer's team. Odoo email gateway configuration (for inbound and outbound email sync) is completed by the customer's IT team during the hypercare week.
Platform deep dives
Spiro
Source
Strengths
Weaknesses
Odoo CRM
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 Spiro and Odoo CRM.
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
Spiro: Not publicly documented.
Data volume sensitivity
Spiro 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 Spiro to Odoo CRM migration scoping. Not seeing yours? Book a call.
Walk through your Spiro to Odoo 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 Spiro
Other ways to arrive at Odoo 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.