14 KiB
Bambuddy InvenTree Sync
Sidecar service for syncing successful Bambuddy print archives into InvenTree stock and tracking filament spools between InvenTree and Bambuddy.
The service runs as a separate Docker container. It does not modify Bambuddy or InvenTree source code. Bambuddy is used as the print-history source, while InvenTree remains the stock-control system of record.
What It Does
For each successful Bambuddy archive, the service:
- finds or creates an InvenTree
Part; - creates one InvenTree
StockItemfor the Bambuddy archive; - writes
WeightandPrintTimepart parameters when those templates exist in InvenTree; - uploads the Bambuddy archive thumbnail to the InvenTree part image;
- writes an InvenTree part URL back into Bambuddy archive
external_url; - stores sync state in SQLite to prevent duplicate stock items.
Failed, stopped, running, or still-printing archives are skipped when SYNC_SUCCESS_ONLY=true.
For filament, the service can:
- use InvenTree
StockItem.batchas the spool identity; - create/update Bambuddy spool records from InvenTree filament stock;
- move InvenTree spool stock between storage and printer locations from Bambuddy assignments;
- subtract Bambuddy filament usage from the matching InvenTree stock item;
- store usage sync state in SQLite to prevent duplicate subtraction.
Data Flow
Bambuddy Archives
|
| webhook or polling
v
bambuddy-inventree-sync
|
| InvenTree API
v
Part + StockItem + Parameters + Image
|
| Bambuddy API
v
Archive external_url -> InvenTree Part page
Filament flow:
InvenTree filament StockItem.batch
|
| creates or updates Bambuddy spool tag_uid
v
Bambuddy spool + printer assignment
|
| stock transfer
v
InvenTree storage location <-> printer location
|
| successful Bambuddy usage history
v
InvenTree stock/remove subtracts filament grams
InvenTree Mapping
| Bambuddy data | InvenTree target |
|---|---|
| archive/model identity | Part |
| successful print archive | StockItem |
| target category | Part.category |
| target storage | StockItem.location |
| archive id | StockItem.batch = bambuddy-<archive_id> |
| filament weight | Part parameter Weight |
| print time | Part parameter PrintTime |
| archive thumbnail | Part.image |
| InvenTree part page | Bambuddy external_url |
Filament Tracking
InvenTree remains the source of truth for spool identity and remaining stock.
The key rule is:
InvenTree StockItem.batch == Bambuddy Spool.tag_uid
Recommended InvenTree structure for the current setup:
| Purpose | InvenTree ID |
|---|---|
| filament part category | 19 |
| filament storage root | 85 |
| loaded-in-printers root | 72 |
| B1 printer stock location | 93 |
| B2 printer stock location | 94 |
| B3 printer stock location | 95 |
| B4 printer stock location | 96 |
The service deliberately starts with FILAMENT_DRY_RUN=true. In dry-run mode it reads both systems and reports what it would create, move, or subtract, but it does not write filament changes. Switch to FILAMENT_DRY_RUN=false only after /filament/status and /sync/filament?dry_run=true show the expected mapping.
Filament sync has three independent parts:
- spool catalog sync: InvenTree stock items create/update Bambuddy spools;
- location sync: Bambuddy assignments move InvenTree stock to printer locations; returning unassigned loaded spools to storage is optional;
- usage sync: Bambuddy usage history subtracts grams from the matching InvenTree stock item.
Duplicate Protection
The service is idempotent:
- each Bambuddy archive ID is stored in
data/sync.sqlite3; - each
StockItemgets batchbambuddy-<archive_id>; - rerunning backfill does not create duplicate stock items;
- repeat prints of the same file/model reuse the same
Partand create newStockItemrows. - each Bambuddy filament usage ID is stored before it can subtract stock twice.
The Part identity key is controlled by:
PART_KEY_FIELDS=content_hash,filename,print_name,name
The generated key becomes an InvenTree IPN:
BMB-<first-12-sha1-chars>
Delete Policy
If an archive is deleted in Bambuddy after it was synced, the corresponding InvenTree data is not deleted.
This is intentional. InvenTree is the inventory record, and deleting print history in Bambuddy should not silently remove stock records. The synced Part, StockItem, parameters, and image remain in InvenTree.
Requirements
- Docker with Linux containers enabled.
- Network access from the sync container to Bambuddy API and InvenTree API.
- Bambuddy API key.
- InvenTree API token.
- Existing InvenTree part category ID.
- Existing InvenTree stock location ID.
- Optional InvenTree filament category and stock location IDs.
- Optional InvenTree parameter templates:
WeightandPrintTime.
On Windows Server 2022, verify Docker with:
docker run --rm hello-world
docker run --rm python:3.12-slim python --version
Docker Deployment
Clone the repository:
git clone https://git.tcom.space/tcom/Lab8DATAPROCESSOR.git
cd Lab8DATAPROCESSOR
Create the runtime config:
Copy-Item .env.example .env
notepad .env
Start the service:
docker compose up -d --build
View logs:
docker compose logs --tail=100
Stop the service:
docker compose down
Update to the latest version:
git pull
docker compose up -d --build
Configuration
Example .env:
BAMBUDDY_BASE_URL=http://192.168.1.5:8000/api/v1
BAMBUDDY_API_KEY=replace-with-bambuddy-api-key
INVENTREE_BASE_URL=http://192.168.0.3:1337
INVENTREE_WEB_URL=
INVENTREE_TOKEN=replace-with-inventree-token
INVENTREE_PART_CATEGORY_ID=26
INVENTREE_STOCK_LOCATION_ID=98
SERVICE_API_TOKEN=change-me
WEBHOOK_SHARED_SECRET=
SYNC_SUCCESS_ONLY=true
SYNC_PART_IMAGES=true
OVERWRITE_PART_IMAGES=false
SYNC_ARCHIVE_EXTERNAL_LINK=true
OVERWRITE_ARCHIVE_EXTERNAL_LINK=false
DEFAULT_STOCK_QUANTITY=1
INVENTREE_STOCK_STATUS=10
PART_IPN_PREFIX=BMB
PART_KEY_FIELDS=content_hash,filename,print_name,name
BACKFILL_PAGE_SIZE=50
POLL_INTERVAL_SECONDS=300
SYNC_ON_STARTUP=false
HTTP_TIMEOUT_SECONDS=30
FILAMENT_TRACKING_ENABLED=false
FILAMENT_DRY_RUN=true
FILAMENT_PART_CATEGORY_ID=19
FILAMENT_STORAGE_LOCATION_ID=85
FILAMENT_LOADED_LOCATION_ID=72
FILAMENT_PRINTER_LOCATION_MAP=B1:93,B2:94,B3:95,B4:96
FILAMENT_BATCH_SOURCE=tag_uid
FILAMENT_SYNC_SPOOLS=true
FILAMENT_SYNC_LOCATIONS=true
FILAMENT_SYNC_USAGE=true
FILAMENT_RETURN_UNASSIGNED_TO_STORAGE=false
FILAMENT_USAGE_LIMIT=200
FILAMENT_USAGE_SUCCESS_STATUSES=success,completed,complete,done
FILAMENT_DEFAULT_MATERIAL=PLA
FILAMENT_DEFAULT_LABEL_WEIGHT=1000
FILAMENT_DEFAULT_CORE_WEIGHT=250
DATA_DIR=/data
Do not commit .env. It contains API tokens and is ignored by git.
Important Settings
BAMBUDDY_BASE_URL- Bambuddy API base URL. Use
/api/v1. INVENTREE_BASE_URL- InvenTree root URL or
/apiURL. The service normalizes it internally. INVENTREE_WEB_URL- Browser-facing InvenTree URL for Bambuddy external links. If empty,
INVENTREE_BASE_URLis used. INVENTREE_PART_CATEGORY_ID- Existing InvenTree category where auto-created printed parts are placed.
INVENTREE_STOCK_LOCATION_ID- Existing InvenTree stock location where printed stock items are placed.
SYNC_SUCCESS_ONLY- When
true, only successful/completed prints are imported. POLL_INTERVAL_SECONDS- Enables automatic periodic backfill.
300means every 5 minutes.0disables polling. SYNC_PART_IMAGES- Downloads Bambuddy thumbnail and uploads it to InvenTree
Part.image. OVERWRITE_PART_IMAGES- When
false, manually set InvenTree part images are preserved. SYNC_ARCHIVE_EXTERNAL_LINK- Writes the InvenTree part page URL into Bambuddy
external_url. OVERWRITE_ARCHIVE_EXTERNAL_LINK- When
false, existing non-InvenTree external links in Bambuddy are preserved. FILAMENT_TRACKING_ENABLED- Enables scheduled and manual filament sync actions.
FILAMENT_DRY_RUN- When
true, filament endpoints report planned writes but do not create spools, move stock, or subtract stock. FILAMENT_PART_CATEGORY_ID- InvenTree category containing filament parts.
FILAMENT_STORAGE_LOCATION_ID- InvenTree root location where spare filament spools are stored.
FILAMENT_LOADED_LOCATION_ID- InvenTree root location for spools loaded in printers.
FILAMENT_PRINTER_LOCATION_MAP- Printer prefix to InvenTree location map. Example
B1:93matches Bambuddy printer names likeB1-X1-CARBON. FILAMENT_BATCH_SOURCE- Bambuddy spool field that contains the InvenTree batch code. Default is
tag_uid. FILAMENT_SYNC_SPOOLS- Creates/updates Bambuddy spool records from InvenTree stock.
FILAMENT_SYNC_LOCATIONS- Moves InvenTree stock items between storage and printer locations from Bambuddy assignments.
FILAMENT_SYNC_USAGE- Subtracts successful Bambuddy usage history from InvenTree stock.
FILAMENT_RETURN_UNASSIGNED_TO_STORAGE- When
true, known Bambuddy spools that are no longer assigned are moved from printer locations back to storage. Keep thisfalseuntil Bambuddy assignments are reliable.
InvenTree IDs
Use numeric IDs for target category and stock location. You can find them from the InvenTree UI URL or API.
Example:
curl.exe -H "Authorization: Token YOUR_TOKEN" http://192.168.0.3:1337/api/part/category/26/
curl.exe -H "Authorization: Token YOUR_TOKEN" http://192.168.0.3:1337/api/stock/location/98/
Current known example:
INVENTREE_PART_CATEGORY_ID=26
INVENTREE_STOCK_LOCATION_ID=98
Validate Connectivity
After the container starts:
curl.exe http://localhost:8088/health
curl.exe -H "X-Service-Token: change-me" http://localhost:8088/validate
curl.exe -H "X-Service-Token: change-me" http://localhost:8088/filament/status
Expected result:
/healthreturnsstatus: ok;/validateconfirms Bambuddy, InvenTree category, and InvenTree location are reachable./filament/statusshows how many InvenTree filament batches match Bambuddy spools.
Initial Backfill
Test one successful archive first:
curl.exe -X POST -H "X-Service-Token: change-me" "http://localhost:8088/sync/backfill?max_archives=1"
Run full backfill:
curl.exe -X POST -H "X-Service-Token: change-me" http://localhost:8088/sync/backfill
Check status:
curl.exe -H "X-Service-Token: change-me" http://localhost:8088/sync/status
When SYNC_SUCCESS_ONLY=true, still-printing or failed archives are skipped and do not consume max_archives.
Automatic Operation
Recommended production mode:
SYNC_SUCCESS_ONLY=true
POLL_INTERVAL_SECONDS=300
SYNC_ON_STARTUP=false
This makes the service check Bambuddy every 5 minutes and import all newly completed prints.
To also run filament tracking automatically:
FILAMENT_TRACKING_ENABLED=true
FILAMENT_DRY_RUN=true
FILAMENT_SYNC_SPOOLS=true
FILAMENT_SYNC_LOCATIONS=true
FILAMENT_SYNC_USAGE=true
FILAMENT_RETURN_UNASSIGNED_TO_STORAGE=false
First run in dry-run:
curl.exe -X POST -H "X-Service-Token: change-me" "http://localhost:8088/sync/filament?dry_run=true"
When the reported actions are correct, change:
FILAMENT_DRY_RUN=false
Then rebuild/restart:
docker compose up -d --build
For near-real-time syncing, also configure a Bambuddy webhook:
http://WINDOWS-SERVER-IP:8088/webhooks/bambuddy
Use the print_complete event. If WEBHOOK_SHARED_SECRET is set, Bambuddy must send:
X-Sync-Secret: your-secret
Running both webhook and polling is recommended. Webhook gives fast sync, polling catches missed events after restarts or temporary failures.
Manual Sync
Sync one archive:
curl.exe -X POST -H "X-Service-Token: change-me" http://localhost:8088/sync/archive/11
Force re-sync one archive:
curl.exe -X POST -H "X-Service-Token: change-me" "http://localhost:8088/sync/archive/11?force=true"
Force sync is useful after changing image, parameter, or external link behavior.
Run all filament sync steps manually:
curl.exe -X POST -H "X-Service-Token: change-me" http://localhost:8088/sync/filament
Run individual filament steps:
curl.exe -X POST -H "X-Service-Token: change-me" http://localhost:8088/sync/filament/spools
curl.exe -X POST -H "X-Service-Token: change-me" http://localhost:8088/sync/filament/locations
curl.exe -X POST -H "X-Service-Token: change-me" http://localhost:8088/sync/filament/usage
API Endpoints
GET /health
GET /validate
GET /sync/status
GET /filament/status
POST /sync/archive/{archive_id}
POST /sync/backfill
POST /sync/filament
POST /sync/filament/spools
POST /sync/filament/locations
POST /sync/filament/usage
POST /webhooks/bambuddy
Manual sync endpoints require X-Service-Token when SERVICE_API_TOKEN is set.
Troubleshooting
View recent logs:
docker compose logs --tail=100
Rebuild after pulling code changes:
git pull
docker compose up -d --build
Common issues:
401from service endpoints: missing or wrongX-Service-Token.401from Bambuddy: wrongBAMBUDDY_API_KEY.401from InvenTree: wrongINVENTREE_TOKEN.- InvenTree
descriptionlength errors: update to the latest service version; descriptions are capped at 250 characters. - No items imported: check if Bambuddy archives are still
printingorfailed. - Duplicate protection prevents repeated imports: use
force=trueonly when you want to refresh parameters/images/links for an existing archive. - Filament sync reports
missing_in_bambuddy: run/sync/filament/spools?dry_run=true, then disable dry-run when the generated spool data is correct. - Filament usage stays
pending: the Bambuddy spool is not linked to an InvenTree batch code intag_uid, or the matching InvenTree stock item is missing. - Location moves do not happen: check
FILAMENT_PRINTER_LOCATION_MAPand Bambuddy spool assignments.
Backups
Persistent sync state is stored in:
./data/sync.sqlite3
Back up the data directory together with .env if you move the service to another server.