Skip to main content

Zentail Store Management

Zentail Store Management connects an Odoo database to a Zentail account through Zentail's Open API. Everything on this page describes the zentail_store_management module as it ships today; the behaviour below was read out of the released build.

Zentail is the catalogue master in this relationship. The connector does not try to mirror Zentail's catalogue into Odoo: it exports product data as a report, pushes product data as a CSV you prepare, and reads inventory, listings and orders. That is the surface Zentail's merchant API actually documents, and this module implements exactly that surface — nothing more, and no invented routes.

Technical namezentail_store_management
Odoo versions17.0, 18.0, 19.0 (Community or Enterprise)
Current shipped version17.0 → 17.0.2.0.2, 18.0 → 18.0.2.0.2, 19.0 → 19.0.2.0.2
Price$499 USD — one-time, per Odoo version
Odoo module licenceOPL-1
CategoryConnector

What the module does, and what it does not​

It does:

  • connect to Zentail with the API token from Account Settings → API Access, and verify that token from Odoo with two independent tests;
  • export a product report (POST /v1/report with isExport), wait for it to complete, and keep the generated CSV as an Odoo attachment;
  • push a product CSV you prepare (POST /v1/report), creating new SKUs and optionally clearing blank fields;
  • read inventory per SKU — the all-warehouse total and the per-warehouse breakdown;
  • read listings and orders;
  • receive Zentail webhooks over four signed endpoints and turn them into queue jobs;
  • keep SKU-to-product, warehouse and payment-gateway mappings, with a dashboard over the records it holds.

It deliberately does not:

  • write products, orders, customers, refunds, payouts, shipments, locations or webhooks. Zentail publishes no merchant endpoint for those; the paths a previous build called were invented, and they have been removed rather than left to fail against the real API.
  • import product records into Odoo as products. Product data moves through the report endpoint in both directions; the mapping table links a Zentail SKU to the Odoo product you already created.
  • pull sales orders on a schedule. There is no order-list import. An order payload is available read-only from the Operations Center, and order records can arrive through the webhook intake described below.
  • write stock quantities into Odoo. Zentail documents the inventory paths but not the response schema for them, so the connector records what the API returned on the sync log and leaves your Odoo stock levels alone. A quantity derived from an unpublished shape would be an invented number.

If a capability is not on the first list, the module does not have it.

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, portal, product, contacts, digest — Odoo installs any that are missing
Python packagesrequests
Zentail accountAn account with API access, and a token generated under Account Settings → API Access
NetworkOutbound HTTPS to api.zentail.com (and to the report file host Zentail returns in filePath)
Inbound (webhooks only)Your Odoo instance reachable over HTTPS from Zentail, if you use the webhook intake

Install requests into the same interpreter that runs Odoo:

sudo -u odoo pip install requests

Installation​

  1. In Odoo, open Apps, turn on developer mode, and click Update Apps List.
  2. Search for Zentail Store Management and click Install.
  3. Odoo resolves the apps listed above by itself. There is no second package to fetch and no extra download step — the module is self-contained.

When the install finishes, a Zentail app appears in the main Odoo app switcher.

For a self-hosted server that installs the module from a package, follow the usual Odoo custom-addon procedure: the folder zentail_store_management/ must sit directly inside your addons path with __manifest__.py at its top level, then restart Odoo and update the apps list.

Connect your Zentail account​

1. Create the API token in Zentail​

In Zentail, open Account Settings → API Access and choose GENERATE NEW TOKEN. Copy the value; Zentail shows it once.

2. Create the instance record in Odoo​

Go to Zentail → Configuration → Instances → New.

FieldWhat it isRequired
Instance NameA label for this connection inside OdooYes
Account ReferenceA short label identifying this Zentail account in Odoo (for example mystore). It is not sent in any API requestYes
CompanyThe Odoo company this connection belongs toYes
API Base URLDefaults to https://api.zentail.com. Change it only if Zentail moves the API or you test against a staging hostNo
Auth HeaderWhich HTTP header carries the token — see step 3Yes
Access TokenThe token from step 1. This is what authenticates every requestRecommended
API Key / Client IDOnly for the registered-app OAuth flow: Zentail issues a client ID and secret, the token exchange is completed with Zentail outside Odoo, and the resulting token is pasted into Access TokenNo
Client SecretThe paired secret from the same registered-app flow. Also used as the HMAC key for webhooksOnly for webhooks
API PasswordLegacy field, kept for older databases. Zentail retired private-app passwords in 2022 — use the access tokenNo
NotesFree textNo

The same form carries your operating defaults: default warehouse, discount and shipping products, the three risk thresholds (critical / high / medium), monthly marketing cost and monthly operating expenses, payout journal and currency. They feed the dashboard and the risk scoring; they are not sent to Zentail.

3. Set the auth header​

Zentail does not publish the header name its API expects, so the connector makes it a setting instead of guessing:

SettingSends
X-Auth-Token (default)X-Auth-Token: <token>
Authorization: BearerAuthorization: Bearer <token>

Leave it on the default first. If Test Connection answers Authentication rejected while you are sure the token is correct, switch this setting and test again — that is the only variable between the two attempts.

4. Test the connection​

The instance form has two test buttons, because Zentail's account endpoint is not confirmed for every account:

  • Test Connection calls GET /v1/account and reports the account payload.
  • Test Report Access calls POST /v1/report with an export of a single SKU column. It writes nothing to your Zentail account, and it is the dependable test when the account endpoint is unavailable.

Either test sets the instance Status to Connected on success or Error on failure, and raises the API's own message on failure so you can see the real cause rather than a generic error. A connection record that has never passed a test stays in Draft, and the scheduled actions skip it.

The Operations Center​

Zentail → Operations → Run Operations is where every call the API documents is executed by hand. Choose an instance, choose an operation, fill in its fields and click Run.

OperationCallsFields
Export Product ReportPOST /v1/report with isExport, then poll GET /v1/report/{reportId}, then fetch the fileReport Columns — comma-separated headers, first column must be SKU
Push Product ReportPOST /v1/reportProduct CSV (first header must be SKU), Create New Products, Overwrite With Blank
Read Inventory for a SKUGET /v1/inventory/{sku} and GET /v1/inventory/{sku}/warehousesSKU
Read ListingsGET /v1/listings—
Read OrdersGET /v1/salesOrderOrder Parameters — optional key=value pairs, passed through verbatim

How a product report works​

Zentail's product mechanism is a report, not a REST resource, and the connector follows it exactly:

  1. A report is created with a CSV whose first column header is SKU. That header row is also how you select which columns come back — the available column names are Zentail's own Data Dictionary, and the module does not assume any of them, so you name the ones you want.
  2. The module polls the report every 5 seconds, for up to 5 minutes, until Zentail reports COMPLETED. A report ending FAILED, ERROR or CANCELLED stops with that status; a report that is still running at the timeout stops with the last status it reported.
  3. A completed export carries a filePath. That URL is fetched as it is (it lives on a different host from the API) and the file is stored as an Odoo attachment on the run.

A push is the same endpoint without the export flag: the CSV you paste is Base64-encoded and sent. Create New Products allows Zentail to create SKUs that do not exist yet. Overwrite With Blank clears fields that would otherwise be left untouched when the CSV has them empty.

How the reads behave​

Inventory, listing and order reads record the API's own response on the sync log, together with the API's referenceId when it returns an error, so a support case can quote it. Inventory and listing reads do not change any Odoo record — see What the module does not do above. Order parameters are not published by Zentail either, so anything you type in that field is passed through unchanged rather than filtered against a list this module made up.

Webhooks​

If you want Zentail to push events into Odoo, point it at these URLs on your instance. All four accept POST, require no user session, and are protected by an HMAC signature:

EventURL
Producthttps://<your-odoo>/zentail/webhook/product
Orderhttps://<your-odoo>/zentail/webhook/order
Customerhttps://<your-odoo>/zentail/webhook/customer
Refundhttps://<your-odoo>/zentail/webhook/refund

Each request must carry:

  • X-Zentail-Shop-Domain — used to find the matching instance: the module matches it against the instance's Account Reference.
  • X-Zentail-Hmac-SHA256 — the request body signed with your Client Secret (HMAC-SHA256, Base64-encoded). A request with a missing or mismatched signature is rejected and logged, and the queue job is not created.

A verified request is not processed inline. It becomes a queue job and a log entry, and the Process Queue Jobs scheduled action picks it up. That keeps a slow downstream action from timing out Zentail's request.

There are no separate settings to enable per event: the four routes exist as soon as the module is installed. The Webhooks menu under Configuration holds webhook records for your own reference and testing.

Scheduled actions​

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

Scheduled actionRuns everyOn after install
Zentail: Sync Inventory10 minutesEnabled — reads inventory for mapped SKUs and stamps the mapping
Zentail: Process Queue Jobs5 minutesEnabled — drains the webhook and manual-job queue
Zentail: Process Workflows10 minutesEnabled — runs the workflow rules
Zentail: Auto Risk Detection30 minutesEnabled — scores the risk records
Zentail: Generate Analytics4 hoursEnabled — rebuilds the analytics records
Zentail: Webhook Health Check60 minutesEnabled — flags a webhook that has stopped arriving
Zentail: Cleanup Old Logs24 hoursEnabled — prunes old log rows
Zentail: Daily Summary Report1 dayEnabled — the daily digest
Zentail: Sync Customers (no API endpoint — disabled)60 minutesDisabled — Zentail exposes no customer endpoint; the action is kept so the name resolves, and it says so in the log instead of reporting an empty success

Adjust the intervals to your volume. Zentail sets the API rate limits, not Odoo, and shortening an interval is the usual cause of throttling in the log. Every scheduled action skips cleanly when no instance is in the Connected state, so an unconfigured database does not fill its log with failures.

Zentail is a single app menu with these entries:

  • Dashboard — the KPI view described below.
  • Orders, Refunds, Products, Customers, Payouts — the record views the connector keeps. Orders and customers can be created by the webhook intake; refunds and payouts are local records. The API has no order-list, refund-list or payout-list import, so these views do not fill themselves from Zentail.
  • Analytics — the generated analytics records.
  • Operations — Run Operations, Queue Jobs, Logs.
  • Configuration — Instances, Locations (Zentail warehouse ↔ Odoo warehouse mapping), Payment Gateways, Scheduled Actions, Webhooks.

Dashboard​

The instance form and the dashboard show counts and sums over the records Odoo holds: products, orders, customers, queue jobs, errors, pending orders, return rate, average order value and out-of-stock products, with a period selector (and an explicit date range) plus a sales chart.

Read it as an Odoo-side view, not as a Zentail report. If you have not received orders through webhooks, the order figures are zero — that is the connector being honest about what it has, not a failed sync.

Troubleshooting​

Connection​

SymptomCause and fix
Authentication rejected on Test Connection while the token is rightZentail does not publish the header name. Switch Auth Header to Authorization: Bearer and test again.
Report endpoint failed on Test Report AccessThe token was accepted by neither endpoint. Regenerate the token in Zentail and paste the new value; check for a trailing space.
Connection test raises a network errorThe Odoo server cannot reach api.zentail.com over HTTPS. Check outbound firewall rules and the proxy configuration of the Odoo service.
Status returns to Draft after you saveThe record was never tested successfully. A draft instance is skipped by every scheduled action.
The requests library is requiredrequests is missing from Odoo's Python environment. Install it into the interpreter that runs Odoo.

Reports and reads​

SymptomCause and fix
POST /v1/report did not return a report idThe account rejected the request body. Check that the first column header is SKU and that the CSV is comma-delimited.
Report … was still 'PENDING' after 300sThe report did not finish inside the 5-minute poll window. Export fewer columns or a narrower SKU set and run it again; very large exports should be split.
Report … completed without a filePathZentail returned a completed report with no file. Re-run the export; if it repeats, quote the report id in a support request.
report filePath is not a downloadable URLThe API returned something other than an https URL. Re-run; if it repeats, send us the report id.
HTTP 429 in the logRate limiting. Lengthen the scheduled-action interval, or run fewer manual operations at once; the client retries three times with backoff on 429/5xx before failing.
Inventory reads return data, but Odoo stock is unchangedBy design. Zentail publishes the inventory paths but not the response schema, so the payload is recorded on the log rather than written into stock.

Webhooks​

SymptomCause and fix
Invalid signatureThe Client Secret on the instance does not match the secret Zentail signs with, or a proxy rewrote the body. Check the secret first.
Instance not foundThe X-Zentail-Shop-Domain header does not match any instance's Account Reference.
Webhooks verify but nothing happensThe Process Queue Jobs scheduled action is disabled, or Odoo's cron worker is not running. Check Settings → Technical → Scheduled Actions and that --max-cron-threads is greater than zero.
The Webhook Health Check starts flaggingZentail has stopped delivering. Confirm the instance is reachable from the internet over HTTPS; a webhook to an unreachable host fails on Zentail's side, not here.

Version history​

Odoo versionVersion you install today
17.017.0.2.0.2
18.018.0.2.0.2
19.019.0.2.0.2

ECOSIRE module versions are <odoo major>.<module major>.<minor>.<patch>, so 19.0.2.0.2 is the Odoo 19 build of module version 2.0.2. Your installed version is shown in Apps.

What changed in the 2.0.x line:

  • 2.0.0 — the connector was rebuilt on Zentail's Open API: the report-based product flow, inventory / listing / order reads, the two connection tests and the Operations Center replaced the Shopify-shaped client the module had been cloned from.
  • 2.0.1 / 2.0.2 — build numbering moved above the previously published release, and the configuration screens lost sixteen fields that were rendered but read by no code (order-workflow toggles, API version, pricelist and salesperson defaults, payout auto-reconcile flags, the refund "customer notified" flag, three webhook toggles and two carrier flags). Nothing that worked was removed: order automation stays on the Sale Auto Workflow model, where the flags are read.

Support​