# Bagisto Connector

> Two-way Bagisto integration: products, customers, orders, refunds and stock over the Bagisto Admin REST API, with a resilient sync queue.

- **What it is:** Two-way Bagisto integration: products, customers, orders, refunds and stock over the Bagisto Admin REST API, with a resilient sync queue.
- **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:** 199 EUR, one-time, on the Odoo Apps Store
- **Technical name:** bambooforge_bagisto_connector
- **Run for real:** Tested for real against Bagisto 2.0 and the current Bagisto 2 release: products created through the Admin REST API and three orders placed at the storefront checkout came into Odoo with totals identical to the store, 0 sync errors.
- **Not for:** The connector reads products, customers, orders and order slips (refunds) from your store and writes the corresponding Odoo records. It can also export product changes back to Bagisto. Credentials and the webhook secret are stored in admin-only fields.; In scope today: product/customer/order import, product export, order-status mapping, refund 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.
- **Manual:** https://docs.bambooforge.dev/bambooforge_bagisto_connector/
- **Live demo:** https://demo20.bambooforge.dev/odoo/action-bambooforge_bagisto_connector.action_bagisto_control_tower
- **Store page:** https://apps.odoo.com/apps/modules/20.0/bambooforge_bagisto_connector
- **Manual last updated:** 2026-10-15

---
# Bagisto Connector

A two-way bridge between Odoo 20 and your Bagisto store: import products,
customers and orders, push product changes back, and discover 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 Bagisto in sync over the Bagisto Admin REST API
(the `bagisto/rest-api` package). It covers:

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

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

Bagisto returns flat, already-resolved rows and prices in decimal major units,
so no currency conversion is needed. 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 Bagisto 2.0 and the current Bagisto 2 release: products created through the Admin REST API and three orders placed at the storefront checkout came into Odoo with totals identical to the store, 0 sync errors.

### Requirements

- **Odoo**: 20.0, Community or Enterprise.
- **Bagisto**: a Bagisto store with the official `bagisto/rest-api` package
  installed and the Admin REST API enabled. Bagisto must be reachable from the
  Odoo server.
- **Python**: no extra libraries beyond a standard Odoo 20 install.
- **Odoo access**: any internal user can use the connector screens. Bagisto
  credentials are stored in system-only fields, so only the **Settings /
  Administration** user can read or change the admin password or 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_bagisto_connector` into your Odoo addons path.
2. Restart the Odoo service.
3. Open **Apps**, click **Update Apps List**, search for *Bagisto*, and press
   **Activate / Install**. Dependencies (*Sales*, *Contacts*, *Invoicing*,
   *Product*) install automatically.

No Bagisto store is required to evaluate the connector: a mock Bagisto Admin
REST 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. Point an
instance's **Base URL** at `<your-odoo>/bagisto/mock_api` with auth type
*Admin Email + Password* (any email/password) to try it.

### Step 1 — Obtain a Bagisto Admin API token (Sanctum)

The connector talks to the Bagisto Admin REST API, which authenticates with a
Laravel Sanctum bearer token. You have two ways to provide it.

**Option A — let Odoo log in for you (recommended).** Give the connector a
Bagisto admin email and password. On connect it calls
`POST /api/v1/admin/login` with `{email, password, device_name}`; Bagisto
returns a Sanctum token at the top-level `token` key, and the connector sends
it as `Authorization: Bearer <token>` on every request. The token is cached
and automatically refreshed if the store returns 401.

To prepare this in Bagisto:

1. Make sure the `bagisto/rest-api` package is installed and the Admin REST
   API is enabled.
2. Use an existing admin account (or create one under **Settings ▸ Users**)
   that has permission to read products, customers and orders.
3. Note its email and password — you will enter them in Odoo in Step 2.

**Option B — paste a pre-issued token.** If you already have a Sanctum token
(for example one minted by an automation account), you can paste it directly.
To mint one manually, call the login endpoint once, e.g.:

```
curl -X POST https://store.example.com/api/v1/admin/login \
     -H "Accept: application/json" \
     -d "email=admin@example.com" \
     -d "password=YOUR_PASSWORD" \
     -d "device_name=odoo"
```

Copy the `token` value from the JSON response. In Odoo, choose auth type
*Bearer Token* and paste it.

### Step 2 — Create the connection in Odoo

Open **Bagisto Connector ▸ Configuration ▸ Instances** and create a record.

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

Key fields:

| Field | What to enter |
|---|---|
| Name | A label for this store, e.g. *My Live Store*. |
| Base URL | Your store root, e.g. `https://store.example.com` (or `http://localhost:9000` for a self-hosted test store). |
| Authentication | *Admin Email + Password* (Odoo logs in for you — Option A) or *Bearer Token* (you paste a pre-issued Sanctum token — Option B). |
| Admin Email | The Bagisto admin email used by the login flow (Email + Password auth). |
| Admin Password | The Bagisto admin password (login auth). Visible to administrators only. |
| Bearer Token | A pre-issued Sanctum token (Bearer Token auth). Visible to administrators only. |
| Admin path | Leave the default `api/v1/admin` unless your store differs (requires the `bagisto/rest-api` package). |
| 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 store 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. The first successful connection also seeds the default
order-state mapping rows. 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 **Bagisto 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**, **Import Refunds**). This enqueues jobs; it does not block
   the UI.
2. Jobs are processed by the **Bagisto 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 Bagisto reference so
re-imports update the same record instead of duplicating it.

### Order status mapping

Bagisto exposes a string order status on every order (`pending`,
`pending_payment`, `processing`, `completed`, `canceled`, `closed`,
`fraud`, plus any shop-specific custom ones). 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:

![Bagisto order state mapping table](04-order-state-mapping.png)

| Bagisto status | Default Odoo action |
|---|---|
| pending | Keep draft |
| pending_payment | Keep draft |
| processing | Confirm sale order |
| completed | Confirm sale order |
| canceled | Cancel sale order |
| closed | Confirm sale order |
| fraud | Keep draft |

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 your shop introduces (use the exact Bagisto status
string).

### Field mapping & customization

- **Field Mappings** (Configuration) map Bagisto 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 Bagisto fields per resource. Run
  **Schema Introspection** on the instance to refresh it from your live store
  (it falls back to the bundled sample if the store is unreachable).
- **Stock / images / taxes / refunds** 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* — name-based, never
  auto-creates a tax), *Sync refunds* (and *Auto-post refund*). They are off by
  default; turn on only what you need.

### Automation (scheduled actions & webhooks)

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

| Scheduled action | Default | Purpose |
|---|---|---|
| Bagisto Queue Processor | every 1 min | Processes queued import/export/delete jobs. |
| Bagisto Reconciliation | every 15 min | Pulls recent remote changes for enabled models. |
| Bagisto Maintenance | every 1 hr | Recovers stale/locked jobs and trims old jobs and logs. |
| Bagisto Flow Scheduler | every 5 min | Runs scheduled sync flows. |
| Bagisto Flow Metrics | every 1 hr | Aggregates flow-run metrics. |
| Bagisto 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 your Bagisto store's webhook/event
delivery at:

- **Delivery URL**: `https://<your-odoo-domain>/bagisto/webhook`
- **Secret**: the instance **Webhook Secret** (admin-only field on the
  instance).

The webhook is enabled per instance via the **Webhook Enabled** toggle (on by
default). Each delivery must carry an HMAC-SHA256 signature over the raw body in
the `X-Bagisto-Signature` header; Odoo verifies it and rejects anything
without a valid signature. The signed body must include a fresh `emitted_at`
timestamp (within 15 minutes past / 5 minutes future), and each signature is
accepted only once, so captured requests cannot be replayed. Verified
deliveries enqueue a safe import (or a delete, for delete events). Without
webhooks the scheduled reconciliation still keeps data current.

### Safety features

- **Dry-run mode** — simulate writes and review Validation Results before going
  live (`Dry-run` field, ON by default).
- **Business validation profiles** — *Minimal / Standard / Strict* gate risky
  writes (`Business validation profile` field).
- **Safety profiles** — *Conservative / Balanced / Aggressive* apply a coherent
  set of dry-run, delete-strategy and batch-size defaults in one click.
- **Resilient queue** — every remote action is a job with retry and exponential
  back-off, plus a dead-letter state for jobs that exhaust their retries.
- **Circuit breaker** — after repeated failures an instance auto-pauses
  (*Tripped*); the Auto Recover action reopens it once the store responds again
  and no blocking validation issues remain.
- **Rollback snapshots** — when enabled (`Rollback 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.
- **Admin-only credentials** — admin password, bearer token and webhook secret
  live in `base.group_system` fields, hidden from ordinary internal users.

### Where Bagisto shows up in Odoo

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

- **Sales orders** - the *Bagisto* tab, *Queue Bagisto Export* and *Bagisto Binding*
  appear only on orders that came from Bagisto, are bound to Bagisto, or belong
  to a customer bound to Bagisto.
- **Products and contacts** - the *Bagisto* tab appears once an active Bagisto
  connection exists; the *Bagisto 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 "login failed" / 401 | Wrong admin email or password, or the bearer token is invalid/expired. Re-check Step 1. For Bearer Token auth, mint a fresh token; for Email + Password auth, confirm the admin account can sign in to Bagisto. |
| "Admin email and password are required" on Test Connection | Auth type is *Admin Email + Password* but one field is blank. Fill both, or switch to *Bearer Token* and paste a token. |
| "the URL must start with http:// or https://" / "is an internal host" | Base URL points at localhost or a private IP. Enable *Allow internal host* on the instance (test/self-hosted only), or use a public store URL. |
| SSL errors on Test Connection | Self-signed certificate. Use a valid cert, or turn off *Verify SSL* for testing only. |
| "requires the bagisto/rest-api package" / 404 on resources | The Admin REST API is not installed/enabled, or *Admin path* is wrong. Install `bagisto/rest-api` and leave *Admin path* at `api/v1/admin`. |
| Orders import but never confirm | The order's Bagisto status is mapped to *Keep draft* or *Ignore*. Adjust **Order State Mappings**. |
| 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 deliveries rejected (401 / 400 / 409) | 401 = missing or wrong `X-Bagisto-Signature` (check the shared secret); 400 = missing/stale `emitted_at` timestamp; 409 = duplicate (replay) already processed. Confirm both sides share the same secret and their clocks are roughly in sync. |
| Records imported twice | Imports are keyed by the Bagisto 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 targets the Bagisto
Admin REST API (the `bagisto/rest-api` package). Validate your exact build
with the bundled mock first.

**Do I need Bagisto installed to evaluate it?**
No. A mock Bagisto Admin REST 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>/bagisto/mock_api`.

**How does authentication work?**
Bagisto uses a Laravel Sanctum bearer token. Either let the connector log in for
you (it calls `POST /api/v1/admin/login` with your admin email/password and
caches the returned token), or paste a pre-issued token and choose *Bearer
Token* auth. The token is refreshed automatically on 401.

**How does real-time sync work?**
Point your store's webhook delivery at `/bagisto/webhook` with the shared
secret; Odoo verifies the HMAC-SHA256 signature, rejects stale or replayed
deliveries, and enqueues a safe import. Without it, scheduled reconciliation
keeps things in sync.

**Are prices and currency converted?**
No conversion is needed: Bagisto returns prices in decimal major units and the
connector reads them as-is.

**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 (refunds) from
  your store and writes the corresponding Odoo records. It can also export
  product changes back to Bagisto. Credentials and the webhook secret are stored
  in admin-only fields.
- **In scope today**: product/customer/order import, product export, order-status
  mapping, refund 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](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 / Bagisto Admin
  REST API 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_bagisto_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 `bagisto.*`) — 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.2.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.0.0

Current release for Odoo 20.0. This build includes:

- Two-way Odoo 20 <-> Bagisto connector: products, customers, orders and refunds over the Bagisto Admin REST API (Sanctum token).
- 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, **102 automated checks** run against this app on Odoo 16, 17, 18, 19 and 20.
Among them:

- A domain that does not parse is refused.
- Nothing at all is an empty row not a crash.
- A product shows its binding button only once bound.
- A record outside the filter is not queued.
- Import to odoo true but dry run never moves stock.

Tested for real against Bagisto 2.0 and the current Bagisto 2 release: products created through the Admin REST API and three orders placed at the storefront checkout came into Odoo with totals identical to the store, 0 sync errors.

The complete list is in the source you receive.
