BFBambooForge Labs

Saleor Connector

Two-way Saleor integration over the GraphQL API: products, variants, customers, orders and stock, with order totals that match to the cent.

Buy on the Odoo Apps StoreOpen the live demoeCommerce€290Community & Enterprise

Available for Odoo 16.0, Odoo 17.0, Odoo 18.0, Odoo 19.0. Technical name bambooforge_saleor_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.

Saleor Connector

A bridge between Odoo 18 and your Saleor store over the Saleor GraphQL API: import products (with variants and media), customers and orders, 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 aligned with Saleor over Saleor's GraphQL API. Instead of REST endpoints, every read is a typed GraphQL query against a single endpoint (graphql/). It covers:

  • Products — import Saleor products (with variants and media) into Odoo product templates, optionally with stock, images and tax group; export Odoo product changes back to the store. Saleor's Editor.js rich-text descriptions are flattened to plain text on import.

  • Customers — import Saleor customers (and their billing/shipping addresses) into Odoo contacts.

  • Orders — import Saleor orders into Odoo sale orders, mapping each order's Saleor status to a sale-order action (keep draft, confirm, cancel, or ignore).

  • Refunds — optionally discover Saleor order slips (credit notes) attached to an order and create matching draft customer credit notes in Odoo.

Direction of sync: Odoo ↔ Saleor (import is the primary flow; product export and webhook-driven updates are supported).

Prices are read per Saleor channel (a configurable channel slug, default default-channel), so amounts match what that sales channel actually charges.

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.

  • Saleor: any Saleor server exposing the standard GraphQL API at /graphql/. Saleor must be reachable from the Odoo server.

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

  • Odoo access: any internal user can use the connector screens. Saleor credentials are stored in system-only fields, so only the Settings / Administration user can read or change the admin password and the app / bearer token.

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

Installation

  1. Copy bambooforge_saleor_connector into your Odoo addons path.

  2. Restart the Odoo service.

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

No Saleor store is required to evaluate the connector: a mock Saleor GraphQL 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 store. To use it, set the instance Base URL to <your-odoo-url>/saleor/mock_api and leave GraphQL Path at graphql/.

Step 1 — Create a Saleor app token

The connector talks to Saleor's GraphQL API as an authenticated app. The recommended way is a pre-issued app token:

  1. Open the Saleor Dashboard and go to Apps.

  2. Create a local app (or open an existing one).

  3. Grant it the permissions the connector needs: read for products, product variants, customers/users and orders; add manage permissions for those resources only if you intend to export products back to Saleor.

  4. Create / reveal the app's auth token and copy it. This token is used as a Bearer token against the GraphQL endpoint.

Alternatively, the connector can log in with a staff email + password using the Saleor tokenCreate mutation; it then uses (and auto-refreshes) the returned JWT. The app-token approach is preferred for unattended servers because it does not store a password.

Step 2 — Create the connection in Odoo

Open Saleor Connector ▸ Configuration ▸ Instances and create a record.

Saleor instance / connection cockpit

Key fields:

Field

What to enter

Name

A label for this store, e.g. My Live Store.

Base URL

Your Saleor server root, e.g. https://store.example.com. For the bundled mock, use <your-odoo-url>/saleor/mock_api.

Authentication

App / Bearer Token (recommended) or Email + Password (tokenCreate).

Admin Email / Password

Only for the Email + Password auth type: a Saleor staff/admin email and password (password is visible to administrators only).

App / Bearer Token

Only for the App / Bearer Token auth type: the token from Step 1 (visible to administrators only).

GraphQL Path

Leave the default graphql/ unless your server differs.

Default Channel

The Saleor channel slug used for product pricing, default default-channel.

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 a Saleor server on localhost or a private network (lowers the SSRF guard — see Safety features).

Then click Test Connection. A green Connected state means the credentials and URL are correct, and the default order-state mapping is seeded automatically. 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 use case (catalog only, B2C full sync, …), seed default field mappings and order-status rules, and apply a recommended schedule 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 Saleor Connector ▸ 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 Saleor Queue Processor scheduled action (every minute), or immediately if you run it manually 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: Sales ▸ Products, Contacts, and Sales ▸ Orders. Each carries its Saleor reference so re-imports update the same record instead of duplicating it.

Order status mapping

Saleor exposes each order's status as an UPPERCASE enum on the order's status field. Under Configuration ▸ Order State Mappings each instance gets a default table that decides what happens to the Odoo sale order when an order arrives in a given status:

Saleor status

Default Odoo action

DRAFT

Keep draft

UNCONFIRMED

Keep draft

UNFULFILLED

Confirm sale order

PARTIALLY_FULFILLED

Confirm sale order

FULFILLED

Confirm sale order

PARTIALLY_RETURNED

Confirm sale order

RETURNED

Cancel sale order

CANCELED

Cancel sale order

EXPIRED

Cancel sale order

Change any row to Ignore (do nothing), Keep draft, Confirm sale order or Cancel sale order. Unknown/custom statuses default to Ignore, so a status you have not mapped never triggers a destructive transition. Add a row for any custom status using the exact Saleor enum value.

Field mapping & customization

  • Field Mappings (Configuration) map Saleor 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 Saleor fields per resource. Run Schema Introspection on the instance to refresh it from your live store.

  • Stock / images / tax are opt-in toggles on the instance: Sync stock, Sync images (and max images), Upload images on export, Sync taxes (and auto-match taxes on import). They are off by default; turn on only what you need.

  • Refunds: Sync refunds discovers Saleor order slips and creates draft credit notes; Auto-post refund (off by default) posts them automatically.

Automation (scheduled actions & webhooks)

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

Scheduled action

Default

Purpose

Saleor Queue Processor

every 1 min

Processes queued import/export/delete jobs.

Saleor Reconciliation

every 15 min

Pulls recent remote changes for enabled models.

Saleor Maintenance

every 1 hr

Recovers stale/locked jobs and trims old logs.

Saleor Flow Scheduler

every 5 min

Runs scheduled sync flows.

Saleor Flow Metrics

every 1 hr

Aggregates flow-run metrics.

Saleor 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): point a Saleor webhook at:

  • Target URL: https://<your-odoo-domain>/saleor/webhook

  • Secret: the instance Webhook Secret (admin-only field on the instance).

Saleor signs each delivery with an X-Saleor-Signature HMAC-SHA256 header over the raw body; Odoo verifies it (fail-closed: a missing secret or signature is rejected), checks the signed emitted_at timestamp to reject stale/future deliveries, dedupes replays, and enqueues a safe import. Without webhooks the scheduled reconciliation still keeps data current.

Safety features

  • Dry-run mode — simulate writes and review Validation Results before going live.

  • Business validation profilesMinimal / Standard / Strict gate risky writes.

  • Resilient queue — every remote action is a job with retry and exponential back-off.

  • Circuit breaker — after repeated failures an instance auto-pauses (Tripped); the Auto Recover action reopens it once the store responds again.

  • 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 hosts unless Allow internal host is explicitly enabled.

Troubleshooting

Symptom

Cause and fix

Test Connection fails with an auth error

Wrong app token, or the token/app lacks permissions; for Email + Password, wrong credentials. Re-check Step 1 and that the token has product/customer/order read permissions.

"Username and password are required" / "A bearer token is required"

The fields for the chosen Authentication type are empty. Fill the email+password pair, or the app/bearer token, to match the selected auth type.

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

Base URL points at localhost/private IP. Enable Allow internal host on the instance (test/self-hosted only).

SSL errors on Test Connection

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

GraphQL endpoint not found / 404

The GraphQL Path is wrong. Saleor's default is graphql/ under the server root; correct it to match your deployment.

Orders import but never confirm

The order's Saleor status is mapped to Keep draft or Ignore. Adjust Order State Mappings (use the exact UPPERCASE enum).

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. Fix the store/credentials; Auto Recover reopens it, or click Resume.

Webhook returns 401 Invalid signature

The instance Webhook Secret does not match the secret Saleor signs with, or no X-Saleor-Signature header was sent. Set the same secret on both sides.

Webhook returns 400 Stale / future emitted_at

The Saleor and Odoo server clocks differ by more than the freshness window. Sync both clocks (NTP).

Records imported twice

Imports are keyed by the Saleor 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 hash and error with a timestamp.

Frequently asked questions

Which versions are supported? Odoo 18.0 on the Odoo side. On the store side the connector targets Saleor's standard GraphQL API at /graphql/. Validate your exact build with the bundled mock first.

Do I need Saleor installed to evaluate it? No. A mock Saleor GraphQL API ships inside, so you can install, explore and demo the full import flow before connecting a real store — point the Base URL at <your-odoo-url>/saleor/mock_api.

How does authentication work? Two options. Create a Saleor app token in Saleor Dashboard ▸ Apps with the needed read (and optional manage) permissions and use it as a Bearer token — recommended. Or use a staff email + password; the connector runs the tokenCreate mutation and auto-refreshes the returned JWT.

How does real-time sync work? Point a Saleor webhook at /saleor/webhook with the shared secret; Odoo verifies the X-Saleor-Signature HMAC-SHA256 over the raw body, rejects stale/replayed deliveries, and enqueues a safe import. Without it, scheduled reconciliation keeps things in sync.

How are prices read? Per Saleor channel. Set the Default Channel slug (default default-channel) so the connector reads the price that channel charges.

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. Credentials are stored in admin-only fields.

  • In scope today: product/customer/order import, product variants and media, product export, order-status mapping, refund (order-slip) discovery, 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 — 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 / Saleor GraphQL API 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_saleor_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 saleor.*) — 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:

  • Odoo 18 <-> Saleor connector over the Saleor GraphQL API: products, variants, customers, orders.

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

Screens

01 connection cockpit - bambooforge_saleor_connector
01 connection cockpit
Video poster operations - bambooforge_saleor_connector
Video poster operations
Video poster - bambooforge_saleor_connector
Video poster