eBay Store Management
eBay Store Management connects an eBay seller account to Odoo. This page is the installation and configuration guide for the ebay_store_management module as it ships today.
| Technical name | ebay_store_management |
| Odoo versions | 17.0, 18.0, 19.0, 20.0 (Community or Enterprise) |
| Current shipped version | 17.0 → 17.0.2.9.2, 18.0 → 18.0.2.9.2, 19.0 → 19.0.2.9.2, 20.0 → 20.0.2.9.2 (see New in 2.9.2 below) |
| Price | $499 USD — one-time |
| Odoo module licence | OPL-1 |
| Category | Connector |
The module needs no licence key and no activation: there is no ECOSIRE licence client to install.
Requirements
| Requirement | Detail |
|---|---|
| Odoo | 17.0, 18.0, 19.0 or 20.0, Community or Enterprise. Self-hosted or Odoo.sh — Odoo Online (SaaS) cannot install third-party modules |
| Odoo apps | base, sale_management, stock, account, delivery, mail, web, product, contacts — Odoo installs any that are missing |
| Python packages | requests, cryptography |
| Platform account | An eBay seller account and an eBay Developer Program application keyset |
Install the Python packages into the same interpreter that runs Odoo:
sudo -u odoo pip install requests cryptography
Installation
1. Get the module
Download it from the Odoo Apps Store with the account that bought it, or from your ecosire.com account downloads if you bought it on ecosire.com.
2. Extract into your addons path
unzip ebay_store_management*.zip -d /opt/odoo/addons/
ls /opt/odoo/addons/ebay_store_management/__manifest__.py # sanity check
If the ls check fails, the module folder ended up one level too deep — move it up so __manifest__.py sits directly inside ebay_store_management/. On Odoo.sh, commit the folder to your repository instead.
3. Restart Odoo and install
sudo systemctl restart odoo
- Go to Apps and click Update Apps List (developer mode must be on).
- Search for eBay Store Management and click Install.
When the install finishes, an eBay menu appears in the main Odoo app switcher.
Configuration
Connect to eBay
Open eBay → Configuration → Settings and create a record (model ebay.configuration). The connection fields are:
| Label | Technical name | Required | Values |
|---|---|---|---|
| Client ID (App ID) | client_id | Yes | Text |
| Client Secret (Cert ID) | client_secret | Yes | Text |
| Refresh Token | refresh_token | Yes | Text |
| Marketplace | marketplace | Yes | Selection of 25: US, UK, DE, AU, CA, FR, IT, ES, NL, BE, PL, AT, CH, IE, HK, SG, MY, PH, TW, IN, RU, MX, FRBE, FRCA, MOTORS |
Client ID (App ID) and Client Secret (Cert ID) come from your eBay developer application keyset; the Refresh Token is produced by the user-consent OAuth grant for the seller account.
The same record carries behaviour checkboxes — sandbox, sync_products, sync_orders, sync_customers, sync_inventory, auto_sync_products, auto_sync_orders, auto_sync_customers, auto_confirm_orders and auto_delist_relist_by_stock (the Odoo 19 and 20 builds add auto_export_product_changes, labelled Auto Push Product Edits to eBay). They gate what the connector is allowed to do automatically once it is connected. Leave anything you are not ready for switched off, and turn them on one at a time.
On the Odoo 19 and 20 builds the record also carries Sync Frequency (sync_frequency): how often the scheduled Products, Orders and Customers imports run for that account. The choices are Standard (the default: Products hourly, Orders every 30 minutes, Customers every 6 hours), every 15 or 30 minutes, every hour, every 6 or 12 hours, or daily. If you tick an Auto Sync switch while the matching Sync switch under Data Types is off, the form warns you, and the scheduled job writes one Warning Sync Log naming the switch to turn on instead of failing on every run.
Credentials are issued from the eBay Developer Program — see developer.ebay.com/api-docs. The connector talks to api.ebay.com (or api.sandbox.ebay.com when Sandbox Mode is ticked), with OAuth at api.ebay.com/identity.
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 7 scheduled actions (Settings → Technical → Scheduled Actions); the Odoo 19 and 20 builds add an eighth:
| Scheduled action | Runs every (17.0, 18.0) | Runs every (19.0, 20.0) | Enabled on install |
|---|---|---|---|
| ebay: Sync Products | 1 hour | checks every 15 minutes, runs each account at its Sync Frequency | Yes |
| ebay: Sync Orders | 30 minutes | checks every 15 minutes, runs each account at its Sync Frequency | Yes |
| ebay: Sync Customers | 6 hours | checks every 15 minutes, runs each account at its Sync Frequency | Yes |
| ebay: Sync Inventory | 15 minutes | 15 minutes | Yes |
| ebay: Test Connection | 1 day | 1 day | Yes |
| ebay: Auto Delist / Relist by Stock | 15 minutes | 15 minutes | Yes — does nothing until a configuration enables it |
| ebay: Cleanup Old Logs | 1 day | 1 day | Yes — removes sync logs older than 30 days |
| ebay: Export Product Changes | — | 30 minutes | Yes — does nothing until a configuration enables it |
On the Odoo 19 and 20 builds, an account on the default Standard Sync Frequency keeps the 17.0/18.0 timing (Products hourly, Orders every 30 minutes, Customers every 6 hours). 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.
What each sync does
Each button on the configuration form runs the same code as the scheduled action of the same name. The arrows below are the direction the data moves — the sync options read from eBay, and only the two push options write to it.
| Option / button | Direction | What it does | Scheduled action |
|---|---|---|---|
| Sync Products | eBay → Odoo | Imports eBay inventory items. Matches an Odoo product by SKU (eBay SKU or Internal Reference), then by title = product name. On a match it overwrites the Odoo product name and description with eBay's; with no match and an SKU it creates the product. Prices are not touched, because eBay prices live on offers. Sends nothing to eBay. | ebay: Sync Products, hourly (on 19.0/20.0: at the account's Sync Frequency), when Auto Sync Products is on |
| Publish to eBay | Odoo → eBay | Creates or updates the eBay inventory item (title = product name, first 80 characters; description; item specifics; images; quantity — see Stock sent to eBay below) and its offer (price + markup, in the listing currency or the company's currency, category, business policies), then publishes the listing. Fixed price only — auctions are not supported. | None by default: this button is the only trigger. The 30-minute edited-product re-export above repeats it once a configuration enables that job. |
| Push Prices & Stock | Odoo → eBay | Sends the current Odoo price and quantity to eBay for products that are already published, in batches of 25 SKUs. On the Odoo 19 and 20 builds the push names each SKU's eBay offer, and a SKU with no offer yet is skipped (not counted as failed) with a Sync Log line telling you to publish it first with Publish to eBay; on 17.0 and 18.0 such a SKU comes back as a failed record, named with eBay's own error text on the export Sync Log. It never creates a listing. | None — button only. On 19.0/20.0, Export Inventory in the Export wizard runs the same push |
| Sync Orders | eBay → Odoo | New eBay orders become Odoo quotations. The customer is matched by eBay username → e-mail → name; each line by SKU → barcode → eBay product ID → title, and a line that matches nothing is booked on eBay Unmatched Item. Shipping becomes its own order line. An order that is already imported has its eBay status refreshed and is never duplicated. | ebay: Sync Orders, every 30 minutes (on 19.0/20.0: at the account's Sync Frequency, reading every page of new orders), when Auto Sync Orders is on |
| Sync Customers | inside Odoo | Makes no eBay call at all. It reads the buyers of the orders already imported and flags them as eBay customers; the buyer records themselves are created by Sync Orders. | ebay: Sync Customers, every 6 hours (on 19.0/20.0: at the account's Sync Frequency), when Auto Sync Customers is on |
| Sync Inventory | eBay → Odoo | Sets the Odoo on-hand quantity to eBay's, on the configuration company's stock location, without creating a stock move. Leave it off when Odoo is your stock master. | ebay: Sync Inventory, every 15 minutes, whenever the switch is on |
Notes:
- The Data Types switch for a sync (
Sync Products,Sync Orders,Sync Customers,Sync Inventory) must be on, or that option and its scheduled action do nothing.Sync Inventoryis the exception in how it stops: the job skips a configuration that has it off, where the other three raise and log the refusal. - No option detects conflicts. The last run to touch a record wins, so do not leave two directions enabled over the same field at once.
- Import Sync Logs carry counters (processed, created, updated, failed); on the Odoo 19 and 20 builds they also name each failed or skipped SKU, order or contact with the reason. Export Sync Logs carry the SKU and eBay's own error text for each failed record; on the Odoo 19 and 20 builds that is eBay's error number, message and the field eBay names, with the technical detail underneath and the failed products linked on the log.
- If Odoo is the master for products and stock: switch Sync Inventory off, send product edits with Publish to eBay and price and quantity with Push Prices & Stock — and leave Sync Products off as well while Odoo owns the catalogue, because that import overwrites your titles and descriptions from eBay.
Webhook and API endpoints your server exposes
These are the HTTP routes this module adds to your Odoo instance. Only the public ones are reachable without an Odoo login.
| Endpoint | Auth | Purpose |
|---|---|---|
/ebay/webhook | public | Webhook receiver — see the note below, it currently rejects every delivery |
/ebay/account_deletion | public | eBay marketplace account deletion/closure endpoint. GET answers eBay's challenge-code handshake (sha256(challengeCode + verificationToken + endpointURL)); POST records a MARKETPLACE_ACCOUNT_DELETION notice for manual review (no partner is deleted automatically) and acknowledges it. Every build verifies eBay's ECDSA X-EBAY-SIGNATURE over the raw body before recording |
/ebay/api/status | logged-in user | connection and sync status read by the dashboard |
/ebay/api/sync | eBay manager | triggers a sync from the dashboard |
/ebay/dashboard/data | logged-in user | dashboard KPI data |
eBay requires every production application to expose a marketplace account-deletion endpoint. Before you paste the URL into the eBay developer portal, set the verification token in Settings → Technical → System Parameters:
| System parameter | Value |
|---|---|
ebay_store_management.deletion_verification_token | your 32–80 character verification token, the same string you paste into the eBay portal (required — without it the handshake answers HTTP 500) |
ebay_store_management.deletion_endpoint_url | optional override for the endpoint URL eBay hashes; leave empty to use web.base.url + /ebay/account_deletion |
The URL you register is https://<your-odoo-host>/ebay/account_deletion, and it must match the endpoint value byte for byte or eBay's challenge response will not verify.
/ebay/webhook is closed in this build — sync runs on the scheduled actionsThe route exists and is publicly reachable, but it fails closed: ebay.webhook._verify_signature() rejects every delivery and the endpoint answers HTTP 403. eBay pushes events, but no inbound delivery-signature scheme for the general event feed is pinned in our platform contract yet, and we would rather reject a payload than trust an unsigned one. The module will not process an unauthenticated payload, so there is nothing to register in your eBay seller portal today — scheduled polling is the supported path. Leave the scheduled actions above enabled; they are how this build stays current.
Publishing on the Odoo 19 and 20 builds
The Odoo 19 and 20 builds check each product before anything is sent to eBay, and it publishes products with variants as one listing. These behaviours are not part of the 17.0 and 18.0 builds.
-
No stock, no new listing. A new listing with no stock on any of its variants is stopped before it is sent, with what to do: add stock, or check the Stock Field on the eBay account. A multi-variation listing may still carry sold-out sizes.
-
A listed product is protected. A product (or variant) with a live eBay listing cannot be deleted or archived; Odoo names the product, SKU and listing and points to End eBay Listing, which is also on the product form's eBay tab for eBay Managers. Ending a listing clears the whole eBay link on the product; the Odoo product data is kept.
-
Variation listings. A product with variants is published as one multi-variation listing through an eBay Inventory Item Group. When eBay answers that a SKU already belongs to another group, the module adopts the group eBay names and publishes through it. A SKU that already has its own live listing keeps that listing: the module never ends a live listing on its own.
-
Checks before any call. A required item specific with no value eBay accepts stops that product, with the product, the item specific and the value named. So does a SKU eBay cannot address (empty, more than 50 characters, or containing
/ ? # %, a space or a control character), and two variants that would end up with the same size. Every other product in the run carries on. -
Selling limit. A listing refused because the account reached eBay's monthly selling limit is marked eBay Selling Limit Reached and skipped by later runs, instead of failing on every run.
-
Currency. Prices go to eBay in the configuration's Listing Currency, else the company's currency. With neither, the action stops with a message; it never publishes in a guessed USD.
Two behaviours change the data sent to eBay, so they are off until you switch them on in the eBay configuration. A database upgraded from 19.0.2.6.0 sends eBay exactly what it sent before.
| Setting | When it is on | When it is off (default) |
|---|---|---|
| Convert Sizes with the Size Map (Listing / Publish tab, Size Map) | Store sizes (Size, US Shoe Size, Waist Size …) are converted to the sizes eBay lists for the category. Each size-map row applies to clothing, footwear or any product, so a clothing row never re-sizes a shoe. | Sizes are sent as they are in Odoo; a size eBay does not accept is reported on the product, never changed. |
| Report Forecasted Stock (shown when Stock Field is empty) | The quantity sent to eBay, and read by the auto delist/relist job, is the forecasted quantity: across all companies when the global-stock module is installed, otherwise the configuration company's. | The quantity is the on-hand stock of the configuration's company, as in earlier versions. |
Stock sent to eBay
The quantity on a listing comes from the Stock Field when you set one. Otherwise it is the on-hand quantity of the configuration's company, or the forecasted quantity when Report Forecasted Stock is on (Odoo 19 and 20 builds). The Stock Field chosen by an administrator applies for every eBay user who publishes. On 17.0 and 18.0 it is the on-hand quantity of the configuration's company.
Using the module
The eBay menu is laid out as:
- eBay → Dashboard
- eBay → Products
- eBay → Orders
- eBay → Customers
- eBay → Operations — Import Wizard, Export Wizard, Mapping Wizard, Test Connection, Logs, Reports
- eBay → Marketing — Promoted Listings campaigns, Best Offer threads
- eBay → Configuration — Settings, and on the Odoo 19 and 20 builds Mappings (eBay Managers), where the mappings saved from the Mapping Wizard are listed
A normal first run is:
- Test Connection until the instance reads connected.
- Review the mapping records (categories, order statuses, payment and shipping methods) so imported data lands on the right Odoo records. On the Odoo 19 and 20 builds the Mapping Wizard creates every mapping type: Product Categories asks for the eBay Category ID that products of the Odoo category are exported in.
- 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.
- 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
- Sandbox Mode switches the connector to
api.sandbox.ebay.com. Sandbox and production keysets are different — a production key will not authenticate against the sandbox. - Marketplace is required and selects the eBay site (US, UK, DE, AU, CA, and more).
- The Refresh Token is a user token for the seller account, produced by eBay's consent flow; it is not the same thing as the application keyset.
Troubleshooting
Syncing
| Symptom | Cause and fix |
|---|---|
| Test Connection fails | Re-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). |
| Nothing syncs even though the connection is fine | The 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-way | Read 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 values | Fix the mapping records under the module's configuration, then re-run the import. |
| Duplicated products or customers | Run the initial import once. If a first attempt half-finished, check the existing records before re-running rather than importing on top. |
| Push Prices & Stock skips a SKU (19.0, 20.0) | The SKU has no eBay offer yet. Publish it first with Publish to eBay (the button on the eBay account, or Action → Publish to eBay on the product). |
| A product cannot be deleted or archived (19.0, 20.0) | It still has a live eBay listing. Use End eBay Listing on the product form's eBay tab, then delete or archive it. |
| A scheduled import never runs and a Warning Sync Log names a switch (19.0, 20.0) | Auto Sync is on while the matching Sync switch under Data Types is off. Turn the Sync switch on; the job runs at its next check. |
New in 2.9.2
Release 2.9.2 (17.0, 18.0, 19.0 and 20.0) fixes how the dashboard and the eBay lists look and read. Nothing in it changes what is sent to eBay.
On every build:
- The dashboard follows Odoo's dark mode. With Odoo set to dark, the page, the KPI cards and the charts (including their axis and legend text) use dark colours.
- Order Status says when there are no orders in the selected period, instead of showing an empty chart under its legend.
- A long store name stays on one line on a phone. The store chip in the dashboard header shortens with "…"; hover it for the full name.
- With no eBay account connected, the setup message comes first, above the figures, with Create Instance and Setup Guide; the header offers Connect eBay instead of Sync Now.
- Sync Logs opens on every log. It used to open filtered to errors, so a store with only successful runs showed "No sync logs found". The Error filter is one click away; View All on the dashboard opens the same list.
- Recent Activity reads as a sentence, for example "Product import succeeded (12 records)", with a relative time such as "2h ago".
- The Products figure counts products shared across companies (no company set), as the Customers figure already did.
On the 20.0 build:
- The dashboard opens on Odoo 20. It no longer stops with "Oops! Something went wrong" when you open eBay → Dashboard.
- Icons display on Odoo 20. The KPI cards, quick actions, buttons and form section headings show their icons instead of empty coloured squares.
On the 17.0 and 18.0 builds (19.0 and 20.0 already worked this way):
- An imported order keeps the eBay account that imported it. With several eBay accounts, Push Tracking to eBay and Refresh eBay Shipment use that account's credentials, not the first active account's. Orders imported before 2.9.2 use an active account of their own company.
- eBay users without Sales rights can open eBay Orders; the list no longer stops with an Access Error on Sales Order Line.
- Imported Products, eBay Orders and Imported Customers open the eBay lists (eBay ID, SKU, sync status as a coloured badge, last sync) instead of Odoo's general product, order and contact lists.
New in 2.9.1
Release 2.9.1 is a fix release. Nothing in it changes what is sent to eBay for a product that already publishes correctly.
On the Odoo 19 and 20 builds:
- A refused product export says why, in the Sync Log. Each product eBay refuses is listed with its SKU, eBay's error number, eBay's message and the field eBay names, with the technical detail underneath, and the failed products are linked on the log.
- A new listing with nothing in stock is stopped before it reaches eBay, with what to do. A multi-variation listing is stopped only when no variant has stock.
- Push Prices & Stock updates the published offer. The push names each SKU's eBay offer, so eBay accepts the new price and quantity. A SKU with no offer yet is skipped, and the log says to publish it first with Publish to eBay. Export Inventory in the Export wizard runs the same push.
- Sync Frequency sets how often the scheduled imports run. The Products, Orders and Customers jobs check every 15 minutes and run an account once its last sync is older than its Sync Frequency; Standard keeps the earlier timing.
- Auto Sync with its Sync switch off now says so: one Warning Sync Log naming the switch, and a warning on the account form.
- Every order page is imported by Sync Orders, and import Sync Logs name each failed or skipped SKU, order or contact with the reason. Sync Customers no longer writes a placeholder eBay username, and products created by Sync Products track inventory.
- The Mapping Wizard creates every mapping type, and saved mappings are under eBay → Configuration → Mappings.
- A product with a live eBay listing cannot be deleted or archived by accident; End eBay Listing is on the product form's eBay tab.
- The Stock Field applies for every eBay user, so publishing no longer stops with "You are not allowed to access Fields" for an eBay administrator without Settings rights.
- The Import Wizard's limit is called Preview Limit: it limits only the preview; Start Import imports every record, as before.
- A control character in a buyer's country or state no longer stops an order import.
On every build (17.0, 18.0, 19.0 and 20.0):
- Import Campaigns stays within its eBay account. Importing Promoted Listings campaigns for one account no longer moves another account's campaign that has the same eBay campaign id onto it.
The 17.0 and 18.0 builds of 2.9.1 carry only the Import Campaigns fix on top of 2.9.0.
Version history
| Odoo version | Version |
|---|---|
| 17.0 | 17.0.2.9.2 |
| 18.0 | 18.0.2.9.2 |
| 19.0 | 19.0.2.9.2 |
| 20.0 | 20.0.2.9.2 |
ECOSIRE module versions are <odoo major>.<module major>.<minor>.<patch>, so 19.0.2.9.2 is the Odoo 19 build of module version 2.9.2. Your installed version is shown in Apps.