ml-connector
OdooExpensify

Odoo and Expensify integration

Odoo runs your enterprise accounting, purchasing, and HR. Expensify collects and approves employee expenses and corporate card transactions. Connecting the two keeps your general ledger current with every approved expense report without manual re-keying. Approved expenses in Expensify flow into Odoo as journal entries, allocated to the GL accounts and cost centers configured in your Odoo policies. ml-connector handles the different APIs on each side, deduplicates expense records, and maintains an audit trail.

How Odoo works

Odoo is an open-source ERP suite available as Odoo Online (SaaS), Odoo.sh (PaaS), or self-hosted, covering accounting, purchasing, inventory, HR, and CRM. It exposes invoices, purchase orders, payments, employees, GL accounts, and analytic accounts through XML-RPC and JSON-2 REST APIs. Odoo authenticates with an API key paired with a username, and the base URL depends on the deployment: Odoo Online uses https://<subdomain>.odoo.com, Odoo.sh uses https://<subdomain>.odoo.sh, and self-hosted installations use a custom domain. Odoo has no production-grade webhooks, so external systems must poll using write_date filters to capture recent changes.

How Expensify works

Expensify is a cloud-based expense-management platform that tracks employee expenses, manages approval workflows, and reconciles corporate card transactions. It publishes expense reports, approved expenses, employees, policies, and corporate card data through a REST API that accepts JSON payloads via POST to https://integrations.expensify.com/Integration-Server/ExpensifyIntegrations. Expensify authenticates with a partner user ID and partner user secret passed inline with every request. The API supports polling only, with no webhooks or sandbox environment; all API calls run against production data. Expensify stores GL account codes as properties of expense categories and uses tags as accounting dimensions such as project, cost center, and class.

What moves between them

Approved expense reports from Expensify are polled on a scheduled basis and posted into Odoo's accounting module as journal entries. Each Expensify expense is mapped to an Odoo GL account based on the expense category and merchant name, and the journal entry is allocated to the cost center specified in the Expensify report. Employee names are matched between the two systems to attach expenses to the correct Odoo HR record. The flow is unidirectional from Expensify into Odoo; Odoo GL entries are read-only in Expensify, so ml-connector does not write GL transactions back to the expense platform.

How ml-connector handles it

ml-connector stores both credential sets encrypted: the Odoo API key and the Expensify partner user ID and secret. On each poll cycle, it queries Expensify for expense reports in an approved or ready-to-post state, filters by date range to avoid re-processing, and fetches the detailed expenses for each report. For each expense, it matches the merchant name and Expensify category to an Odoo GL account and cost center configured in your integration rules. The journal entry is then posted to Odoo via its JSON-2 REST API or XML-RPC, and the deduplication key is the Expensify expense ID to prevent duplicate postings if a poll cycle retries. Because Expensify has no sandbox, testing uses production expense reports marked as drafts and deletes them after verification. Polling is scheduled based on your expense approval cycle, not real-time, so journals typically post within hours of final approval. Every transaction carries an audit trail showing the source Expensify report ID, the posting timestamp, and any remapping that occurred.

A real-world example

A professional services firm with 50 consultants uses Expensify to manage project expenses and corporate card receipts, and Odoo as the accounting system. Before integration, the finance team exported expense reports from Expensify each week, manually re-entered totals by project and cost center into Odoo journals, and chased down merchant name mismatches. With Odoo and Expensify connected, approved expense reports post to Odoo automatically, allocated to the correct project cost centers. The finance team now spends less time on manual entry and more time on exceptions like unapproved expenses or miscoded merchant categories.

What you can do

  • Post approved Expensify expense reports to Odoo as journal entries, allocated to the correct GL accounts and cost centers.
  • Map Expensify merchant names and expense categories to Odoo GL accounts using configurable rules.
  • Match employee records in Expensify and Odoo so expenses attach to the correct person and cost center.
  • Deduplicate expense records by Expensify expense ID to prevent duplicate postings across poll cycles.
  • Poll Expensify on a schedule tied to your approval workflow, with full audit trail and error replay for missed transactions.

Questions

Which direction does data move between Odoo and Expensify?
Data flows from Expensify into Odoo only. Approved expenses and expense reports are posted to Odoo as journal entries and allocated to GL accounts and cost centers. Odoo GL entries are read-only in Expensify, so ml-connector does not write financial data back to the expense platform.
How does the integration map Expensify expenses to Odoo accounts and cost centers?
Each Expensify expense category is mapped to an Odoo GL account, and the report's cost center or project tag is matched to an Odoo analytic account. ml-connector uses configurable rules to handle merchant name variations, so the same vendor across multiple Expensify reports always posts to the same Odoo account.
How often do expense reports post from Expensify into Odoo?
Polling runs on a schedule you configure, typically tied to your expense approval cycle (daily, twice weekly, or weekly). Because Expensify has no webhooks, ml-connector polls for approved reports at each interval and posts any new expenses immediately. Every transaction is logged with the source report ID and posting timestamp for audit trail purposes.

Related integrations

Connect Odoo and Expensify

Free to use. Add your credentials, ping your real systems, and see if we fit.

Get started