Invoice OCR for Odoo, without keying a single line.
Core Invoice reads supplier bills — every line, every tax, every total — and posts them straight into Odoo as draft vendor bills. Built for AP teams running Odoo Online or self-hosted who are tired of keying invoices by hand or fighting Odoo's built-in OCR.
Why Odoo's built-in OCR isn't enough
Odoo's Invoice Digitization module reads totals and a vendor name. It does not reliably extract per-line quantities, unit prices, or line-level taxes — which means your AP user is back to manual entry on every multi-line bill. Core Invoice extracts the full document:
- Supplier identity (name, tax ID, address)
- Bill metadata (number, date, due date, currency)
- Every line: description, quantity, unit price, line total
- Taxes per line and per invoice (rate, base, amount)
- Totals (subtotal, total tax, grand total)
- Payment terms and remittance details
On a typical 12-line vendor bill that's the difference between 45 seconds of clicking and a one-click "Validate" in Odoo.
How the Odoo connection works
- Create a dedicated integration user in Odoo. Don't reuse a real person's login — credentials change, people leave.
- Generate an API key. In Odoo: top-right avatar → My Profile → Account Security tab → New API Key. On Odoo Online this is required — your password will not work.
- Add the connection in Core Invoice with the base URL
(
https://your-host.odoo.com), database name (matches the subdomain on Odoo Online), the integration user's email, and the API key as the password. - Click Test. A successful response looks like
odoo <version> (db=<dbname>). - Optional: enable 3-way matching if your Odoo has the Purchase + Inventory modules. Configure price and quantity tolerances.
What gets posted in Odoo
Each extracted bill becomes a account.move record with
move_type = "in_invoice" in draft state.
That means your AP team always has the final say before anything
reaches your ledger.
Heads-up before your first push:
- Default expense account must be configured on the purchase journal (or on the vendor) — without it, Odoo refuses to validate the bill.
- Tax mapping: Core Invoice extracts the tax rate from the document, but Odoo posts a tax record ID. Until you wire up tax-rate-to-Odoo-tax-ID mapping in the connection settings, the AP user picks the tax on validation. This is a one-time configuration per company.
- Vendor matching: if the extracted vendor name or
tax ID matches a
res.partnerwithsupplier_rank > 0, we link it automatically. Unmatched vendors are flagged in review so you can either pick an existing partner or create a new one — we don't auto-create partners to avoid duplicate vendor records polluting your Odoo contacts.
3-way matching: PO ↔ receipt ↔ bill
If you run procurement through Odoo, every bill should reconcile against a purchase order and (for stockable products) a receipt. Core Invoice does this automatically when 3-way matching is enabled on the connection.
For each invoice line, we compare:
- Quantity against the PO line quantity (default tolerance: 0%)
- Unit price against the PO line price (default tolerance: 5%)
- Unit of measure — UoM drift is a hard fail
Mismatches are flagged with a status (mismatch_qty,
mismatch_price, mismatch_uom) and can
either warn (post anyway, leave a note) or
block (hold until resolved) based on your policy.
Tolerances are configurable per connection.
Auto-push when reviewed
Most AP teams want a two-step workflow: someone reviews extracted data on a phone or laptop, marks it reviewed, and the bill silently lands in Odoo. Toggle Auto-push on reviewed in the connection settings and that's what you get. Failed pushes get retried automatically and surfaced in the ERP push health log on the overview — they never block the review flip.
Multi-company Odoo
Each Odoo company in Core Invoice maps to its own ERP connection. That way you can have distinct credentials, tax mappings, default expense accounts, and matching policies per company — and the AP user for each entity only sees the bills routed to their workspace.
Security and credentials
Odoo credentials are encrypted with Fernet (server-side key) before they touch the database, and they are never logged or returned in any API response. Rotating the Fernet key re-encrypts every stored credential in place; rotating an Odoo API key requires updating the connection record but does not affect any extracted history.
Try it on a real bill
Sign in, drop in a vendor bill PDF, and watch it land in your Odoo as a draft — usually in under 10 seconds, including the API push.