Skip to main content

OpenCart Store Management

OpenCart Store Management connects a self-hosted OpenCart storefront to Odoo. This page is the installation and configuration guide for the module you downloaded from your ECOSIRE dashboard. Everything below describes the opencart_store_management module as it ships today.

Technical nameopencart_store_management
Odoo versions17.0, 18.0, 19.0 (Community or Enterprise)
Current shipped version17.017.0.2.3.3, 18.018.0.2.3.3, 19.019.0.2.3.3
Price$499 USD — one-time, per Odoo version
Odoo module licenseOPL-1
CategoryConnector

Video guides

Watch the connector in action before you read on. All three videos were recorded on a live Odoo 19 instance connected to a real OpenCart store.

Overview (1:20)

Feature tour (3:35)

Step-by-step setup guide (5:54)

Prefer YouTube? The playlist is on the ECOSIRE channel: https://www.youtube.com/@ecosire

Requirements

RequirementDetail
Odoo17.0, 18.0 or 19.0, Community or Enterprise. Self-hosted or Odoo.sh — Odoo Online (SaaS) cannot install third-party modules
Odoo appsbase, sale_management, stock, account, delivery, mail, web, product, contacts — Odoo installs any that are missing
Python packagesrequests
OpenCart storeA self-hosted OpenCart 3.x or 4.x storefront, reachable over HTTPS from the Odoo host
OpenCart API userAn API user created in System → Users → API, enabled, with the Odoo server's IP on its allow-list
OpenCart REST Admin extensionRequired for product, order and customer sync — see OpenCart's API is not enough on its own

Install the Python packages into the same interpreter that runs Odoo:

sudo -u odoo pip install requests

Installation

1. Obtain the archive for your Odoo version

Use the 17.0.2.3.3, 18.0.2.3.3, or 19.0.2.3.3 archive that matches the Odoo major version you operate. Direct ECOSIRE customers can obtain the applicable archive from their dashboard; Odoo App Store customers use the delivery path provided with their purchase.

2. Extract into your addons path

unzip opencart_store_management_v19_*.zip -d /opt/odoo/addons/
ls /opt/odoo/addons/opencart_store_management/__manifest__.py # sanity check

The archive contains a single top-level opencart_store_management/ directory. If the ls check fails, the module folder ended up one level too deep — move it up so __manifest__.py sits directly inside opencart_store_management/.

3. Restart Odoo and install

sudo systemctl restart odoo
  1. Go to Apps and click Update Apps List (developer mode must be on).
  2. Search for OpenCart Store Management and click Install.
  3. Odoo installs the listed Odoo app dependencies automatically.

When the install finishes, an OpenCart menu appears in the main Odoo app switcher.

Configuration

Connect to OpenCart

Open OpenCart → Configuration and create a record (model opencart.instance). The connection fields are:

LabelTechnical nameRequiredValues
store_urlYesText
api_keyYesText
api_secretYesText

Where the Label column shows —, the module does not set an explicit label and Odoo derives one from the technical name, so the wording on screen may differ slightly. The technical name is the reliable identifier.

OpenCart issues API credentials from System → Users → API in its own admin — see docs.opencart.com/en-gb. Create the API user, click Generate for the key, set Status to enabled, and add the Odoo server's IP under the IP Addresses tab. The connector talks to your own store — the Store URL you enter on the instance.

Set OpenCart Version to match your storefront (3.x or 4.x). This selects how request URLs are built; from 2.2.4 the connector uses the universal index.php?route=api/... form and auto-detects the clean /api/... form on stores that front it with a rewrite, so a mismatch here no longer breaks every call.

OpenCart's API is not enough on its own

Creating the API user is necessary but not sufficient. Core OpenCart ships no data API for the records this connector syncs: there is no product API controller in OpenCart 3.0.3.9, 4.0.2.3 or master, and the customer and order controllers that do exist in core are checkout-session mechanics — they attach a customer to the current guest cart and drive storefront checkout. They do not read or write your catalogue, order book or customer list.

Product, order and customer sync therefore require the third-party REST Admin extension (opencart-api.com), which adds the admin-side routes below and issues the bearer token you enter on the instance.

If you are evaluating a different extension, check it against the exact routes this connector calls — anything missing is a feature the connector cannot perform on your store:

AreaRoutes called
Authenticationapi/login
Productsapi/product, api/product/info/{id}, api/product/add, api/product/edit/{id}, api/product/delete/{id}
Categoriesapi/category
Stockapi/product/edit/{id}, api/product/stock/bulk
Ordersapi/order, api/order/info/{id}, api/order/history/{id}
Customersapi/customer, api/customer/info/{id}, api/customer/add, api/customer/edit/{id}
Returnsapi/return
Store & reportsapi/setting/store, api/report/sale, api/modification

An extension exposing only products and categories can drive a one-way catalogue push and nothing else — no orders, no customers, no returns, no stock. Prefer one that authenticates with a token rather than your admin username and password, so your OpenCart admin login is never stored in Odoo.

When the fields are filled in, click Test Connection. The record's status moves to connected only when the platform answers successfully — do not run a first import until it does.

Scheduled actions

The module installs 4 scheduled actions (Settings → Technical → Scheduled Actions):

Scheduled actionRuns everyEnabled on install
OpenCart: Sync Products30 minutesYes
OpenCart: Sync Orders15 minutesYes
OpenCart: Sync Customers60 minutesYes
OpenCart: Process Queue Jobs5 minutesYes

Intervals above are the shipped defaults. Adjust them to your volume — but be aware that the platform, not Odoo, sets the API rate limits, and shortening a sync interval is the usual cause of throttling errors in the logs.

Using the module

The OpenCart menu is laid out as:

  • OpenCart → Automation Dashboard
  • OpenCart → Configuration — OpenCart Instances, Cron Jobs, Webhooks
  • OpenCart → Products — Products
  • OpenCart → Orders — Orders
  • OpenCart → Customers
  • OpenCart → Operations — Queue Jobs, Logs
  • OpenCart → Tools — Manual Sync

A normal first run is:

  1. Test Connection until the instance reads connected.
  2. Review the mapping records (categories, order statuses, payment and shipping methods) so imported data lands on the right Odoo records.
  3. Run a small import first — restrict it by date or by a handful of products — and check the results before letting the scheduled actions take over.
  4. Watch the Logs view during the first full sync. Every sync writes a log line; failures are recorded there rather than raised at the user.

Module-specific notes

  • OpenCart Version (3.x or 4.x) is required and selects the API dialect. OpenCart 4 changed its admin API; picking the wrong one produces authentication errors that look like bad credentials.
  • OpenCart is self-hosted, so the connector reaches your server. The Store URL must be reachable over HTTPS from the Odoo host — a firewall between the two is a common cause of connection failures.
  • This module ships four scheduled actions; there is no inventory-sync job, so stock is handled through the product sync.

What's new since 19.0.2.0.2

2.3.3 (current on Odoo 17, 18 and 19)

  • Odoo 19 builds on the exact 2.3.2 remediation code buyers received: re-imports refresh linked records, unmapped paid order lines are retained, foreign-currency orders book in their own currency, and partial-failure runs report honestly. No behaviour change relative to 2.3.2 — this release aligns the Odoo 19 line and its store listing with that code.
  • The store listing page is regenerated from the current ECOSIRE template.

2.3.2

  • The paid-buyer remediation release is packaged identically for all three supported Odoo majors, with executed fresh installs and 159 tests passing per major.
  • The connector has no dependency on the separate ECOSIRE license client; install the OpenCart module archive directly.

The last few releases focused on correctness (dashboard numbers, manual sync, order-status counting), access control, and accessibility rather than new menus. If you are updating from 2.0.2 or earlier, here is what changed in user-facing terms.

19.0.2.2.5 (prior release)

  • Stores on the clean /api/... URL form no longer re-probe on every sync. The URL form discovered by Test Connection is now carried by the client on Odoo 18 and 17 as well as 19, and is written back by the product, order and customer syncs themselves — not only by the button. A store whose administrator never clicked Test Connection previously paid for a wasted first request against every resource on every unattended run, roughly doubling request volume per cycle.

19.0.2.2.4

  • Every API call went to a URL most OpenCart stores cannot serve. Requests were built as {store_url}/api/<resource> whenever the instance was set to OpenCart 4.x — the default — so any store that does not rewrite clean paths to index.php answered with its own themed 404 page and no sync could ever complete. Requests now use the universal index.php?route=api/<resource> form, with one-time auto-detection of the clean form for stores that do front it. A new API URL Style field pins either form, and URL Style In Use shows which one answered.
  • A rendered HTML page is no longer handed back as data. Anything the store returns as a page — including a 404 served with HTTP 200, as some themes do — was previously decoded to {'_raw': '<html>...'} and treated by the sync layer as a successful empty result. Such responses now raise an error naming the four real causes: wrong URL form, API user not created, Odoo's IP not on the API user's allow-list, or the REST Admin extension not installed.
  • Your API credential no longer leaks into error text. An OpenCart 404 page echoes the request URL in its og:url tag, and that URL carries api_token — so the raw-body dump printed the store's API key back into the error message, the chatter and the logs. Errors are now redacted by parameter name and by value. If you ran an affected build and shared an error screenshot with anyone, regenerate the key in System → Users → API.
  • The connection test probed a route that exists in no OpenCart. GET api/language ships in neither 3.0.3.9, 4.0.2.3 nor 4.1 core, so the test proved nothing and 404'd against real stores.

19.0.2.2.3

  • Queue processing now performs the work it reports. Pending product, order and customer import jobs dispatch to their real import services, move through In Progress to Done, and unsupported jobs become Failed with a reason instead of staying pending forever.
  • Signed webhook events are durably queued. Product/catalog, order/sale and customer events retain their JSON payload on the matching import job; unmapped events are retained as visible failed jobs for inspection. The HTTP response now says queued, matching what has actually been persisted.
  • Each job runs in its own database savepoint, so one failed job cannot abort the rest of the queue-processing run.

19.0.2.2.2

  • Listing truth pass. The App Store page and module description now state only what the shipped code does. The "2026 compliance flows (EU VAT, EU DSA, GDPR)" marketing claim was removed: the three instance toggles behind it were settings that no code ever read, and they have been deleted. The manual tracking fields on orders and partners (VAT OSS country/amount, DSA seller info, GDPR DSR state) remain available for your own processes — they are simply no longer sold as automated compliance flows.
  • The module summary now leads with what this connector is genuinely best at: OpenCart 4.1 authentication (core 4.1 removed api/login — handled), whole-store imports with no 100-record truncation, FX-safe order booking, credential-redacting logs, honest sync outcomes, OCMod tracking, and two-level multi-store.
  • A duplicate support key was removed from the manifest. No functional change.

19.0.2.2.1

  • Reliability hardening (fleet-wide class fix). Every per-record sync/import loop now wraps its body in its own database savepoint with an explicit flush. One bad record rolls back alone: it can no longer poison the batch, abort the database cursor for later records, or make a run's closing write roll back every good record while the logs claim success. A containment regression suite now proves this behaviour on every release.

19.0.2.2.0

  • The Automation Dashboard now follows Odoo's dark mode — switching the web client to dark renders the dashboard in its dark palette instead of leaving light cards with unreadable contrast.
  • A store that has never synchronized no longer shows a fabricated "100% Sync Health" figure — the dashboard reports No syncs yet until a real synchronization has actually run.
  • Starting a sync before the connection has been tested now tells you exactly that ("Test the OpenCart connection before starting synchronization.") instead of a generic "review the logs" message.
  • Test Connection is now restricted to the OpenCart Manager role, matching Synchronization — the button writes the instance status that the scheduled syncs act on.
  • The per-instance OpenCart Version (3.x/4.x), REST Admin bearer token, and rate limit settings now actually take effect on every sync and connection test — previously the API client was built from the store URL and key alone, so a 3.x store could be addressed with 4.x routes and the rate limit always ran at its default. Automatic order-workflow rules now also match per-store correctly on multi-instance installs, instead of always applying whichever rule happened to be first.
  • Full-store sync — product, order, and customer imports no longer stop after the first 100 records. Every import service now pages through the entire store until it is exhausted, so a catalog, order history, or customer base larger than 100 is no longer silently cut off.
  • An OpenCart customer or order with no email address no longer attaches to the wrong Odoo contact — previously it could match the first Odoo contact that also had no email; an empty email is now correctly treated as "no match."
  • Faster, page-batched imports — each page of 100 records now reads its existing mappings, buyer contacts, and product mappings once and creates all of that page's records in a single pass, instead of one database round-trip per record. A single bad record in a page is reported and skipped instead of failing the whole page.
  • Resumable scheduled syncs — a scheduled import or export now saves each completed page as it goes, so a long sync interrupted mid-run (server restart, timeout) keeps the work already done instead of losing it and starting over.
  • Scheduled product exports are now incremental — only products still awaiting export are pushed on each run, rather than re-uploading the whole catalog every time. A new Force Full Export option on the export cron restores the old full-catalog behaviour when you need it; the manual "Export Products" action under Tools → Manual Sync still exports everything on demand. Products exported through the update path are now marked as synced so they are not queued again on the next run.
  • Added database indexes on the OpenCart instance and on the OpenCart product, order, and customer identifiers, keeping mapping lookups fast on large stores.

19.0.2.1.1

  • Fixed a bug that made every manual or dashboard-triggered sync fail before it reached the OpenCart API — the product, order, and customer import services were being registered incorrectly internally, so clicking Sync (or calling /opencart/api/sync) never actually synced anything. All three now dispatch correctly and report success, partial, or failed outcomes as intended.
  • The ECOSIRE App Store listing now links directly to the live demo (opencart.demo.ecosire.com) and to this documentation page from the listing's hero section, a dedicated Resources section, and the footer.
  • Version renumbered to 2.1.1 to supersede a stale 2.1.0 build that had been deployed to the demo server, so upgrades from the demo build land cleanly.

19.0.2.0.9

  • The Automation Dashboard now clearly reports whether a sync completed, partially failed, or failed outright, instead of showing a generic success message for any HTTP 200 response.
  • Dashboard data is scoped to the OpenCart instances visible in your allowed companies, and error cards no longer show raw text returned by the OpenCart server.
  • A custom dashboard date range now includes the end date in full — previously, orders placed later in the day on the end date could be dropped from the totals.
  • The product form gained an OpenCart tab showing that product's connector mapping and catalog settings directly on the product record.
  • Accessibility pass: retry/recovery buttons on failed dashboard panels, accessible labels on the custom date pickers, keyboard-navigable KPI cards, named charts, stronger focus outlines, WCAG AA colour contrast, and dashboard headers that wrap correctly on narrow screens.
  • Editing an existing OpenCart Instance record, and using the optional REST Admin bearer token, now require the OpenCart Manager role.

19.0.2.0.8

  • The webhook endpoint now requires a valid HMAC signature — see Webhooks below. The previous, unsigned webhook route was removed.
  • Tools → Manual Sync for products, orders and customers now runs through the same mapping engine as the scheduled actions. Manual sync could previously fail silently.
  • Automation Dashboard KPIs are now built from your actual product, order, customer and sales records. A connected instance with real data now shows real numbers instead of zeros.
  • An order whose internal workflow step fails is now correctly reported as failed rather than counted as successfully synced.
  • Added Kanban, pivot, graph and chart drill-down views for Orders, alongside the existing list and search views.

19.0.2.0.7

  • Restored full behavioural parity across the Odoo 19, 18 and 17 builds.
  • Stored API credentials (API Key, API Secret, and the optional REST Admin token) are now visible only to Administrators and rendered masked everywhere else.

Webhooks

OpenCart's core has no built-in outbound webhooks — this is a limitation of the platform, not the connector. opencart_store_management still ships a webhook receiver for stores that add their own outbound event source: OpenCart's built-in event/hook system (a small custom extension that POSTs on an event such as catalog/model/checkout/order/addOrder/after), or a third-party webhook extension from the OpenCart marketplace. If your store does not have one of those installed, skip this section — the four scheduled actions already keep Odoo current by polling on a 5–30 minute cycle, and that remains the primary sync path regardless of whether webhooks are configured.

Endpoint

POST https://<your-odoo-host>/opencart/webhook/<instance_id>

<instance_id> is the numeric ID of the OpenCart Instance record you connected in Configuration (visible in the record's browser URL, e.g. .../odoo/opencart-instances/3).

MethodPOST only
AuthPublic — no Odoo user session required
Signature headerX-OpenCart-Hmac-SHA256 — required on every request
BodyAny JSON payload

The request must be signed: compute an HMAC-SHA256 of the raw POST body, keyed with the instance's API Secret (the same secret you entered in Configuration), hex-encode it, and send it as the X-OpenCart-Hmac-SHA256 header. Whatever extension sends the webhook on the OpenCart side needs to be configured with this same URL and secret.

ResponseMeaning
200 {"status": "queued", "event": "<event>"}Signature verified and the event payload stored as a queue job
401 {"error": "Missing signature"}The X-OpenCart-Hmac-SHA256 header was not sent
401 {"error": "Invalid signature"}The header was sent but does not match the computed HMAC
404 {"error": "Instance not found"}<instance_id> does not match an OpenCart Instance record
400 {"error": "Invalid JSON body"}The body could not be parsed as JSON

There is no fixed payload schema to match — the endpoint accepts any JSON body. Its optional event key selects the import queue:

  • names containing product or catalog queue a product import;
  • names containing order or sale queue an order import; and
  • names containing customer queue a customer import.

The exact fields available still depend on the OpenCart-side extension sending the request.

What the webhook does today

A verified webhook is stored immediately as a queue job, with its JSON payload retained for inspection. The five-minute queue processor runs recognised product, order and customer jobs and marks them Done or Failed with the real outcome. An unmapped event is stored as a visible failure rather than acknowledged and discarded. This is a full import of the matching data family, not a single-record delta, and scheduled polling remains the fallback.

The OpenCart → Configuration → Webhooks list (model opencart.webhook) is where you keep a record of which event types you expect (Product/Order/Customer Created, Updated, or Deleted) and note the URL you configured on the OpenCart side. It is for your own documentation and tracking — creating a record here does not register anything with OpenCart itself, and the Test button on a webhook record only confirms the Odoo record exists; it does not perform a real round trip to your store.

Internal API endpoints

These three endpoints back the Automation Dashboard screen itself. They require an authenticated Odoo user session (auth='user') and the roles noted below — they are not meant to be called from outside Odoo, but are documented here for completeness if you script against your own instance.

EndpointRole requiredPurpose
/opencart/api/statusOpenCart UserConnection state and last-sync timestamps for products, orders and customers
/opencart/api/syncOpenCart ManagerTriggers a manual dashboard sync (sync_type: all, products, orders, or customers)
/opencart/dashboard/dataOpenCart UserFull KPI, sales-chart, order-status and recent-activity payload behind the dashboard, for a period or a custom date range

Troubleshooting

Installation

SymptomCause and fix
The requests library is requiredrequests is missing from Odoo's Python environment. Install it into the interpreter that runs Odoo.
The app is not visible in AppsUpdate the Apps List, confirm that the module directory is directly in an addons path, and check that the archive matches your Odoo major version.

Syncing

SymptomCause and fix
Test Connection failsRe-check every required field in the table above. Most failures are a mistyped secret, or credentials created for the sandbox while the connector points at production (or vice-versa).
Test Connection returns your store's 404 page, or an error naming the URL forms it triedThe store answered, but not on a route the connector could use. In order of likelihood: the REST Admin extension is not installed (see above); the API user is missing or disabled; or the Odoo server's IP is not on that API user's allow-list. On builds before 2.2.4 this presented as {'_raw': '<!DOCTYPE html>... — upgrade, because that build also echoed your API key into the error.
Nothing syncs even though the connection is fineThe scheduled actions are disabled at the Odoo level, or Odoo's cron worker is not running. Check Settings → Technical → Scheduled Actions and that --max-cron-threads is greater than zero.
Sync starts then stops part-wayRead the Logs view for that run. Rate limiting and rejected field values are the two common causes; both are logged with the platform's own error text.
Records import but map to the wrong Odoo valuesFix the mapping records under the module's configuration, then re-run the import.
Duplicated products or customersRun the initial import once. If a first attempt half-finished, check the existing records before re-running rather than importing on top.

Version history

Odoo versionVersion you download today
17.017.0.2.3.3
18.018.0.2.3.3
19.019.0.2.3.3

ECOSIRE module versions follow the pattern <odoo major>.<module major>.<minor>.<patch> — for example 19.0.2.3.2 is the Odoo 19 build of module version 2.3.2. Your installed version is shown in Apps.

Support