Skip to main content

What it is

Product master data — one row per variant (per size/version, not per model). Combines shop-synced facts (SKU, name, price, stock, active flag) with procurement master data you maintain in the app: supplier assignment, purchase price, MOQ, lead times, safety/target stock days, seasonality profile, and lifecycle status. Variants of the same model are grouped by product_family (source product gid) with a human-readable product_family_label derived from the title. The procurement views — Product Demand, Procurement Queue, Family Trend — are all computed on top of this table.

How it gets data

Ingest-enabled — shop syncs push rows through the Ingest API; the procurement columns are edited in the app (or via MCP data_row_update) and survive re-syncs:
  • One JSON record per request; unknown fields are dropped.
  • Upsert identity is the variant, not the SKU: products upsert on (tenant_id, identity_key) where identity_key = COALESCE(external_id, sku). Send the source variant id as external_id (Shopify ProductVariant gid) — several sizes of one model can share a SKU, and without external_id they would overwrite each other. Integrations that only have a SKU may omit external_id; then the SKU is the identity.
  • tenant_id / workspace_id come from the API key context, never from the body.
  • A ready-made Make.com flow template is downloadable in Settings → Data Sources.
Minimal example payload:

Fields

Identity & shop facts

Procurement master data (maintained in the app)

“ingest” = populated through the ingest endpoint; read-only in the app. ✓ = editable in the app and settable on create; edits survive shop re-syncs. “API only” = real database column not registered as a visible app column. “trigger” = computed by the database on write.
Like every workspace table, products also carry the system columns id, tenant_id, workspace_id, created_at, and updated_at — set automatically, never sent by integrations.

Query it