BFBambooForge Labs

EspoCRM Connector

Sync EspoCRM accounts, contacts, leads and opportunities into Odoo over the REST API, with a sync control tower and field-mapping studio.

Buy on the Odoo Apps StoreOpen the live demoSales€104Community & Enterprise

Available for Odoo 16.0, Odoo 17.0, Odoo 18.0, Odoo 19.0. Technical name bambooforge_espocrm_connector.

Odoo 16.0Odoo 17.0Odoo 18.0Odoo 19.0
Full walkthrough on a live Odoo 19.0 database, with subtitles. It ends with what this app deliberately does not do.

EspoCRM Connector

A read-only, import-first bridge from EspoCRM into Odoo 18: pull your Accounts, Contacts, Leads and Opportunities into native Odoo contacts and CRM records over the EspoCRM REST API — with a resilient job queue, dry-run safety, pre-flight validation and rollback so you stay in control. The connector never writes back to EspoCRM.

This page is the complete manual. If you follow it top to bottom you can install, connect, run your first import, automate it, and fix the common issues without contacting support.

Overview

The connector reads from EspoCRM over its REST API and creates/updates the matching Odoo records. It is one-way only — Odoo ← EspoCRM (pull). Nothing is ever written back to EspoCRM.

It covers four EspoCRM source entities mapped onto two Odoo models:

EspoCRM entity

Lands in Odoo as

Notes

Account

res.partner (company)

Imported as a company contact (is_company = True).

Contact

res.partner (individual)

Imported as an individual, linked to its account where available.

Lead

crm.lead (type Lead)

The raw EspoCRM status is kept on the record.

Opportunity

crm.lead (type Opportunity)

Amount, close date, probability and the raw EspoCRM stage are kept.

Because four EspoCRM entities map onto only two Odoo models, the connector is keyed by the EspoCRM entity end to end. Accounts and Contacts never collide on res.partner, and Leads never collide with Opportunities on crm.lead.

Every remote call goes through a queue: nothing is written to Odoo until a job runs, jobs retry with back-off on transient failures, and a circuit breaker pauses an instance that keeps failing.

Requirements

  • Odoo: 18.0, Community or Enterprise. The connector depends on Contacts (contacts) and CRM (crm), which install automatically.

  • EspoCRM: any EspoCRM server exposing the standard REST API at /api/v1. The connector uses only generic list and single-record endpoints, so it is version-tolerant. EspoCRM must be reachable from the Odoo server.

  • Python: no extra libraries beyond a standard Odoo 18 install.

  • Odoo access: any internal user can open the connector screens. The EspoCRM API key and webhook secret are stored in system-only fields, so only a Settings / Administration user can read or change them.

  • Network: outbound HTTPS from Odoo to your EspoCRM server. By default the connector refuses internal/loopback/private hosts as an SSRF safeguard (see Safety features).

Installation

  1. Copy bambooforge_espocrm_connector into your Odoo addons path.

  2. Restart the Odoo service.

  3. Open Apps, click Update Apps List, search for EspoCRM, and press Activate / Install. Dependencies (Contacts, CRM) install automatically.

No EspoCRM server is required to evaluate the connector: a mock EspoCRM REST API ships inside the module, so you can install, explore and run the full import flow against sample data before pointing it at a real server. To use it, set the instance Base URL to <your-odoo-url>/espocrm/mock_api with API Path api/v1 and any non-empty API key.

Step 1 — Create an API key in EspoCRM

The connector authenticates with a single API key, sent as the X-Api-Key header on every request. There is no OAuth and no token exchange. Create a read-capable API user in EspoCRM:

  1. Sign in to EspoCRM as an administrator.

  2. Go to Administration ▸ API Users.

  3. Click Create API User.

  4. Set Authentication Method to API Key. EspoCRM generates the key for you.

  5. Give the API user read access to Accounts, Contacts, Leads and Opportunities via its Roles (read-only is enough — the connector never writes to EspoCRM).

  6. Save, then copy the generated API Key. You will paste it into Odoo in Step 2.

Keep the key somewhere safe; EspoCRM shows it on the API user record, but treat it like a password.

Step 2 — Create the connection in Odoo

Open EspoCRM Connector ▸ Configuration ▸ Instances and create a record. The fields that matter:

Field

What to enter

Name

A label for this server, e.g. Production EspoCRM. Must be unique per company.

Company

The Odoo company that owns the imported records.

Base URL

Your EspoCRM server root, e.g. https://crm.example.com. For the bundled demo, use <your-odoo-url>/espocrm/mock_api.

Authentication

API Key — the only supported method. The key is sent as the X-Api-Key header.

API Key

The key from Step 1 (visible to administrators only).

API Path

The REST path. Leave the default api/v1 unless your server differs.

Verify SSL

Keep on for production. Turn off only for self-signed test certificates.

Allow internal host

Off by default. Turn on only to reach an EspoCRM on localhost or a private network (this lowers the SSRF guard — see Safety features).

Timeout (s)

HTTP timeout per request. Default 30.

Then click Test Connection. The connector calls a lightweight EspoCRM endpoint (App/user, falling back to a one-row Account list) and, on success, sets the state to Connected and seeds default Lead/Opportunity status mappings. If it fails, the exact error is stored on the form (last connection error) and recorded in Logs (see Troubleshooting).

Tip: use Quick Setup (button on the instance) to pick a use case and apply a recommended set of auto-import toggles and a safety profile in one step.

Step 3 — First import (dry-run, then live)

New instances start with Dry-run ON. In dry-run, import jobs simulate writes: instead of creating or changing Odoo records they produce Validation Results you can review under EspoCRM Connector ▸ Operations ▸ Validation Results. This lets you confirm what would happen before anything is written.

To run a first import:

  1. On the instance, open the Import tab and click Queue Account Import (and/or Queue Contact Import, Queue Lead Import, Queue Opportunity Import). This enqueues jobs; it does not block the UI.

  2. Jobs are processed by the Espocrm Queue Processor scheduled action (every minute), or immediately if you trigger it from Operations ▸ Queue Jobs.

  3. Review Validation Results while still in dry-run.

  4. When satisfied, open the instance, turn Dry-run OFF, and run the imports again to write the records for real.

Imported records land in the standard Odoo apps:

  • Accounts and Contacts → Contacts (companies and individuals).

  • Leads and Opportunities → CRM (the pipeline; Leads as type Lead, Opportunities as type Opportunity).

Each imported record is tracked by a binder keyed on the EspoCRM entity and remote id, so re-imports update the same Odoo record instead of duplicating it.

Field mapping & customization

  • Field Mappings (Configuration ▸ Field Mappings) map EspoCRM source fields to Odoo target fields, per EspoCRM entity, in the EspoCRM → Odoo direction. Click Suggest Mappings on the instance to seed the business-critical defaults, then adjust. Out of the box the suggested mappings include, for example:

    Entity

    EspoCRM source path

    Odoo target field

    Account

    name / website / emailAddress / phoneNumber

    name / website / email / phone

    Contact

    name / emailAddress / phoneNumber

    name / email / phone

    Lead

    name / emailAddress / accountName

    name / email_from / partner_name

    Opportunity

    name / amount / probability

    name / expected_revenue / probability

  • Per-field transforms: each mapping can coerce values (String, Integer, Float, Boolean, Uppercase/Lowercase, JSON String, CSV Join, First Item) or run a safe Python Expression (variables value and default_value). A Preview shows the result on a sample input before you save.

  • Schema Fields (Configuration ▸ Schema Fields) lists the discovered EspoCRM fields per entity alongside the Odoo target fields. Click Schema Introspection on the instance to refresh it; the connector samples a live record (or the bundled mock when the API is unreachable) and flattens its shape.

  • Suggest Mappings vs Schema Introspection: run introspection first if you want the intelligent suggestions (name/type similarity scored) rather than only the core blueprint set.

Automation (scheduled actions)

The module ships these scheduled actions (Settings ▸ Technical ▸ Scheduled Actions):

Scheduled action

Default

Purpose

Espocrm Queue Processor

every 1 min

Processes queued import jobs.

Espocrm Reconciliation

every 15 min

Pulls recent remote records for entities with auto-reconcile enabled and re-queues any that are missing or previously failed.

Espocrm Maintenance

every 1 hr

Recovers stale/locked jobs and trims old jobs and logs (per the retention settings).

Espocrm Flow Scheduler

every 5 min

Runs scheduled import flows.

Espocrm Flow Metrics

every 1 hr

Aggregates flow-run metrics.

Espocrm Auto Recover

every 15 min

Reopens a tripped circuit breaker once the cooldown passes and no blocking validation issues remain.

Turn on Auto-import / Auto-reconcile per entity on the instance (Accounts, Contacts, Leads, Opportunities) to let the scheduled actions keep things in sync hands-free.

Webhooks (not used in this version). EspoCRM can emit outbound webhooks, but wiring them into the import queue is a roadmap item. A route at /espocrm/webhook exists only so that existing subscriptions or health checks do not return 404 — it acknowledges with HTTP 200 and imports nothing. Do not rely on it to bring in data; use the scheduled import and reconciliation actions instead.

Safety features

  • Dry-run mode (dry_run_mode, ON by default) — import jobs simulate writes and produce Validation Results to review before you go live.

  • Pre-flight validation (validation_enabled) with Minimal / Standard / Strict business-validation profiles — gates risky writes; Standard is the default. Use Run Validation Sweep to validate pending/failed jobs on demand, and Auto-fix Open Issues to clear the ones the connector can resolve.

  • Resilient queue — every import is a job with retry and configurable back-off (fixed or exponential), plus a dead-letter state for jobs that exhaust their retries.

  • Circuit breaker (circuit_state: Open / Protected / Tripped) — after repeated failures (default threshold 5), or immediately on an auth/configuration error, the instance auto-pauses (Tripped). The Espocrm Auto Recover action reopens it after a 30-minute cooldown, or click Resume Sync.

  • Rollback snapshots (rollback_enabled) — imports capture a snapshot so you can undo a batch from Operations ▸ Rollback Snapshots.

  • SSRF guard — the connector refuses internal/loopback/private/reserved hosts (including cloud metadata addresses) for the Base URL unless Allow internal host is explicitly enabled.

  • Safety profilesConservative / Balanced / Aggressive presets set dry-run, validation, batch size and delete strategy together; click Apply Safety Profile.

  • Credential isolation — the API key and webhook secret live in system-only fields, readable and editable only by administrators.

Troubleshooting

Symptom

Cause and fix

Test Connection fails with 401/403

Wrong or missing API key, or the API user lacks read access. Re-check Step 1 and the API Key field; confirm the API user's role grants read on Accounts/Contacts/ Leads/Opportunities.

"Base URL is not allowed … non-public address"

The Base URL points at localhost or a private/reserved IP. For a self-hosted server, enable Allow internal host on the instance (test/self-hosted only).

SSL errors on Test Connection

Self-signed or invalid certificate. Use a valid cert, or turn off Verify SSL for testing only.

"EspoCRM resource not found" / 404

Wrong API Path or Base URL. The default path is api/v1; the connector calls <base>/api/v1/<Entity>. Confirm the server root has no trailing path.

"EspoCRM rate limit reached" (429)

The server is throttling. The client retries with back-off automatically; lower the per-entity import limit or raise API retry settings if it persists.

Jobs stay in Pending

The Queue Processor is off or the instance is paused. Confirm the Espocrm Queue Processor scheduled action is active and the instance is not Paused.

Instance shows Tripped

The circuit breaker tripped after repeated failures (or an auth error). Fix the server/credentials; Auto Recover reopens it after cooldown, or click Resume Sync.

Nothing is written after Import

You are in Dry-run. Review Validation Results, then turn dry-run off and re-run the import.

Records imported twice

Imports are keyed by EspoCRM entity + remote id via the binder, so this should not happen. If it does, check that two instances do not point at the same EspoCRM server.

Jobs end up Dead

They exhausted their retries. Open Operations ▸ Queue Jobs (Dead Letter), read the error on the job and in Logs, fix the cause, then re-queue.

For anything else, Operations ▸ Logs records every API call, payload and error with a timestamp.

Frequently asked questions

Does this connector write anything back to EspoCRM? No. It is read-only and import-first: it lists and fetches records from EspoCRM and creates or updates the matching Odoo records. Write-back to EspoCRM is a roadmap item.

Which versions are supported? Odoo 18.0 on the Odoo side. On the EspoCRM side the connector uses only the generic /api/v1 list and single-record endpoints, so it is version-tolerant. Validate your exact build with the bundled mock first.

Do I need an EspoCRM server to evaluate it? No. A mock EspoCRM REST API ships inside the module. Point the Base URL at <your-odoo-url>/espocrm/mock_api (API Path api/v1, any API key) to run the full import flow against sample data.

How does authentication work? A single API key sent as the X-Api-Key header. Create an API user with API-Key authentication under Administration ▸ API Users in EspoCRM. No OAuth, no tokens.

Where do Leads and Opportunities end up? Both land in the CRM pipeline as crm.lead records — Leads as type Lead, Opportunities as type Opportunity (with amount, close date, probability and the raw EspoCRM stage).

Is it safe to run against production data? Yes. Dry-run is ON by default, validation gates risky writes, and rollback snapshots let you undo a batch. You decide when to go live.

Does it support real-time webhooks? Not in this version. Real-time inbound webhooks are a roadmap item; the /espocrm/webhook route exists only to avoid 404s and imports nothing. Use the scheduled import and reconciliation actions instead.

What support and refund policy do I get? Every request is answered within 24 hours, setup help included. If you report a bug within 2 months of purchase and it is not resolved within 15 days, you are entitled to a full money-back refund.

Data, privacy & limits

  • The connector reads Accounts, Contacts, Leads and Opportunities from your EspoCRM server and writes the corresponding Odoo res.partner and crm.lead records. It never writes, updates or deletes anything in EspoCRM.

  • Credentials (API key, webhook secret) are stored in administrator-only fields.

  • In scope today: read-only import of the four entities, per-field mapping with transforms, schema introspection, dry-run + validation + rollback, a resilient queue, and scheduled import/reconciliation.

  • Out of scope / roadmap: write-back to EspoCRM, inbound webhooks (the route is a no-op), and incremental modifiedAt filtering (v1 lists by maxSize/offset).

Support & updates

  • Support: support@bambooforge.dev — answered within 24 hours, setup help included.

  • Refund: report a bug within 2 months of purchase; if unresolved within 15 days, full refund.

  • Full source is included. Updates track the supported Odoo 18 / EspoCRM REST api/v1 line.

Upgrading & version compatibility

This build targets Odoo 18.0. Each Odoo major series (17.0, 18.0, 19.0) has its own dedicated build of this module — always install the build that matches your Odoo version. Mixing a build with a different Odoo series is not supported.

Patch upgrades (same series, e.g. 18.0.1.0.0 → later)

  1. Back up your database and filestore first.

  2. Replace the module folder with the newer build.

  3. Restart Odoo with the module updated:

    ./odoo-bin -c your.conf -u bambooforge_espocrm_connector -d your_db
  4. Odoo applies any schema/data changes automatically. Your existing records and configuration are preserved.

Cross-version migration (e.g. Odoo 17 → 18)

Upgrading Odoo itself is a database migration handled by Odoo's standard upgrade tooling. When you migrate the database to the next Odoo series, install the matching build of this module for that series. Data created by this module carries over with the database migration.

After any upgrade the module's scheduled actions resume on their normal cadence — no manual re-activation is required.

Uninstallation

You can remove this module at any time from Apps → (this module) → Uninstall, or from the command line. Uninstalling is clean and reversible by reinstalling — but note what is and is not deleted.

What is removed

  • The module's own tables and every record in them (20 models, prefixed espocrm.*) — this is the data this module created.

  • The menus, actions, views and reports this module installed.

  • Its scheduled actions (cron jobs) — they stop immediately on uninstall.

  • Connection records, credentials, field mappings, queue jobs and sync logs stored in Odoo.

What is preserved

  • Your remote platform is never touched. Uninstalling only removes the Odoo-side connector; products, customers and orders on the external store/service are untouched.

  • Records already imported into standard Odoo models (e.g. contacts, products, sales orders) remain — they are ordinary Odoo records once created.

  • Attachments and chatter messages on standard records are kept.

As always, take a database backup before uninstalling in production.

Changelog

18.0.1.0.0

Current release for Odoo 18.0. This build includes:

  • Sync EspoCRM accounts, contacts, leads & opportunities into Odoo 18 over the REST API.

  • Now with a live Sync Control Tower, bulk dead-letter & conflict consoles and a field-mapping studio. Read-only against EspoCRM, resilient queue, dry-run safety, auditable source.

Feature additions and fixes ship as new builds on the Odoo Apps store; this page and the module's version reflect the current published release. Always keep the build matched to your Odoo series (see Upgrading & version compatibility).

Screens

Video poster operations - bambooforge_espocrm_connector
Video poster operations
Video poster - bambooforge_espocrm_connector
Video poster