# PrestaShop Connector | PrestaShop Odoo Integration

> Two-way PrestaShop 8.0 to 9.0 integration: products, customers, orders, refunds and stock, with signed webhooks and order totals that match.

- **What it is:** Two-way PrestaShop 8.0 to 9.0 integration: products, customers, orders, refunds and stock, with signed webhooks and order totals that match.
- **For:** eCommerce
- **Odoo versions:** 16.0, 17.0, 18.0, 19.0, 20.0 - Community and Enterprise
- **Runs on:** Odoo.sh or Odoo you host yourself - not Odoo Online, which accepts no third-party apps
- **Price:** 249 EUR, one-time, on the Odoo Apps Store
- **Technical name:** bambooforge_prestashop_connector
- **Run for real:** Tested for real against PrestaShop 8 and PrestaShop 9.1.5: on 8, 19 products and 19 real orders came into Odoo in 24 sync jobs with 0 errors, and the two defects only a live store reveals - a missing unit of measure on imported order lines and a 7.00 shipping fee left off the total - were fixed; on a freshly installed 9.1.5 the same connector connected and brought in 19 products, 2 customers and 5 orders in 26 jobs with 0 errors, order totals and SKUs matching the store.
- **Not for:** The connector reads products, customers, orders and order slips from your store and writes the corresponding Odoo records. The API key and webhook secret are stored in admin-only fields.; In scope today: product/customer/order import, product export, numeric order-state mapping, refund (order slip) discovery, multistore/multilang flattening, scheduled sync, signed webhooks.; Out of scope / best-effort: tax auto-matching (off by default, name-based, never auto-creates taxes); multi-warehouse stock routing; subscription/booking order types.
- **Compared with the alternatives:** https://docs.bambooforge.dev/bambooforge_prestashop_connector/compare/
- **Manual:** https://docs.bambooforge.dev/bambooforge_prestashop_connector/
- **Live demo:** https://demo20.bambooforge.dev/odoo/action-bambooforge_prestashop_connector.action_prestashop_control_tower
- **Store page:** https://apps.odoo.com/apps/modules/20.0/bambooforge_prestashop_connector
- **Manual last updated:** 2026-10-15

---
# PrestaShop Connector | PrestaShop Odoo Integration

A two-way bridge between Odoo 20 and your PrestaShop store: import products,
customers and orders, push product changes back, and reconcile refunds — with a
resilient job queue, dry-run safety, validation and rollback so you stay in control.

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

## Matching the storefront total

A storefront charges shipping and grants discounts outside the product lines, so
an order rebuilt from those lines alone is worth less than the order the customer
paid for: the sale looks smaller than it was and never reconciles against the
platform payout.

With **Match Storefront Totals** on the instance (on by default):

- the shipping charge is imported as its own order line, on a clearly named
  service product;
- whatever still separates Odoo from the platform total — platform discounts,
  fees, rounding — is posted as a single adjustment line rather than dropped;
- the platform total and the remaining difference are stored on the order and
  shown on its connector tab;
- an order that still does not match within **Total Tolerance** raises a
  validation warning, so the gap is visible instead of silent.

Imported lines deliberately carry no Odoo tax: the storefront has already
computed tax and it is kept on the order's own tax amount field. Switch the
option off if you would rather Odoo recompute everything from your own price
lists and tax rules.

### Overview

The connector keeps Odoo and PrestaShop in sync over the official PrestaShop
Webservice API. It covers:

- **Products** — import PrestaShop products (with variants and images) into Odoo
  product templates, optionally with stock and tax group, and export Odoo product
  changes back to the store.
- **Customers** — import PrestaShop customers (and their addresses) into Odoo
  contacts.
- **Orders** — import PrestaShop orders into Odoo sale orders, mapping each order's
  PrestaShop state id to a sale-order action (keep draft, confirm, cancel, or ignore).
- **Refunds** — optionally discover PrestaShop order slips (credit notes) attached to
  an order and create matching draft customer credit notes in Odoo.

Direction of sync: **Odoo ↔ PrestaShop** (import is the primary flow; product export
and webhook-driven updates are supported). Multistore and multilanguage shops are
supported via a shop id and a default language id on the instance.

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.

### Tested against the real thing

Automated tests run against a bundled mock store on every release; the line below is the part no mock can give you - the connector pointed at the real platform, with real records and real order totals.

Tested for real against PrestaShop 8 and PrestaShop 9.1.5: on 8, 19 products and 19 real orders came into Odoo in 24 sync jobs with 0 errors, and the two defects only a live store reveals - a missing unit of measure on imported order lines and a 7.00 shipping fee left off the total - were fixed; on a freshly installed 9.1.5 the same connector connected and brought in 19 products, 2 customers and 5 orders in 26 jobs with 0 errors, order totals and SKUs matching the store.

### Requirements

- **Odoo**: 20.0, Community or Enterprise.
- **PrestaShop**: live-tested against PrestaShop 8.0, 8.1, 8.2, 9.0 and 9.1 (9.1.5 on a fresh install). The shop must be
  reachable from the Odoo server and have the **Webservice** feature enabled.
- **Python**: no extra libraries beyond a standard Odoo 20 install.
- **Odoo access**: any internal user can use the connector screens. PrestaShop
  credentials are stored in system-only fields, so only the **Settings / Administration**
  user can read or change the API key and the webhook secret.
- **Network**: outbound HTTPS from Odoo to your shop. By default the connector refuses
  internal/loopback/private hosts as an SSRF safeguard (see *Safety features*).

### Installation

1. Copy `bambooforge_prestashop_connector` into your Odoo addons path.
2. Restart the Odoo service.
3. Open **Apps**, click **Update Apps List**, search for *PrestaShop*, and press
   **Activate / Install**. Dependencies (*Sales*, *Contacts*, *Invoicing*) install
   automatically.

No PrestaShop store is required to evaluate the connector: a mock PrestaShop Webservice
ships inside the module (served under `/prestashop/mock_api/api`), so you can install,
explore and run the full import flow against sample data before pointing it at a real
store.

### Step 1 — Enable the PrestaShop Webservice & create an API key

PrestaShop talks over its built-in **Webservice** (a REST-style API). You enable it and
mint a key in the PrestaShop back office.

1. Log in to the PrestaShop back office as an administrator.
2. Go to **Advanced Parameters ▸ Webservice**.
3. Set **Enable PrestaShop's webservice** to **Yes** and save. (If your store is behind
   a proxy that strips the HTTP Authorization header, also set **Enable HTTP method
   override** to **Yes**.)
4. Click **Add new webservice key**.
5. Leave **Key** to be generated automatically (or click *Generate*), and set a clear
   **Key description**, e.g. `Odoo connector`.
6. Set **Status** to **Enabled**.
7. Under **Permissions**, grant the resources the connector uses. For a full two-way
   sync, give **View (GET)**, **Add (POST)**, **Modify (PUT)** and (optionally)
   **Delete** on at least: *products*, *combinations*, *images*, *stock_availables*,
   *customers*, *addresses*, *orders*, *order_states*, *order_details* and
   *order_slips*. **View (GET)** alone is enough if you only import.
8. **Save**, then copy the generated **Key** — this long alphanumeric string is your API
   key.

The key is used as the HTTP Basic *username* with an empty password — exactly how the
PrestaShop Webservice expects it. The connector handles that for you; you only paste the
key.

Optional, for real-time updates, you will also configure a webhook later (see
*Automation*).

### Step 2 — Create the connection in Odoo

Open **PrestaShop ▸ Configuration ▸ Instances** and create a record.

![PrestaShop instance / connection cockpit](01-connection-cockpit.png)

Key fields:

| Field | What to enter |
|---|---|
| Name | A label for this store, e.g. *My Live Store* (unique per company). |
| Company | The Odoo company that owns this instance. |
| Base URL | Your shop root, e.g. `https://shop.example.com`. Must be a public `http://` or `https://` URL. |
| API Key | The Webservice key from Step 1 (visible to administrators only). |
| Response Format | *JSON* (default) or *XML*. Leave on JSON unless you have a reason to change it. |
| Shop ID | `0` (default) targets all shops. Set a non-zero PrestaShop shop id to scope a single store on a multistore install. |
| Default Language ID | The PrestaShop language id (default `1`) used to flatten multilanguage fields into Odoo's single-language columns. |
| Verify SSL | Keep on for production. Turn off only for self-signed test certificates. |
| Timeout (seconds) | HTTP request timeout (default `30`). |
| Webhook Enabled | On by default; controls whether the public webhook route accepts deliveries for this instance (see *Automation*). |

Then click **Test Connection**. A green *Connected* state means the key and URL are
correct, and the default order-state mapping is seeded automatically on first success.
If it fails, the exact error is shown on the form and recorded in **Logs** (see
*Troubleshooting*).

Tip: use **Quick Setup** (button on the instance) to pick a solution pack (Catalog Only,
B2C Full Sync, B2B Order-First, Retail Starter), seed default field mappings and starter
flows, and apply a recommended safety profile in one step.

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

New instances start with **Dry-run** ON. In dry-run, import and delete jobs *simulate*
writes: instead of changing data they produce **Validation Results** you can review under
**PrestaShop ▸ Operations ▸ Validation Results**. This lets you confirm what *would*
happen before anything is written.

To run a first import:

1. On the instance, click **Import Products** (and/or **Import Customers**,
   **Import Orders**). This enqueues jobs; it does not block the UI.
2. Jobs are processed by the **PrestaShop Queue Processor** scheduled action (every
   minute), or immediately if you open **Operations ▸ Queue Jobs** and run them.
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: **Sales ▸ Products**, **Contacts**, and
**Sales ▸ Orders** (refunds appear as draft credit notes in **Invoicing**). Each carries
its PrestaShop reference so re-imports update the same record instead of duplicating it.

### Order status mapping

PrestaShop returns each order's state as a numeric id (its `current_state`), not a
slug. Under **Configuration ▸ Order State Mappings** each instance gets a default table
(seeded on first successful **Test Connection**) that decides what happens to the Odoo
sale order when an order arrives in a given PrestaShop state:

| State id | PrestaShop state | Default Odoo action |
|---|---|---|
| 1 | Awaiting check payment | Keep draft |
| 2 | Payment accepted | Confirm sale order |
| 3 | Preparation in progress | Confirm sale order |
| 4 | Shipped | Confirm sale order |
| 5 | Delivered | Confirm sale order |
| 6 | Canceled | Cancel sale order |
| 7 | Refunded | Cancel sale order |
| 8 | Payment error | Keep draft |
| 9 | On backorder | Keep draft |
| 10 | Awaiting bank wire payment | Keep draft |
| 11 | Awaiting PayPal payment | Keep draft |
| 12 | Payment remotely accepted | Confirm sale order |

Change any row to **Ignore (do nothing)**, **Keep draft**, **Confirm sale order** or
**Cancel sale order**. Unknown/custom state ids default to *Ignore*, so a state you have
not mapped never triggers a destructive transition. Add a row for any custom state your
shop introduces (use the exact PrestaShop numeric state id).

### Field mapping & customization

- **Field Mappings** (Configuration) map PrestaShop fields to Odoo fields per model.
  Use **Generate suggested mappings** on the instance to seed the business-critical ones,
  then adjust. The mapping board flags fields that need attention.
- **Schema Fields** lists the discovered PrestaShop fields per resource. Run **Schema
  Introspection** on the instance to refresh it from your live store (or from the bundled
  mock when evaluating).
- **Stock / images / tax** are opt-in toggles on the instance, all off by default; turn
  on only what you need:
  
  | Toggle | What it does |
  |---|---|
  | Sync Stock | Reads `stock_available` and writes the PrestaShop quantity on the product template. |
  | Sync Taxes | Resolves the PrestaShop `tax_rules_group` and stores it on the product (best effort). |
  | Auto-match Taxes on Import | With *Sync Taxes*, matches the PrestaShop tax group name to an existing Odoo sales tax in the same company. Never auto-creates taxes. |
  | Sync Images | Downloads the first PrestaShop image as the Odoo product cover image. |
  | Max Images | How many images to download per product (default `1`; only the first becomes the cover, the rest go to product images). |
  | Upload Images on Export | When exporting a product, also uploads its images to PrestaShop. |
  | Sync Refunds | On order import, discovers attached order slips and creates a draft customer credit note. |
  | Auto-post Refund | Auto-validates the refund credit note instead of leaving it draft (off by default so accountants review first). |

### Automation (scheduled actions & webhooks)

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

| Scheduled action | Default | Purpose |
|---|---|---|
| PrestaShop Queue Processor | every 1 min | Processes queued import/export/delete jobs. |
| PrestaShop Reconciliation | every 15 min | Pulls recent remote changes for enabled models. |
| PrestaShop Maintenance | every 1 hr | Recovers stale/locked jobs and trims old logs. |
| PrestaShop Flow Scheduler | every 5 min | Runs scheduled sync flows. |
| PrestaShop Flow Metrics | every 1 hr | Aggregates flow-run metrics. |
| PrestaShop Auto Recover | every 15 min | Reopens a tripped circuit breaker once the store is healthy. |

Turn on **Auto import** / **Auto reconcile** per model on the instance to let the
scheduled actions keep things in sync hands-free.

**Real-time webhooks** (optional): the connector exposes a single public route that
accepts signed deliveries:

- **Delivery URL**: `https://<your-odoo-domain>/prestashop/webhook`
- **Signature header**: `X-Prestashop-Signature` — an HMAC-SHA256 hex digest of the
  raw request body, keyed with the instance **Webhook Secret** (admin-only field on the
  instance).

The shipped PHP companion module posts to this route with the correct signature. Odoo
verifies the signature on every delivery, rejects stale or replayed requests, and
enqueues a safe import. The route accepts `product`, `customer`, `order` and
`order_slip` events, and you can target a specific instance with an `instance_id` (or
`base_url`) query parameter. Without webhooks, the scheduled reconciliation still keeps
data current.

### Safety features

- **Dry-run mode** — simulate writes and review Validation Results before going live
  (field *Dry-run*, ON by default).
- **Business validation profiles** — *Minimal / Standard / Strict* gate risky writes
  (field *Business Validation Profile*).
- **Safety profiles** — *Conservative / Balanced / Aggressive* set sensible defaults for
  dry-run, delete strategy and batch size in one click.
- **Resilient queue** — every remote action is a job with retry and exponential back-off,
  and a dead-letter queue for exhausted jobs.
- **Circuit breaker** — after repeated failures (or an auth/config error) an instance
  auto-pauses (*Tripped*); the Auto Recover action reopens it once the store responds
  again, or click **Resume**.
- **Rollback snapshots** — when 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; Base
  URL must be a public `http(s)` address.
- **Signed webhooks with replay protection** — deliveries must carry a valid HMAC-SHA256
  signature and a fresh `emitted_at`; duplicates are rejected.

### Where PrestaShop shows up in Odoo

The connector stays out of the way on records that have nothing to do
with PrestaShop:

- **Sales orders** - the *PrestaShop* tab, *Queue PrestaShop Export* and *PrestaShop Binding*
  appear only on orders that came from PrestaShop, are bound to PrestaShop, or belong
  to a customer bound to PrestaShop.
- **Products and contacts** - the *PrestaShop* tab appears once an active PrestaShop
  connection exists; the *PrestaShop Binding* button inside it appears once the
  record is bound.
- List views, the sync queue and the control tower are unchanged.

### Troubleshooting

| Symptom | Cause and fix |
|---|---|
| Test Connection fails with 401 | Wrong API key, or the key is disabled. Re-check Step 1: the key must be **Enabled** and have at least **View (GET)** permission on the resources you sync. |
| Test Connection fails with 403 / "webservice disabled" | The PrestaShop Webservice is off. Set **Advanced Parameters ▸ Webservice ▸ Enable PrestaShop's webservice** to *Yes*. |
| 401 even with a correct key (behind a proxy) | Your front proxy strips the HTTP Authorization header. Enable **HTTP method override** in the Webservice settings, or configure the proxy to pass the header. |
| "is not allowed because it resolves to a non-public address" | Base URL points at localhost/a private IP/cloud metadata. Point the connector at a public shop URL; the SSRF guard blocks internal hosts by design. |
| SSL errors on Test Connection | Self-signed or invalid certificate. Use a valid cert, or turn off *Verify SSL* for testing only. |
| Orders import but never confirm | The order's PrestaShop state id is mapped to *Keep draft* or *Ignore*. Adjust **Order State Mappings** (match the exact numeric state id). |
| Jobs stay in *Pending* | The Queue Processor is off or the instance is paused. Check **Scheduled Actions** is active and the instance is not *Paused*. |
| Instance shows *Tripped* | Circuit breaker tripped after repeated failures (or an auth/config error). Fix the store/credentials; Auto Recover reopens it after cooldown, or click **Resume**. |
| Webhook returns 401 "Invalid signature" | The `X-Prestashop-Signature` HMAC does not match. Confirm the companion module's secret equals the instance **Webhook Secret**. |
| Webhook returns 400 "Stale" / "in the future" | The two servers' clocks differ by more than the freshness window. Sync the clocks (NTP) on both the PrestaShop and Odoo hosts. |
| Records imported twice | Imports are keyed by the PrestaShop reference, so this should not happen. If it does, check that two instances do not point at the same store. |
| Nothing happens after Import | You are in **Dry-run**. Review Validation Results, then turn dry-run off and re-run. |

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

### Frequently asked questions

**Which versions are supported?**
Odoo 20.0 on the Odoo side. On the store side the connector was live-tested on PrestaShop
8.0, 8.1, 8.2, 9.0 and 9.1 over the PrestaShop Webservice. Validate your exact build with the
bundled mock first.

**Do I need PrestaShop installed to evaluate it?**
No. A mock PrestaShop Webservice ships inside (served at `/prestashop/mock_api/api`), so
you can install, explore and demo the full import flow before connecting a real store.

**How does authentication work?**
You enable the **Webservice** and create a key under **Advanced Parameters ▸ Webservice**
in the PrestaShop back office. Paste that key into the instance's **API Key** field. The
connector sends it as the HTTP Basic username with an empty password — the standard
PrestaShop scheme.

**How does real-time sync work?**
The shipped PHP companion posts signed events to `/prestashop/webhook` with an
HMAC-SHA256 `X-Prestashop-Signature` over the raw body, keyed with the instance webhook
secret. Odoo verifies the signature, rejects stale/replayed requests, and enqueues a safe
import. Without it, scheduled reconciliation keeps things in sync.

**How are multistore and multiple languages handled?**
Set **Shop ID** to scope requests to one store (`0` = all), and **Default Language ID**
to choose which PrestaShop language is flattened into Odoo's single-language fields.

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

**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 products, customers, orders and order slips from your store and
  writes the corresponding Odoo records. The API key and webhook secret are stored in
  admin-only fields.
- **In scope today**: product/customer/order import, product export, numeric order-state
  mapping, refund (order slip) discovery, multistore/multilang flattening, scheduled
  sync, signed webhooks.
- **Out of scope / best-effort**: tax auto-matching (off by default, name-based, never
  auto-creates taxes); multi-warehouse stock routing; subscription/booking order types.

### Support & updates

- Support: [support@bambooforge.dev](mailto: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 20 / PrestaShop 8.0–9.1 line.

### Upgrading & version compatibility

This build targets **Odoo 20.0**. Each Odoo major series (16.0, 17.0, 18.0, 19.0, 20.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. 20.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_prestashop_connector -d your_db
   ```
4. Odoo applies any schema/data changes automatically. Your existing records and
   configuration are preserved.

## Cross-version migration (moving to a newer Odoo)

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 `prestashop.*`) — 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

## 20.0.1.36.5

- Built for Odoo 20: record rules and access rights rewritten onto Odoo 20's single ir.access model, the screens rebuilt on Owl 3, and every icon moved to the icon set Odoo 20 ships.

## 20.0.1.35.0

Current release for Odoo 20.0. This build includes:

- Two-way Odoo 20 <-> PrestaShop 8.0 / 8.1 / 8.2 / 9.0 connector: products, customers, orders, refunds and stock, signed webhooks.
- Two-way stock sync, live Sync Control Tower, resilient queue and dry-run safety.

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*).

### How we make sure it works

Before every release, **133 automated checks** run against this app on Odoo 16, 17, 18, 19 and 20.
Among them:

- A domain that does not parse is refused.
- Plain user cannot create.
- Plain user cannot unlink.
- Plain user cannot write.
- Nothing at all is an empty row not a crash.

Tested for real against PrestaShop 8 and PrestaShop 9.1.5: on 8, 19 products and 19 real orders came into Odoo in 24 sync jobs with 0 errors, and the two defects only a live store reveals - a missing unit of measure on imported order lines and a 7.00 shipping fee left off the total - were fixed; on a freshly installed 9.1.5 the same connector connected and brought in 19 products, 2 customers and 5 orders in 26 jobs with 0 errors, order totals and SKUs matching the store.

The complete list is in the source you receive.
