Products & Variants

Manage your full product catalog. A product is the parent container; a variant is the trackable SKU that actually moves through inventory. Each variant carries its own cost, price, barcode, unit of measure, and per-location stock, so the same product can hold many sellable or stockable items. This is the catalog every other inventory feature — purchase orders, transfers, production, COGS — reads from.

Key capabilities

  • Products and variants with create / edit / archive (archiving preserves history)
  • Per-variant SKU, manufacturer SKU, and scannable barcode (UPC/EAN/QR)
  • Unit cost and unit price, plus optional sub-cent precise cost for bulk/commodity inputs
  • Automatic profit margin (price − cost) computed per variant
  • Unit of measure per variant (EA, LB, G, KG, OZ, …) for weight- and count-based stock
  • Default vendor per variant to power reorder suggestions and draft POs
  • Per-location on-hand and available quantities, with optional per-location reorder point and reorder quantity
  • Manual stock adjustments scoped to a location, with a required structured reason code
  • Barcode/SKU lookup endpoint used by receiving, cycle counting, and point-of-sale flows
  • Bulk unit-cost update via CSV export → preview → apply
  • Set opening on-hand quantities per location without generating adjustment journal entries
  • Convert a standalone product into a variant of another product
  • Filter by source (manual vs Shopify), category, or archived status, with search and pagination
  • Optional expiration tracking that switches a product's cost-lot consumption from FIFO to FEFO (earliest expiry first)

How it works

Products group related SKUs; each variant owns its cost, price, and a stock level per location. Adjustments and receipts update the per-location level.

flowchart TD
  product["Product (parent container)"] --> v1["Variant / SKU (cost, price, UoM, barcode)"]
  product --> v2["Variant / SKU"]
  v1 --> level["Inventory level per location (on_hand / available)"]
  level --> reorder{"Below reorder point?"}
  reorder -->|"Yes"| alert["Low-stock alert + reorder suggestion"]
  reorder -->|"No"| ok["Healthy"]
  v1 --> adj["Manual adjustment (reason code)"]
  adj --> level

How to use it

  1. Open Inventory from the sidebar and select the Products tab (/inventory?section=products).
  2. Click New Product, enter a name, and optionally set a category (e.g. Finished Goods, Ingredients, Packaging).
  3. Expand the product row and click Add variant to create a SKU with unit cost, unit price, unit of measure, barcode, and a default vendor.
  4. Read the per-variant stock badges showing on-hand and available quantities across locations.
  5. Click the stock/adjust icon on a variant to open the Adjustment Modal, enter a +/− quantity change, pick a location, and choose a reason code.
  6. Use search and the All / Manual / Shopify / Archived filters to find items quickly in large catalogs.
  7. Click a product row to open Product detail, which surfaces linked POs, per-location stock, and recipes.

Pro tips

  • Think of products as the grouping (T-Shirt) and variants as the real items you stock and sell (Medium / Blue). Stock always lives on the variant, per location.
  • Set a default vendor on each variant — the Overview reorder suggester can only draft a PO for items that have one; unassigned items are flagged separately.
  • Use precise unit cost for commodity or bulk inputs priced in fractions of a cent (e.g. $0.0478/unit); the standard cost field rounds to whole cents.
  • Archiving hides a product or variant from default views but keeps its history and stock ledger intact — prefer it over deletion.
  • For a one-time catalog or count load, use Set opening quantities (or the spreadsheet import) so starting stock doesn't post adjustment entries.
  • Enable expiration tracking on perishables so cost-lot consumption uses FEFO and lots surface on the Overview "Expiring lots" card.

In-depth guide

Stock & quantity tracking

Current stock is tracked per variant per location:

Field Meaning
On hand Total physical units at the location (supports decimals like 803.2 LB)
Available Allocatable units (equals on-hand for inventory management)
Reorder point Triggers a low-stock alert when available falls to or below it
Reorder quantity Suggested quantity to reorder

Notes on how levels behave:

  • Multiple locations — a variant can hold stock at many locations.
  • No location — represents non-tangible/digital goods.
  • No zero floor — levels are not floored at zero; negative on-hand from corrections is allowed and surfaced as an oversell signal rather than blocked.

Adjustments and the delta ledger

Every change (receipt, transfer, sale, manual correction) is recorded and updates the stock level. Manual adjustments require a reason; the structured list buckets reports and the audit trail:

Reason Reason
Shrinkage Count variance
Damage Theft
Expired Transfer
Return Receipt correction
Found Other

How a manual adjustment behaves:

  • Location — targets a specific location (or the default location if none is given).
  • Quantity — accepts a positive or negative non-zero quantity change.
  • Reasons — free-text reasons still save; the preset list just gives a known vocabulary and a stable reporting bucket.

Bulk cost & opening quantities

  • Bulk unit cost: export active variants and current costs as CSV, edit the new_unit_cost column, then preview the diff and apply confirmed changes.
  • Opening quantities: Set opening quantities writes absolute on-hand per location without creating inventory-adjustment journal entries — ideal for an initial load or migration.
  • Convert to variant: move a product's variants under another product and archive the source, useful for merging duplicates created by imports.

Integrations & lookup

How variants connect to external catalogs and scanners:

  • Stripe connected — creating a variant mirrors it to Stripe Catalog (Product + Price).
  • Stripe not connected — variants are created locally and can sync later.
  • Shopify / Square — Shopify and Square IDs link variants to those catalogs for inventory sync.
  • Barcode/SKU lookup — resolves a single non-archived variant (barcode first, then SKU) for scanner-driven receiving, counts, and POS.

Edge cases

  • Archived variants are excluded from barcode/SKU lookup and from default catalog views.
  • Inventory value on the Overview is unit_cost × on_hand; variants with no cost contribute zero.
  • A variant with no location is digital/non-tangible and won't appear in per-location matrices.

Start free and build a catalog that every order, transfer, and cost rolls up from.