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.orderoutbound sync, and Paybridge payment method - Paybridge (optional): Rust local agent on the POS PC — see Paybridge and
services/paybridge/README.mdin the Linkit repo
Installation
- Extract the ZIP into your Odoo addons path so the folder is
…/addons/odoo-linkit-module/. - Restart Odoo and Update Apps List.
- Search for Linkit Middleware and click Install.
Upgrade from older releases
| Situation | Action |
|---|---|
| Upgrading Linkit Middleware | Apps → 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
Linkit → Connections (recommended)
- Open Linkit → Connections.
- Set Linkit base URL (for example
https://linkit.works) and an API token from the Linkit admin dashboard. - Health check —
GET /api/v1/health(no token). - Verify token —
GET /api/v1/auth/credentialswithAuthorization: Bearer ….
Header buttons also support Pull catalog, Pull offers, Push offers, and the full sync wizard.
See Credential verification for response fields.
Settings → Linkit
| Setting | Purpose |
|---|---|
| ERP inbound plugin key | linkit.erp_plugin_key — /linkit/erp/* and legacy /api/linkit/* aliases |
| POS inbound plugin key | linkit.pos_plugin_key — /linkit/pos/* (Linkit odoo-pos-* apps) |
| API token / base URL | Outbound Odoo → Linkit /api/v1 |
| Default branch IV id | Branch used when pushing SKU stock |
| Outbound sync enabled | Master switch for automatic pushes |
Settings → Linkit → Offers (1.2.0+)
| Setting | Purpose |
|---|---|
| Offer sync enabled | Master toggle for outbound offer API |
| Auto-push on change | Push when coupon.program records change |
| Sync coupon / loyalty / pricelist | Which Odoo promotion sources to include |
| Detected modules | Read-only hint (coupon, loyalty, etc.) |
| Action | Direction |
|---|---|
| Pull offers (Connections) | Linkit → linkit.pulled.offer staging |
| Push offers (Connections) | Odoo coupons / loyalty / pricelist → POST /api/v1/offers or bulk |
| Offer mappings menu | linkit.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:
| Setting | Purpose |
|---|---|
| Enabled | Turn on Paybridge for POS |
| Base URL | Local agent HTTPS URL, e.g. https://127.0.0.1:9443 |
| API key | X-Api-Key for Paybridge |
| Default terminal id | Geidea / Paybridge terminal |
| TLS verify | Verify 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_localProduction (Windows POS PC)
Full step-by-step on the till: services/paybridge/WINDOWS-SETUP.md in the Linkit repo.
- Install Geidea Web ECR (
geidea-ecr-core-web-integration.exe, defaulthttp://localhost:5000). - Build or copy
paybridge_local.exe; runscripts\install-windows-service.batwith the binary path. - 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. - 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)
| Variable | Typical value |
|---|---|
PAYBRIDGE_LOCAL_BIND | 127.0.0.1:9443 |
PAYBRIDGE_TLS_CERT / PAYBRIDGE_TLS_KEY | Paths to PEM (required for HTTPS from browser) |
PAYBRIDGE_LOCAL_API_KEY | Shared secret with Odoo settings |
PAYBRIDGE_MODE | mock (dev) or geidea_web_ecr |
GEIDEA_WEB_ECR_TERMINAL_ID | Terminal id from Geidea |
PAYBRIDGE_CORS_ORIGINS | Odoo origin(s) allowed in browser |
PAYBRIDGE_REQUIRE_ODOO_SESSION | 1 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.orderreachespaid,done, orinvoiced, 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):
| Path | Method | Description |
|---|---|---|
/linkit/erp/health | GET | Health + module version |
/linkit/erp/inventory | POST | Update product.product stock |
/linkit/erp/orders | GET | sale.order feed |
/linkit/erp/products | GET | Product catalog page |
/linkit/erp/offers | POST | Coupon / loyalty programs |
/linkit/erp/customers | POST | res.partner upsert |
/linkit/erp/branches/working-hours | POST | Update warehouse resource.calendar from Linkit hours |
/linkit/erp/branches/working-hours/bulk | POST | Multi-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):
| Path | Method | Description |
|---|---|---|
/linkit/pos/health | GET | POS plugin health |
/linkit/pos/inventory | POST | Stock sync |
/linkit/pos/orders | GET | pos.order feed (optional session_id, state, since) |
/linkit/pos/customers | POST | Customer upsert |
/linkit/pos/branches/working-hours | POST | Same as ERP branch hours (POS plugin key) |
/linkit/pos/branches/working-hours/bulk | POST | Multi-branch hours (POS plugin key) |
Paybridge (Odoo UI / POS session, not Linkit engine):
| Path | Method | Description |
|---|---|---|
/linkit/paybridge/config | POST (JSON) | Paybridge URL, API key, terminal for POS client |
/linkit/paybridge/health | GET | Server-side probe of Paybridge /healthz |
/linkit/paybridge/terminals | GET | Server-side GET /v1/terminals |
Linkit admin apps
Install matching Linkit apps in the tenant dashboard:
| Odoo surface | Example Linkit app slugs |
|---|---|
| ERP | odoo-ecommerce-orders, odoo-ecommerce-inventory, odoo-ecommerce-branches, … |
| POS | odoo-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.
| Direction | Flow |
|---|---|
| Linkit → Odoo | Admin updates branch hours → branch_stagings → install odoo-ecommerce-branches app → POST /linkit/erp/branches/working-hours |
| Odoo → Linkit | Push 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 -vFull ORM tests require an Odoo database:
odoo-bin -d linkit_test -i odoo-linkit-module --test-enable --test-tags linkit --stop-after-init