← All integrations
Odoo → Salesforce

Odoo Salesforce integration

In short

An Odoo to Salesforce integration keeps your ERP and your CRM describing the same customer at the same time. Odoo partners, sales orders, invoices, products, and delivery status are matched to Salesforce Accounts, Contacts, Orders, and price book entries by stable external IDs and upserted through the Salesforce API, while Salesforce keeps the sales-facing view of fulfilment and billing that Odoo owns. Done properly it is not a nightly CSV push: it is an idempotent, delta-driven pipeline that respects Salesforce API limits, multi-currency, and referential order so nobody re-keys a won deal into the ERP.

What an Odoo to Salesforce integration actually does

Salesforce is where your sales team lives: leads, opportunities, forecasts, the story of how a deal was won. Odoo is where that deal becomes real: the confirmed sales order, the stock reservation, the delivery, the customer invoice, the payment. The moment a deal closes, the same customer exists in two systems that were never designed to agree with each other.

An Odoo to Salesforce integration closes that gap automatically. It keeps the customer master aligned, pushes the operational truth Odoo owns - order confirmed, goods shipped, invoice raised, balance outstanding - back into Salesforce where account managers can see it, and does it without anyone exporting a spreadsheet or re-typing a won opportunity into the ERP. Sales stops asking operations “did that order actually ship”, because Salesforce already shows it.

What data moves

Odoo object / eventBecomes in SalesforceNotes
Company partner (res.partner, is_company)AccountMatched by a stable External ID; upserted, never blind-inserted
Individual partner / contactContact linked to its AccountParent Account must exist first, so ordering matters
Confirmed sales order (sale.order)Order (or Opportunity update)Only on state = sale; draft quotations are not pushed
Order lines (sale.order.line)OrderItem / OpportunityLineItemRequires a matching Product2 and PricebookEntry to exist
Product (product.product)Product2 + PricebookEntryPrice book and currency mapped from the Odoo pricelist
Customer invoice (account.move)Invoice / custom billing objectStatus and amount due surfaced for account visibility
Delivery (stock.picking)Order fulfilment status fieldSales sees shipped / partially shipped without ERP access

The exact field mapping, the External ID fields, and which side wins on a conflict are agreed once during design and encoded in the pipeline. After that, nobody maps a field by hand again.

The details that break naive syncs

A point-and-click connector or a nightly CSV push gets you a demo that works and a production system that drifts. The expensive parts are specific to this pair:

How we build and run it

We treat this as a pipeline, not a scheduled export. Changed Odoo records are read on a schedule via RPC using write_date deltas, validated, transformed into your agreed Salesforce shape, and upserted through the REST or Bulk API by their External ID. Where Salesforce is the source for a given object, Change Data Capture drives the flow the other way. Writes are sequenced so parents exist before children.

The pipeline is idempotent: every record carries a stable identifier and is upserted, so a retry or a re-run updates in place and never spawns a duplicate Account or a second Order. It runs on cloud-native, fully EU-hosted AWS infrastructure, so partner and order data never leaves the EU, which keeps your DPA / AVV and GDPR obligations clean.

Then we keep it running. Monitoring, alerting, incident response, and - critically - watching for Odoo upgrade changes and Salesforce API version deprecations are our responsibility under contract. You get a named owner and an SLA. Revenue operations stops depending on a middleware flow that only one person understood.

When this integration is worth building

If a handful of deals a month cross from Salesforce into Odoo and someone re-keys them in five minutes, that manual step is genuinely fine and we will tell you so. A native connector app may also be enough when your objects are standard and your volume is low.

The integration earns its place when deal volume makes re-keying a real cost, when duplicate Accounts and stale fulfilment status start eroding trust in Salesforce, when multi-currency or multi-company Odoo makes the mapping non-trivial, or when you need the whole thing owned and operated by someone accountable rather than maintained by whoever set up the last automation.

Frequently asked questions

Which system should own which data, Odoo or Salesforce?
Usually Salesforce owns the pipeline (leads, opportunities, sales activity) and Odoo owns everything after the deal is won - the confirmed sales order, inventory, invoicing, and fulfilment. The customer master (partner versus Account) is the one record both sides touch, so we agree a single source of truth for it up front and let the other system receive updates. Getting that ownership map right is most of the design work.
Does Odoo support webhooks, or do you have to poll it?
Odoo has no general-purpose outbound webhook system. Recent versions add limited webhook actions, but in practice we read changes from Odoo over its XML-RPC or JSON-RPC API using the write_date field as a delta marker, and we push into Salesforce through its REST and Bulk APIs. Salesforce can notify us the other way via Change Data Capture or Platform Events. We pick per object rather than forcing one mechanism on both systems.
How do you stop duplicate Accounts and Contacts appearing in Salesforce?
Every Odoo record is matched to Salesforce by a stable external ID stored in a dedicated External ID field, and we write through Salesforce upsert rather than insert. That means a re-run updates the existing Account instead of creating a second one. Where the two systems already hold overlapping customers, we run a one-time reconciliation against your existing Salesforce duplicate rules before the pipeline goes live.
Will this blow through our Salesforce API limits?
It will not, because we design for them. High-volume writes go through the Salesforce Bulk API 2.0 rather than one REST call per record, deltas keep the volume proportional to what actually changed rather than a full reload, and the pipeline backs off and retries on limit errors instead of failing the batch. We size the expected daily call budget with you before build.
Who operates it after go-live?
We do. The pipeline runs on cloud-native, fully EU-hosted infrastructure that we monitor. If Odoo changes its RPC behaviour on an upgrade or Salesforce deprecates an API version, that is our problem to fix under contract, not a surprise your revenue operations team discovers when orders stop flowing. You get a named owner, alerting, and an SLA rather than a middleware recipe nobody maintains.

Need this integration built and permanently operated? Tell us which systems connect and what data has to move. Fixed-price scoping quote within 48 hours.

Request a scoping call