CRM migration
Field-level mapping, validation, and rollback between Firmao CRM and Odoo CRM. We move data and schema; workflows are rebuilt natively in Odoo CRM.
Firmao CRM
Source
Odoo CRM
Destination
Compatibility
9 of 12
objects map 1:1 between Firmao CRM and Odoo CRM.
Complexity
BStandard
Timeline
2-4 weeks
Overview
Moving from Firmao CRM to Odoo CRM is a structural migration across API architectures. Firmao exposes a flat JSON REST API with per-endpoint GET and POST operations and no bulk endpoint, while Odoo uses XML-RPC with distinct model names (res.partner, crm.lead, project.task, product.product) and per-method batch limits of 5,000 records per call. The core migration work involves mapping Firmao's Companies and Contacts to Odoo's res.partner (distinguished by company_type), mapping Deals to crm.lead with stage names reconciled against the Odoo pipeline, resolving Firmao's dot-notation custom fields (customFields.customN) into Odoo custom field definitions before data import, and handling the subClass=warehouse envelope in Products by extracting each warehouse variant as a separate stock.location in Odoo. We do not migrate automations, workflows, or Forms as code; we deliver a written inventory of every active automation for the customer's Odoo admin to rebuild. Historical timestamps and owner assignments (via email-to-user resolution) are preserved throughout.
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 Firmao CRM 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.
Firmao CRM
Contact
Odoo CRM
res.partner
1:1Firmao Contact records (GET /svc/v1/contact) map to Odoo res.partner with company_type='contact'. We extract name, email, phone, address fields (street, city, postal_code, country) and resolve the parent company via companyName matching against Firmao Company records before inserting into Odoo, populating the parent_id lookup. Custom contact fields (customFields.customN) are mapped after the Odoo custom field definition is created during schema setup. Owner assignment is resolved via email matching against Odoo res.users.
Firmao CRM
Company
Odoo CRM
res.partner (company_type='company')
1:1Firmao Company records (GET /svc/v1/company) map to Odoo res.partner with company_type='company'. The company name becomes partner name, and address components (street, city, postal_code, country) are split into Odoo address fields. Company records are imported before Contacts so that parent_id lookups resolve at Contact insert time. Custom company fields follow the same dot-notation extraction and Odoo custom field pre-creation pattern as Contacts.
Firmao CRM
Deal
Odoo CRM
crm.lead
1:1Firmao Deals (GET /svc/v1/deal, available on Professional and above) map to Odoo crm.lead. We verify the customer's Firmao tier during scoping before attempting Deal extraction; accounts on Standard tier have no Deals to migrate. Deal name maps to crm.lead name, dealstage maps to stage_id (resolved via crm.stage name matching), and dealValue maps to planned_revenue. Owner is resolved by email. The Firmao subClass/subId envelope for deal-to-task associations is handled via a note on the crm.lead record until the Tasks phase inserts project.task records.
Firmao CRM
Task
Odoo CRM
project.task
1:1Firmao Tasks (GET /svc/v1/task) map to Odoo project.task. The subClass/subId envelope carries the associated dealId or contactId reference. We use dealName matching against the migrated crm.lead to resolve project_id on the task, and contactId to resolve the user_id or partner_id. Status (pending, inProgress, completed) maps to Odoo stage_id within a dedicated project.project created for the migration. Due dates and assignee are preserved directly.
Firmao CRM
Product
Odoo CRM
product.product
1:1Firmao Products (GET /svc/v1/product) map to Odoo product.product with name, default_code (product code), list_price, and standard_price preserved. The product's base fields migrate as-is. We create a corresponding product.template record alongside product.product per Odoo's internal architecture. Custom product fields (customFields.customN) follow the standard dot-notation extraction pattern.
Firmao CRM
Warehouse (subClass of Product)
Odoo CRM
stock.location + stock.quant
1:manyFirmao warehouse stock is not a standalone object — it returns as subClass=warehouse subId entries within the product GET response, carrying netPriceInStore and currentStoreState per warehouse. We extract each subId variant as a separate Odoo stock.location record with location_type='internal' and a corresponding stock.quant record for each product-location combination, setting the quantity from currentStoreState. This flattens the nested envelope structure into Odoo's flat stock management model.
Firmao CRM
User
Odoo CRM
res.users
1:1Firmao Users (GET /svc/v1/user) export as name, email, and role. We map the role string to an Odoo access rights group (for example, 'admin' maps to 'CRM Manager' group, 'user' maps to 'Sales' group). Owner assignments on Deals and Tasks are resolved by email match against the migrated res.users records. Users without a matching Odoo account enter a reconciliation queue for the customer's admin to provision before the record import resumes.
Firmao CRM
Custom Fields
Odoo CRM
ir.model.fields (custom)
lossyFirmao custom fields are defined in Professional and above under Settings and referenced in the API using dot-notation keys (customFields.custom5, customFields.custom12). There are no human-readable labels in the API response. We retrieve a sample record via GET first to enumerate which custom field keys are populated, then cross-reference against the customer's import documentation. Each active custom field key gets an Odoo ir.model.fields definition created before any data import begins, with the field type set to 'char' for string values. Empty custom fields in the sample export are flagged and excluded.
Firmao CRM
Tag / Label
Odoo CRM
res.partner.category
1:1Tags appear as a comma-separated property on Firmao Contact and Company records with no dedicated /tags endpoint. We extract the tag values as a list during export and create corresponding res.partner.category records in Odoo (or match to existing categories by name). Each Contact or Company receives res.partner.category assignments via res.partner.respartner_rel_m2m during import.
Firmao CRM
Pipeline Stages
Odoo CRM
crm.stage
lossyPipeline stages are not a standalone API object in Firmao — they are a property value on each Deal record. We export the distinct stage names from the Deal dataset and create corresponding crm.stage records in Odoo before Deal import begins. Stage sequence order and probability percentages are set on each stage. If the customer has custom stage names (not the Firmao defaults), we use those verbatim in Odoo.
Firmao CRM
Invoice Header
Odoo CRM
account.move
1:1Firmao Invoices (VAT invoices, bills, receipts, accounting notes) are accessible via the API with line items, tax codes, and payment status. We map invoice headers to Odoo account.move records with move_type='out_invoice' or 'in_invoice' depending on direction, and line items to account.move.line. Note that the full invoice financial workflow (payments, reconciliation, aged receivable reports) requires an Odoo Accounting configuration that is out of scope for the data migration itself.
Firmao CRM
Project (Professional+)
Odoo CRM
project.project
1:1Firmao Projects (available on Professional and above, with Gantt and Kanban views) migrate as project.project with name, description, and date_start. The project task associations map to the project.task records already migrated. The Gantt bar positions and Kanban column configuration are visual layout data that do not have a structural equivalent in Odoo's project.project model and are not migrated.
| Firmao CRM | Odoo CRM | Compatibility | |
|---|---|---|---|
| Contact | res.partner1:1 | Fully supported | |
| Company | res.partner (company_type='company')1:1 | Fully supported | |
| Deal | crm.lead1:1 | Fully supported | |
| Task | project.task1:1 | Fully supported | |
| Product | product.product1:1 | Fully supported | |
| Warehouse (subClass of Product) | stock.location + stock.quant1:many | Fully supported | |
| User | res.users1:1 | Fully supported | |
| Custom Fields | ir.model.fields (custom)lossy | Mapping required | |
| Tag / Label | res.partner.category1:1 | Fully supported | |
| Pipeline Stages | crm.stagelossy | Mapping required | |
| Invoice Header | account.move1:1 | Fully supported | |
| Project (Professional+) | project.project1: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.
Firmao CRM gotchas
Tier-gated objects cause silent import failures
Custom field keys are dynamic and not self-documenting
Parent-child object import order is mandatory
Warehouse stock state is subClass-embedded, not top-level
API login is auto-generated and tied to company ID
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 tier verification
We audit the source Firmao account across tier (Standard/Professional/Enterprise/Supreme), active API objects, custom field definitions (via sample record GET and customer documentation), pipeline stage names, owner list, and engagement volume. We also review the destination Odoo instance: edition (Community or Enterprise), installed modules (CRM, Sales, Project, Stock, Accounting), existing crm.stage records, and custom field definitions already present. The discovery output is a written migration scope confirming which objects are in scope, which are tier-gated and require upgrade confirmation, and which Odoo modules need activation before migration.
Schema design and Odoo custom field pre-creation
We design the Odoo destination schema before any data import. This includes creating ir.model.fields definitions for every Firmao custom field key found in the sample export, setting the field type to 'char' for string values, and assigning the fields to the correct model (res.partner, crm.lead, product.product). We also create crm.stage records matching the customer's Firmao pipeline stage names in the correct sequence order. Schema is deployed into the Odoo Sandbox or test environment first for validation.
Sandbox migration and reconciliation
We run a full migration into the Odoo Sandbox environment using a representative data sample. The customer reconciles record counts (Contacts in, Companies in, Deals in, Tasks in, Products in, stock.quant in), spot-checks 25-50 random records against the Firmao source, and signs off the schema and mapping before production migration begins. Any mapping corrections, custom field type adjustments, or stage name corrections happen in Sandbox, not in production.
Owner reconciliation and User provisioning
We extract every distinct owner referenced on Firmao Contact, Company, Deal, and Task records and match by email against the Odoo destination's res.users table. Owners without a matching Odoo User enter a reconciliation queue. The customer's Odoo admin provisions any missing Users before record import resumes, because OwnerId (user_id, user_ids) references on crm.lead, project.task, and res.partner must be valid at import time.
Production migration in dependency order
We run production migration in record-dependency order: res.users (provisioned, not migrated), res.partner for Companies (company_type='company'), res.partner for Contacts (company_type='contact' with parent_id resolved via companyName), crm.stage (stage definitions), crm.lead for Deals, product.template and product.product for Products, stock.location for each warehouse subId, stock.quant for each product-location quantity, project.project for Projects, project.task for Tasks, res.partner.category for Tags, account.move for Invoices. Each phase emits a row-count reconciliation report before the next phase begins.
Cutover, validation, and automation rebuild handoff
We freeze Firmao 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 active Firmao automation and process for the customer's Odoo admin to rebuild via Odoo Studio or a certified Odoo partner. We support a one-week hypercare window where we resolve any reconciliation issues. We do not rebuild Firmao automations as Odoo server actions or workflow rules inside the migration scope; that is a separate engagement or internal admin task.
Platform deep dives
Firmao CRM
Source
Strengths
Weaknesses
Odoo CRM
Destination
Strengths
Weaknesses
Complexity grading
Standard CRM migration. 2 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 Firmao CRM and Odoo CRM.
Object compatibility
2 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
Firmao CRM: Not publicly documented.
Data volume sensitivity
Firmao 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 Firmao CRM to Odoo CRM migration scoping. Not seeing yours? Book a call.
Walk through your Firmao CRM 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 Firmao CRM
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.