Skip to main content

Part search, matching and ordering with popular suppliers

Project description

SupplierScout

SupplierScout is an InvenTree plugin that automatically finds, matches, and imports supplier parts for your inventory. Given any purchaseable part in InvenTree, it derives a search query from the part's name, parameters, IPN, MPN, and category, then searches configured supplier APIs, ranks the results, and lets you add or update supplier parts and price breaks with one click.

Features

  • Automatic query derivation — builds a supplier search query from the part's name, Internal Part Number (IPN), Manufacturer Part Number (MPN), parameters, and category hierarchy, with normalisation for passive component values (capacitance, resistance, EIA codes, engineering shorthand).
  • Candidate ranking — scores results using a configurable mix of text-match similarity, stock availability, and unit price; supports balanced, availability-first, and price-first strategies.
  • One-click import — select one or more candidates and add or update supplier parts, manufacturer parts, and price breaks directly from the part detail page.
  • Scheduled resync — periodically refreshes existing supplier-part metadata and price breaks in the background, with per-supplier interval and batch-size controls.
  • Response caching — caches API responses to reduce quota usage and improve responsiveness.
  • API usage tracking — per-supplier request counters and daily-limit enforcement with a dashboard widget showing live metrics.
  • Per-user supplier credentials — users can store their own supplier credentials (API key or OAuth2 client credentials), overriding global settings for their own searches.
  • Token debug endpoint — inspect exactly which tokens were extracted from a part and how the final search query was constructed.

Supported Suppliers

Supplier Search Scheduled Resync Notes
DigiKey Uses DigiKey OAuth2 client credentials (client_id + client_secret) for authenticated API access; response caching
Mouser Electronics Part-number and keyword search; response caching; per-user API keys

Additional suppliers can be added by implementing a BaseSupplierAdapter subclass.

Installation

Via the InvenTree Plugin Manager (recommended)

  1. Open InvenTree → Settings → Plugins.
  2. Click Install Plugin.
  3. Enter the package name: inventree-supplier-scout
  4. Click Install and then Activate.

Via the Command Line

pip install inventree-supplier-scout

After installation, restart InvenTree and activate the plugin in Settings → Plugins.

From Source

git clone https://github.com/getpwnam/inventree-supplier-scout.git
cd inventree-supplier-scout
pip install -e .

Initial Setup

After activating the plugin, you must configure at least one supplier before you can search:

  1. Open Settings → Plugins and click on Supplier Scout → Plugin Settings.
  2. Set either DigiKey Supplier ID (DIGIKEY_PK) or Mouser Supplier ID (MOUSER_PK) to the primary key of your supplier company record in InvenTree.
  3. Set credentials for your chosen supplier:
    • DigiKey: DIGIKEY_CLIENT_ID and DIGIKEY_CLIENT_SECRET
    • Mouser: MOUSER_APIKEY_SEARCH
  4. Save. The Supplier Match action will now appear on every purchaseable part.

Usage

Searching and Matching Parts

  1. Navigate to any purchaseable part in InvenTree.
  2. Click the Supplier Match action button (🔍) that appears in the primary actions bar.
  3. A panel opens showing:
    • The auto-derived search query (editable).
    • A supplier selector.
    • Optional quantity range controls for price selection (Min Qty / Max Qty).
  4. Click Find Matches. SupplierScout queries the supplier API and shows ranked candidates with part number, description, availability, and price.
  5. Select one or more candidates using the checkboxes.
  6. Click Add Selected to create or update supplier parts and import price breaks.

Dashboard Widget

A Supplier Scout Metrics card appears on the InvenTree dashboard (if at least one supplier is registered). It shows, for each configured supplier:

  • Total and successful query counts.
  • API usage (daily calls remaining, reset time).
  • Mouser cache status (enabled, file count, size, TTL).

API Endpoints

The plugin exposes several JSON endpoints under the plugin base URL (/plugin/supplierscout/):

Endpoint Method Permission Description
searchcandidates POST Part write Search one or all configured suppliers for ranked candidate matches
applycandidates POST Part write Create or update supplier parts and refresh part pricing
runresync POST Part write or Admin Run or queue a manual supplier resync
clearcache POST Admin Clear response caches for one supplier or all suppliers
ratelimitstatus GET or POST Part write Return current API usage and daily quota status
dashboardmetrics GET None Return dashboard diagnostics for registered suppliers
tokendebug GET or POST Part write Inspect token extraction and query planning for a part

Notes:

  • Every endpoint also accepts a .json suffix, for example /plugin/supplierscout/runresync.json.
  • Browser requests must still satisfy the normal InvenTree session and CSRF requirements.
  • Part write means the user must have add, change, or delete permission for parts.
  • Admin means InvenTree staff or superuser access.

Endpoint Details

POST /plugin/supplierscout/searchcandidates

Search supplier APIs for a part and return ranked candidates.

Request body:

{
   "pk": 123,
   "supplier": 7,
   "query": "10k 0603 resistor",
   "top_n": 10,
   "min_qty": 1,
   "max_qty": 100
}

Request fields:

  • pk required: InvenTree part primary key.
  • supplier optional: supplier company primary key. Omit it, set it to "", 0, "all", or "*" to search all configured suppliers.
  • query optional: explicit search string. If omitted or empty, Supplier Scout builds a query from part metadata.
  • top_n optional: maximum ranked results returned after scoring. Defaults to the user setting or 10.
  • min_qty optional: lower quantity bound used when selecting price breaks.
  • max_qty optional: preferred upper quantity bound used when selecting price breaks.

Response highlights:

  • message, query, count, and candidates.
  • Each candidate includes supplier metadata, rank score, and whether it already matches an existing supplier part.
  • debug includes token sources, semantic hints, numeric constraints, supplier attempts, and supplier failures.

Example success response:

{
   "message": "OK",
   "query": "10k 0603 resistor",
   "count": 2,
   "candidates": [
      {
         "supplier_part_number": "RC0603FR-0710KL",
         "manufacturer_part_number": "RC0603FR-0710KL",
         "_supplier_pk": 7,
         "_supplier_key": "mouser",
         "_supplier_name": "Mouser",
         "existing_supplier_part": true,
         "existing_supplier_part_pk": 456,
         "action": "update"
      }
   ],
   "debug": {
      "supplier_failures": [],
      "supplier_attempts": []
   }
}

POST /plugin/supplierscout/applycandidates

Create or update supplier parts from candidate payloads returned by searchcandidates.

Request body:

{
   "pk": 123,
   "supplier": 7,
   "candidates": [
      {
         "supplier_part_number": "RC0603FR-0710KL",
         "manufacturer_part_number": "RC0603FR-0710KL",
         "description": "10 kOhm Thick Film Resistor 0603",
         "price_breaks": [
            { "quantity": 1, "price": 0.02 },
            { "quantity": 100, "price": 0.01 }
         ]
      }
   ]
}

Response highlights:

  • created, updated, errors, and per-candidate results.
  • Part pricing is refreshed automatically when any candidate import succeeds.

Example success response:

{
   "message": "OK",
   "created": 0,
   "updated": 1,
   "errors": 0,
   "results": [
      {
         "status": "updated",
         "supplier_part_pk": 456
      }
   ]
}

POST /plugin/supplierscout/runresync

Trigger a manual resync of existing supplier parts.

Request body:

{
   "supplier": 7,
   "part_pk": 123,
   "async": true
}

Request fields:

  • supplier required: supplier company primary key.
  • part_pk optional: when present, resync only supplier parts attached to this InvenTree part.
  • async optional: truthy values 1, true, yes, on, or y queue the work through the InvenTree background task worker.
  • action optional: set to reset_cursor to reset the round-robin cursor for scheduled supplier-wide resync.

Permission rules:

  • Any user with part write permission may resync a single part by passing part_pk.
  • Supplier-wide resync without part_pk requires admin access.
  • action = reset_cursor requires admin access.

Synchronous response example:

{
   "message": "OK",
   "scope": "supplier",
   "action": "resync",
   "supplier_pk": 7,
   "processed": 5,
   "updated": 5,
   "created": 0,
   "failed": 0,
   "skipped": 0,
   "cursor_before": 120,
   "cursor_after": 125
}

Asynchronous response example:

{
   "message": "Queued",
   "queued": true,
   "scope": "supplier",
   "action": "resync",
   "supplier_pk": 7,
   "task_id": "b526758b2baf433eb71ac6994918065f",
   "task_url": "/api/background-task/b526758b2baf433eb71ac6994918065f/"
}

Cursor reset response example:

{
   "message": "OK",
   "scope": "supplier",
   "action": "reset_cursor",
   "supplier_pk": 7,
   "cursor_before": 125,
   "cursor_after": 0
}

Operational note:

  • Async resync requires the InvenTree worker to be running from the main checkout with cd /home/inventree && source dev/venv/bin/activate && invoke worker.

POST /plugin/supplierscout/clearcache

Clear cached supplier API responses.

Request body for one supplier:

{
   "supplier": 7
}

Request body for all suppliers:

{}

Response highlights:

  • Supplier-specific response returns scope = supplier plus a cache object.
  • Global response returns scope = all plus a suppliers list.
  • Cache paths are intentionally sanitized before being returned.

Example supplier response:

{
   "message": "OK",
   "scope": "supplier",
   "supplier_pk": 7,
   "supplier_key": "mouser",
   "cache": {
      "enabled": true,
      "cache_backend": "filesystem",
      "cache_ttl_seconds": 3600,
      "cache_path": "~/.cache/inventree_mouser",
      "cache_file_count": 12,
      "cache_size_bytes": 48219,
      "cleared_file_count": 12,
      "failed_file_count": 0
   }
}

GET|POST /plugin/supplierscout/ratelimitstatus

Return current API usage state for one supplier or all configured suppliers.

Inputs:

  • GET /plugin/supplierscout/ratelimitstatus?supplier=7
  • POST with body { "supplier": 7 }
  • Omit supplier to return all registered suppliers.

Response highlights:

  • updated_ts timestamp.
  • Per-supplier usage with configured, rate_limit_per_second, daily_limit, daily_count, daily_remaining, daily_percent_used, and daily_reset_at.

GET /plugin/supplierscout/dashboardmetrics

Return dashboard diagnostics for every registered supplier.

Response highlights:

  • query_metrics for historical request totals.
  • api_usage for current rate-limit counters.
  • cache_status for dashboard-visible cache diagnostics.

This endpoint is used by the dashboard card and currently does not require part-write permission.

GET|POST /plugin/supplierscout/tokendebug

Inspect how Supplier Scout derived the search query for a part.

Inputs:

  • GET /plugin/supplierscout/tokendebug?pk=123
  • POST with body { "pk": 123 }

Response highlights:

  • Top-level part_pk and query.
  • debug.tokens, debug.token_sources, and debug.token_attribution.
  • debug.semantic_hints for inferred component type and extracted values.
  • debug.query_debug for name_mode, has_structured_tokens, include_name_tokens, source_token_map, and final_query_tokens.

Example response:

{
   "message": "OK",
   "part_pk": 123,
   "query": "capacitor 100nF 0402 16V",
   "debug": {
      "query_debug": {
         "name_mode": "fallback",
         "has_structured_tokens": true,
         "include_name_tokens": false,
         "final_query_tokens": ["capacitor", "100nF", "0402", "16V"]
      }
   }
}

Common Error Responses

Most endpoints return a JSON payload with a message field on validation or permission failures.

Common cases:

  • 400 for invalid supplier or part identifiers.
  • 403 for missing part-write permission or admin-only operations.
  • 404 for unknown suppliers or missing parts.
  • 500 for unexpected internal failures.
  • 503 from runresync when async queue submission fails.

How Search Tokens Are Derived

SupplierScout builds a keyword search query from a part's structured data rather than relying on the part name alone. The goal is to generate a query that a supplier's API will match against real component listings.

Token Sources

Tokens are extracted from the following sources, in priority order:

Source Description
Manufacturer Part Number (MPN) Highest-signal identifier; used first if available
IPN Internal Part Number
SKU Supplier-facing stock-keeping unit
Part parameters Parameter values (e.g., 100nF, 10kΩ, 0402), with unit template attached
Part category names Direct category and every ancestor up the tree (configurable)
Part name / description Fallback when no structured tokens exist (configurable)

Text Tokenisation

Each source value is split on non-alphanumeric boundaries (spaces, dashes, slashes, underscores). Sub-tokens are also extracted from compound tokens. The following normalisation rules are applied to every fragment:

Rule Input example Output tokens
Raw chunk 100nF 100nF
Split sub-token MLCC-0402 MLCC, 0402
Shorthand expansion 4.7n 4.7nf, 4.7nF
Shorthand expansion 10k 10kohm, 10kOhm
Capacitance normalisation 4n7 4.7nF
Resistance normalisation 4R7 4.7ohm
EIA capacitor code 104 100nF
Unitised parameter value=100, unit=nF 100nF, 100 nF

Tokens shorter than two characters are discarded. Duplicate tokens (case-insensitive) are removed.

Semantic Hints and Query Plan

After token extraction, SupplierScout inspects the tokens for semantic clues:

  • Component type — inferred from the part name prefix (C_/C- → capacitor, R_/R- → resistor, L_/L- → inductor) or from parameter names containing capacit, resist, induct.
  • Electrical characteristics — capacitance, resistance, inductance, package, tolerance, voltage, and current values are extracted from parameters and tokens.

The final query is assembled from:

  1. Component type hint (e.g., capacitor)
  2. Electrical characteristic values (e.g., 100nF, 0402, 10%, 25V)
  3. Structured tokens (MPN → IPN → SKU → parameters → category)
  4. Name/description tokens — included always, never, or only as fallback when no structured tokens exist (controlled by TOKEN_NAME_MODE)

The query is capped at ten tokens before being sent to the supplier API.

Numeric Constraints

Voltage and current parameter values are also extracted as hard constraints. Candidates whose spec attributes violate these constraints (e.g., rated voltage below the required minimum) receive a score penalty, so they appear lower in the ranked list.

Inspecting Token Extraction

Use the Token Debug endpoint to see exactly what SupplierScout extracted from a part:

GET /plugin/supplierscout/tokendebug?pk=<part_pk>

The response includes the full token list, per-source breakdown, semantic hints, and the final query token sequence.

Configuration Reference

Settings are managed through the InvenTree plugin settings UI (Settings → Plugins → Supplier Scout). Scope labels below indicate where each setting is stored:

  • Global — applies to all users; set by an administrator in plugin settings.
  • User — per-user override; each user sets their own value in their personal plugin settings. An empty value falls back to the global setting.

DigiKey

Setting key Scope Default Description
DIGIKEY_PK Global Primary key of the DigiKey supplier company record in InvenTree. Must be set before search works.
DIGIKEY_CLIENT_ID Global, User Global: / User: DigiKey OAuth2 client ID. User scope overrides global when set.
DIGIKEY_CLIENT_SECRET Global, User Global: / User: DigiKey OAuth2 client secret (stored encrypted). User scope overrides global when set.
DIGIKEY_MAX_CANDIDATES Global 40 Maximum number of raw DigiKey results fetched before ranking.
DIGIKEY_MIN_PRICE_QUANTITY Global, User Global: 1 / User: Minimum quantity used when selecting the best price break. User scope overrides global when set.
DIGIKEY_MAX_PRICE_QUANTITY Global, User Global: (empty) / User: Upper bound for price-break quantity selection. User scope overrides global when set.
DIGIKEY_CACHE_TTL Global 3600 How long (in seconds) to cache DigiKey API responses on disk. Set to 0 to disable caching. Cache files are stored in ~/.cache/inventree_digikey/.

DigiKey Scheduled Resync

Setting key Scope Default Description
DIGIKEY_RESYNC_ENABLED Global False Enable periodic background refresh of existing DigiKey supplier parts.
DIGIKEY_RESYNC_INTERVAL_MINUTES Global 1440 How often to run a DigiKey resync (in minutes). Default is once per day.
DIGIKEY_RESYNC_BATCH_SIZE Global 100 Maximum number of existing DigiKey supplier parts to refresh per scheduled run. Uses a round-robin cursor to spread work across runs.
DIGIKEY_API_RATE_LIMIT_PER_SECOND Global 1 Maximum DigiKey API requests per second. Set to 0 to disable rate limiting.
DIGIKEY_API_DAILY_LIMIT Global 1000 Maximum DigiKey API requests per day. Requests beyond this limit raise an error until midnight UTC. Set to 0 for no limit.

Mouser Electronics

Setting key Scope Default Description
MOUSER_PK Global Primary key of the Mouser supplier company record in InvenTree. Must be set before search works.
MOUSER_APIKEY_SEARCH Global, User Global: / User: Mouser Part Search API key (stored encrypted). Obtain from the Mouser API Hub. User scope overrides global when set.
MOUSER_MAX_CANDIDATES Global 40 Maximum number of raw Mouser results fetched before ranking. Higher values improve match quality at the cost of more API calls.
MOUSER_MIN_PRICE_QUANTITY Global, User Global: 1 / User: Minimum quantity used when selecting the best price break (e.g., 1 for single-unit prices, 10 for tape-and-reel). User scope overrides global when set.
MOUSER_MAX_PRICE_QUANTITY Global, User Global: (empty) / User: Upper bound for price-break quantity selection. Leave empty to use the smallest available price break above the minimum. User scope overrides global when set.
MOUSER_CACHE_TTL Global 3600 How long (in seconds) to cache Mouser API responses on disk. Set to 0 to disable caching. Cache files are stored in ~/.cache/inventree_mouser/.

Mouser Scheduled Resync

Setting key Scope Default Description
MOUSER_RESYNC_ENABLED Global False Enable periodic background refresh of existing Mouser supplier parts.
MOUSER_RESYNC_INTERVAL_MINUTES Global 1440 How often to run a Mouser resync (in minutes). Default is once per day.
MOUSER_RESYNC_BATCH_SIZE Global 100 Maximum number of existing Mouser supplier parts to refresh per scheduled run. Uses a round-robin cursor to spread work across runs.
MOUSER_API_RATE_LIMIT_PER_SECOND Global 1 Maximum Mouser API requests per second. Set to 0 to disable rate limiting.
MOUSER_API_DAILY_LIMIT Global 1000 Maximum Mouser API requests per day. Requests beyond this limit raise an error until midnight UTC. Set to 0 for no limit.

General Scheduler

Setting key Scope Default Description
RESYNC_SCHEDULER_TICK_MINUTES Global 15 How often the background scheduler checks whether any supplier is due for a resync. The per-supplier interval settings control the actual refresh frequency; this is just the polling granularity.

Candidate Ranking

Setting key Scope Default Description
RANKING_STRATEGY Global, User Global: balanced / User: (empty) Candidate ranking strategy. balanced weights match similarity (45 %), availability (35 %), and price (20 %). availability prioritises stock (50 %). price prioritises cost (50 %). User scope overrides global when set.
TOP_N_CANDIDATES User (empty) Number of ranked candidates displayed in the search panel. Leave empty to use the default of 10.

Token Generation

Setting key Scope Default Description
TOKEN_PARAMETER_NAMES Global (empty) Comma- or newline-separated list of parameter template names to include in token extraction. Leave empty to use all parameters. Example: Capacitance, Voltage Rating, Package.
TOKEN_INCLUDE_CATEGORY_NAMES Global True When enabled, the part's direct category name and every ancestor category name are added as token sources. Disable if category names interfere with search results.
TOKEN_NAME_MODE Global, User Global: fallback / User: (empty) Controls when the part name and description are included as search tokens. fallback — only when no structured tokens (MPN, IPN, parameters, categories) are available. always — always append name tokens. never — never include name tokens. User scope overrides global when set.

Testing and Coverage

See development/TESTING.md for test commands, local CI-equivalent checks, and coverage details.

Development Docs

Developer-focused documentation and helper scripts live under development/:

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

inventree_supplier_scout-0.1.0.tar.gz (65.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

inventree_supplier_scout-0.1.0-py3-none-any.whl (73.7 kB view details)

Uploaded Python 3

File details

Details for the file inventree_supplier_scout-0.1.0.tar.gz.

File metadata

  • Download URL: inventree_supplier_scout-0.1.0.tar.gz
  • Upload date:
  • Size: 65.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for inventree_supplier_scout-0.1.0.tar.gz
Algorithm Hash digest
SHA256 46595ab8e8c5d075df9a8b75d84be414f25f9d9852c37751180c0f355b6fc7a7
MD5 22e28c6f79be6d19b7a0e03c6a03cdf6
BLAKE2b-256 317ad22a3fb2965eb18659e6ec7c4771c31fa806fad4ea96eaedac5b5dcde5eb

See more details on using hashes here.

File details

Details for the file inventree_supplier_scout-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for inventree_supplier_scout-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b26f0a8eb9c1f375739ecd6e0672f82b61cde94180bd90f98c90a6dbddc65c4a
MD5 007eea6346abd90204bf5b5cb9c3cb70
BLAKE2b-256 6f2b58403c3c4389adbff23bca6c5f16471b59d1b2d8505987fcc93598de509e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page