Linkit
Plugins

Linkit Middleware Plugin (Odoo)

Install and configure the Linkit Middleware Plugin for Odoo 15+ — ERP, Point of Sale, offers sync, and Paybridge (Geidea).

Linkit Middleware Plugin

Native Odoo addon (version 1.2.3) that connects Sales, Inventory, Offers, Customers, Branches (working hours), Point of Sale, and Paybridge (local Geidea terminal) to Linkit middleware.

Download

Download odoo-linkit-module.zip

The ZIP root folder must be named odoo-linkit-module (matches the technical module name).

Requirements

  • Odoo 15.0+ (Community or Enterprise)
  • Python package requests
  • Odoo apps: sale, stock, product, coupon, purchase
  • Point of Sale (point_of_sale) — required for POS routes, pos.order outbound sync, and Paybridge payment method
  • Paybridge (optional): Rust local agent on the POS PC — see Paybridge and services/paybridge/README.md in the Linkit repo

Installation

  1. Extract the ZIP into your Odoo addons path so the folder is …/addons/odoo-linkit-module/.
  2. Restart Odoo and Update Apps List.
  3. Search for Linkit Middleware and click Install.

Upgrade from older releases

SituationAction
Upgrading Linkit MiddlewareApps → Linkit Middleware → Upgrade, or odoo-bin -d YOUR_DB -u odoo-linkit-module --stop-after-init
Had Linkit POS Middleware (odoo-pos-linkit-module)Uninstall the old POS module first, then upgrade Linkit Middleware to 1.2.0+ (POS is merged into this addon)
Local dev (this repo)bash plugins/scripts/sync-odoo-dev.sh then upgrade the module

Configuration

  1. Open Linkit → Connections.
  2. Set Linkit base URL (for example https://linkit.works) and an API token from the Linkit admin dashboard.
  3. Health checkGET /api/v1/health (no token).
  4. Verify tokenGET /api/v1/auth/credentials with Authorization: Bearer ….

Header buttons also support Pull catalog, Pull offers, Push offers, and the full sync wizard.

See Credential verification for response fields.

Settings → Linkit

SettingPurpose
ERP inbound plugin keylinkit.erp_plugin_key/linkit/erp/* and legacy /api/linkit/* aliases
POS inbound plugin keylinkit.pos_plugin_key/linkit/pos/* (Linkit odoo-pos-* apps)
API token / base URLOutbound Odoo → Linkit /api/v1
Default branch IV idBranch used when pushing SKU stock
Outbound sync enabledMaster switch for automatic pushes

Settings → Linkit → Offers (1.2.0+)

SettingPurpose
Offer sync enabledMaster toggle for outbound offer API
Auto-push on changePush when coupon.program records change
Sync coupon / loyalty / pricelistWhich Odoo promotion sources to include
Detected modulesRead-only hint (coupon, loyalty, etc.)
ActionDirection
Pull offers (Connections)Linkit → linkit.pulled.offer staging
Push offers (Connections)Odoo coupons / loyalty / pricelist → POST /api/v1/offers or bulk
Offer mappings menulinkit.offer.map — Linkit offer id per Odoo record

Scheduled job Linkit: Push offers runs every 12 hours when offer sync is enabled.

Offer payloads use offer_type: direct_discount with target_scope: order or product. Idempotency key: remote_offer_id (odoo:<model>:<id>).

Sources (auto-detected):

  • coupon.program (Coupon app — hooks on create/write/unlink)
  • loyalty.program (when Loyalty app is installed)
  • product.pricelist.item (optional, off by default)

Settings → Paybridge (1.1.0+)

Configure under Settings → Paybridge or Linkit → Paybridge:

SettingPurpose
EnabledTurn on Paybridge for POS
Base URLLocal agent HTTPS URL, e.g. https://127.0.0.1:9443
API keyX-Api-Key for Paybridge
Default terminal idGeidea / Paybridge terminal
TLS verifyVerify Paybridge HTTPS cert (use mkcert in dev)

Test health / List terminals probe Paybridge from the Odoo server (optional). The POS browser still calls Paybridge on the POS PC (127.0.0.1) directly.

Add a POS payment method Paybridge (Geidea). Flow: Odoo POS (browser) → Paybridge (HTTPS localhost) → Geidea Web ECR on Windows (http://localhost:5000).

Odoo exposes POST /linkit/paybridge/config (JSON, authenticated session) so the POS client can read URL, API key, and terminal id.

Paybridge (Geidea POS terminal)

Paybridge is a local Rust agent on the cash-register PC, not on the Odoo server.

Quick start (dev)

cd services/paybridge
./scripts/gen-dev-tls.sh
export PAYBRIDGE_TLS_CERT=$PWD/local/dev-certs/paybridge-local.pem
export PAYBRIDGE_TLS_KEY=$PWD/local/dev-certs/paybridge-local-key.pem
export PAYBRIDGE_LOCAL_BIND=127.0.0.1:9443
export PAYBRIDGE_LOCAL_API_KEY=dev
export PAYBRIDGE_MODE=mock
export PAYBRIDGE_CORS_ORIGINS=http://127.0.0.1:8069,http://localhost:8069
cargo run -p paybridge_local

Production (Windows POS PC)

Full step-by-step on the till: services/paybridge/WINDOWS-SETUP.md in the Linkit repo.

  1. Install Geidea Web ECR (geidea-ecr-core-web-integration.exe, default http://localhost:5000).
  2. Build or copy paybridge_local.exe; run scripts\install-windows-service.bat with the binary path.
  3. Set service environment: PAYBRIDGE_MODE=geidea_web_ecr, GEIDEA_WEB_ECR_TERMINAL_ID, TLS cert paths, PAYBRIDGE_LOCAL_API_KEY, PAYBRIDGE_CORS_ORIGINS=https://your-odoo.example.com.
  4. In Odoo: enable Paybridge, set URL https://127.0.0.1:9443, API key, terminal id; enable Paybridge (Geidea) on the POS payment method.

Paybridge environment variables (summary)

VariableTypical value
PAYBRIDGE_LOCAL_BIND127.0.0.1:9443
PAYBRIDGE_TLS_CERT / PAYBRIDGE_TLS_KEYPaths to PEM (required for HTTPS from browser)
PAYBRIDGE_LOCAL_API_KEYShared secret with Odoo settings
PAYBRIDGE_MODEmock (dev) or geidea_web_ecr
GEIDEA_WEB_ECR_TERMINAL_IDTerminal id from Geidea
PAYBRIDGE_CORS_ORIGINSOdoo origin(s) allowed in browser
PAYBRIDGE_REQUIRE_ODOO_SESSION1 to require X-Odoo-Session on payment routes

POS-compatible routes include POST /payment/start, GET /payment/{id}, GET /events (WebSocket). See Paybridge README for MessagePack/gRPC and cloud orchestration.

Features

Outbound (Odoo → Linkit)

  • Catalog, SKU stock, sale orders, customers, offers via /api/v1
  • Hooks on confirmed sale orders, stock moves, purchase flows
  • Offers: auto-push on coupon program changes; cron bulk push
  • POS: when pos.order reaches paid, done, or invoiced, pushes order + related stock (source: odoo-pos)

Inbound pull (Linkit API → Odoo staging)

From Linkit → Connections or the sync wizard:

  • Sample or Full pull for products, SKUs, orders (paginated)
  • Pull offers into Pulled Offers staging
  • Staging menus: Pulled Products, Pulled SKUs, Pulled Orders, Pulled Offers
  • Automatic sync via cron and record hooks (when enabled)

Inbound HTTP (Linkit connectors → Odoo)

Auth: header X-Linkit-Plugin-Key or Authorization: Bearer <key>.

ERP (linkit.erp_plugin_key):

PathMethodDescription
/linkit/erp/healthGETHealth + module version
/linkit/erp/inventoryPOSTUpdate product.product stock
/linkit/erp/ordersGETsale.order feed
/linkit/erp/productsGETProduct catalog page
/linkit/erp/offersPOSTCoupon / loyalty programs
/linkit/erp/customersPOSTres.partner upsert
/linkit/erp/branches/working-hoursPOSTUpdate warehouse resource.calendar from Linkit hours
/linkit/erp/branches/working-hours/bulkPOSTMulti-branch working hours (array of {branch_iv_id, working_hours})

Legacy aliases: /api/linkit/health, /api/linkit/inventory, etc. (same handlers).

POS (linkit.pos_plugin_key, requires Point of Sale):

PathMethodDescription
/linkit/pos/healthGETPOS plugin health
/linkit/pos/inventoryPOSTStock sync
/linkit/pos/ordersGETpos.order feed (optional session_id, state, since)
/linkit/pos/customersPOSTCustomer upsert
/linkit/pos/branches/working-hoursPOSTSame as ERP branch hours (POS plugin key)
/linkit/pos/branches/working-hours/bulkPOSTMulti-branch hours (POS plugin key)

Paybridge (Odoo UI / POS session, not Linkit engine):

PathMethodDescription
/linkit/paybridge/configPOST (JSON)Paybridge URL, API key, terminal for POS client
/linkit/paybridge/healthGETServer-side probe of Paybridge /healthz
/linkit/paybridge/terminalsGETServer-side GET /v1/terminals

Linkit admin apps

Install matching Linkit apps in the tenant dashboard:

Odoo surfaceExample Linkit app slugs
ERPodoo-ecommerce-orders, odoo-ecommerce-inventory, odoo-ecommerce-branches, …
POSodoo-pos-orders, odoo-pos-inventory, odoo-pos-offers

Configure each app with your Odoo base URL and the correct plugin key (ERP vs POS).

Local development (this repository)

# Sync addon → .local/odoo-15-extra-addons/
bash plugins/scripts/sync-odoo-dev.sh

# Start Odoo (PostgreSQL via docker; see .local/odoo.conf)
bash .local/start-odoo.sh

# Upgrade module after code changes
.local/odoo-venv/bin/python .local/odoo-15/odoo-bin \
  -c .local/odoo.conf -u odoo-linkit-module --stop-after-init

# Rebuild docsite download ZIP
bash plugins/scripts/build-all.sh
cp -f plugins/dist/odoo/odoo-linkit-module.zip \
  web/docsite/public/downloads/plugins/odoo/

Working hours (1.2.3+)

Branch schedules sync through Linkit working_hours (weekday object or canonical period array). Each Odoo stock.warehouse maps by branch_iv_id = warehouse code.

DirectionFlow
Linkit → OdooAdmin updates branch hours → branch_stagings → install odoo-ecommerce-branches app → POST /linkit/erp/branches/working-hours
Odoo → LinkitPush branches (warehouses) via Connections / auto-sync → working_hours included in POST /api/v1/branches/bulk

Per-branch payload (single branch):

{
  "branch_iv_id": "WH1",
  "working_hours": [
    {"WeekDay": "Monday", "OpenHour": 9, "OpenMinute": 0, "CloseHour": 18, "CloseMinute": 0}
  ]
}

Multi-branch bulk (POST /linkit/erp/branches/working-hours/bulk):

{
  "branches": [
    {"branch_iv_id": "WH1", "working_hours": [{"WeekDay": "Monday", "OpenHour": 9, "OpenMinute": 0, "CloseHour": 18, "CloseMinute": 0}]},
    {"branch_iv_id": "WH2", "working_hours": {"monday": {"open": "10:00", "close": "22:00"}}}
  ]
}

Odoo stores hours on a dedicated resource.calendar linked from each warehouse (linkit_resource_calendar_id). POS tenants may point the Linkit app at /linkit/pos/branches/working-hours instead (same body, POS plugin key).

Test fixtures: plugins/odoo-linkit-module/tests/fixtures/working_hours_multi_branch.json.

Tests (addon)

cd plugins/odoo-linkit-module
python -m unittest discover -s tests -v

Full ORM tests require an Odoo database:

odoo-bin -d linkit_test -i odoo-linkit-module --test-enable --test-tags linkit --stop-after-init