Skip to content

Odoo ​

Odoo is an open-source suite of business apps covering CRM, sales, purchasing, inventory, accounting, projects, and HR.

ingestr supports Odoo as a source. It works with Odoo Online, Odoo.sh, and self-hosted Odoo servers.

URI format ​

plaintext
odoo://<host>?database=<database>&username=<username>&api_key=<api_key>

URI parameters:

  • host: the address of your Odoo server, such as mycompany.odoo.com or erp.example.com:8069.
  • api_key: an API key of the Odoo user to read as. On servers without API keys, the user's password works here too.
  • database: the Odoo database name. Required on Odoo 18 and older; on Odoo 19 and newer it is only needed when one server hosts several databases.
  • username: the login of the Odoo user. Required on Odoo 18 and older.
  • scheme: https (default) or http for servers without TLS.

ingestr uses the JSON-2 API on Odoo 19 and newer, and the JSON-RPC API on older versions.

Setting up an Odoo integration ​

  1. Log in to Odoo as the user that ingestr should read as. That user's access rights decide which records and fields ingestr can see.
  2. Open your avatar menu, then Preferences (or My Profile) → Account Security.
  3. Click New API Key, give it a name, and copy the key.

The external API is only available on Odoo Online's Custom plan; it is always available on self-hosted servers and Odoo.sh.

Here's a sample command that copies sale orders into a DuckDB database:

bash
ingestr ingest \
  --source-uri 'odoo://mycompany.odoo.com?database=mycompany&username=me@example.com&api_key=key_123' \
  --source-table 'sale_orders' \
  --dest-uri duckdb:///odoo.duckdb \
  --dest-table 'odoo.sale_orders'

Tables ​

Every table has the primary key id and uses the merge strategy keyed on write_date, Odoo's last-modified timestamp. Archived records are included.

TableOdoo modelDetails
partnersres.partnerCustomers, vendors, and contacts
partner_categoriesres.partner.categoryContact tags
usersres.usersUsers
companiesres.companyCompanies
currenciesres.currencyCurrencies
currency_ratesres.currency.rateCurrency exchange rates
countriesres.countryCountries
product_categoriesproduct.categoryProduct categories
product_templatesproduct.templateProduct templates
productsproduct.productProduct variants
uomsuom.uomUnits of measure
pricelistsproduct.pricelistPricelists
sale_orderssale.orderQuotations and sales orders
sale_order_linessale.order.lineSales order lines
purchase_orderspurchase.orderRequests for quotation and purchase orders
purchase_order_linespurchase.order.linePurchase order lines
crm_leadscrm.leadLeads and opportunities
crm_stagescrm.stageCRM pipeline stages
crm_teamscrm.teamSales teams
account_movesaccount.moveInvoices, bills, and journal entries
account_move_linesaccount.move.lineJournal items
account_paymentsaccount.paymentPayments
accountsaccount.accountChart of accounts
journalsaccount.journalAccounting journals
taxesaccount.taxTaxes
payment_termsaccount.payment.termPayment terms
analytic_linesaccount.analytic.lineAnalytic lines and timesheets
stock_pickingsstock.pickingTransfers (receipts, deliveries)
stock_movesstock.moveStock moves
stock_move_linesstock.move.lineDetailed stock move lines
stock_quantsstock.quantOn-hand quantities per location
stock_locationsstock.locationStock locations
warehousesstock.warehouseWarehouses
projectsproject.projectProjects
project_tasksproject.taskProject tasks
project_task_stagesproject.task.typeTask stages
employeeshr.employeeEmployees
departmentshr.departmentDepartments
jobshr.jobJob positions
activitiesmail.activityScheduled activities
messagesmail.messageChatter messages and notes

A table is only available when the Odoo app that provides it is installed, such as Sales for sale_orders or Inventory for stock_pickings.

Any other model, including custom and Studio models, can be read by passing its technical name as the table, such as --source-table 'fleet.vehicle' or --source-table 'x_vehicles'.

Each table contains the model's stored fields. Many-to-one fields hold the ID of the related record, many-to-many fields hold a JSON array of IDs, and one-to-many and binary (attachment and image) fields are left out. Timestamps are in UTC.

Records deleted in Odoo are not removed from the destination by incremental runs; use --full-refresh to rebuild a table.