Skip to content

Products

The Products menu is the catalog's product-management surface — list, search, create, edit, copy, and delete products, plus manage each product's images, per-source inventory, and customer-group prices. It mirrors the admin Catalog → Products screen.

Product types

Every product has a type, fixed at creation. There are seven:

TypeNotes
simpleA standalone product with its own price and stock.
virtualLike simple but non-shippable (no weight/dimensions) — services, memberships.
downloadableSells downloadable links (paid files) and samples (free previews); non-stockable.
groupedA storefront grouping of other simple products (linked products); has no own price.
bundleA configurable kit built from bundle options; its price is calculated from the chosen items.
configurableA parent with variants generated from variant-defining attributes (super_attributes, e.g. colour × size). Each variant is its own SKU with its own price/stock.
bookingA bookable product (default / appointment / event / rental / table sub-types) with time slots; non-stockable.

Composite types own no price or stock of their own. For configurable, bundle, grouped, and booking, the price and inventory live on the children — the variants, bundle items, linked products, or slots. Their top-level price / quantity are derived or empty.

Creating a product is two steps

Creation is deliberately minimal: createAdminCatalogProduct creates the shell from just sku + attributeFamilyId + type (plus superAttributes for configurable). Everything else — name, description, price, images, categories, channels, inventory — is filled in afterwards via updateAdminCatalogProduct. This mirrors the admin's create-then-edit wizard.

status vs visibleIndividually

Two independent flags control storefront presence:

  • status1 enabled / 0 disabled. A disabled product is fully hidden from the storefront.
  • visibleIndividually — whether the product appears in category/search listings. Variant products and grouped-component products are usually set to 0 (reachable only through their parent), while still being status = 1.

Both must effectively be on for a product to be browsable on its own.

Nested data is returned whole

On the single-product query, nested blocks (translations, images, categories, inventories, customerGroupPrices, and the type-specific blocks like variants / bundleOptions / downloadableLinks) are returned as whole JSON — query each as a bare field (translations, not translations { … }); the entire array comes back. They resolve over GraphQL on the detail query.

Per-product sub-resources

The product edit screen's tabs map to their own operations, each scoped to one product:

  • Images — upload (REST only — binary), reorder, and delete a product's images.
  • Inventories — read and bulk-update the per-inventory-source stock quantities.
  • Customer-group prices — tiered prices that apply to specific customer groups.

These are not returned in full on the listing (they're detail-only); the single-product query embeds them inline.

The product listing

adminCatalogProducts is the datagrid query — cursor pagination via first / after. Every scalar field (including the special-price columns) resolves over GraphQL.

Listing arguments (filters are AND-combined)

All filter arguments are combined with AND — every one you add narrows the result set:

ArgTypeDescription
first / aftercursor paginationPage size (default 10, max 50) + cursor from a previous pageInfo.endCursor.
channelStringChannel code used to resolve per-channel values.
nameStringPartial product-name match.
skuStringPartial SKU match.
attribute_familyIntAttribute-family ID.
price_from / price_toFloatPrice band (inclusive).
product_idStringA single ID, or a comma-separated list (e.g. "1,22,2705").
statusInt0 (disabled) or 1 (active).
typeStringOne of the seven product types.
localeStringLocale code used to resolve translated values.
sortStringproduct_id (default), sku, name, type, status, price, quantity, attribute_family, channel.
orderStringasc or desc (default desc).

Listing node fields

Each node carries these scalar columns. Heavy fields are null on the listing (query them on the detail query):

FieldTypeNotes
idIDIRI (/api/admin/catalog/products/{id}).
_idIntNumeric product ID.
skuStringSKU.
nameStringResolved for the active locale/channel. null for draft products.
typeStringProduct type.
statusInt1 active / 0 disabled.
price / formattedPriceStringBase price (composite types carry no own price → null).
specialPrice / formattedSpecialPriceStringDiscounted price, when set.
specialPriceFrom / specialPriceToStringSpecial-price window (null = always on / no end).
quantityIntTotal stock across inventory sources.
baseImageUrlStringMedium-cache base image URL.
imagesCountIntNumber of images.
categoryId / categoryNameInt / StringPrimary category.
channel / localeStringResolved channel / locale.
attributeFamilyId / attributeFamilyNameInt / StringAttribute family.
urlKeyStringStorefront URL slug.
visibleIndividually / featured / newBooleanStorefront flags.
shortDescription / description / metaTitle / metaDescription / metaKeywordsStringResolved content / SEO.
weightFloatProduct weight.
createdAt / updatedAtStringTimestamps.
taxCategoryId / manageStock / inStockDetail-onlynull on the listing.
translations, images, categories, inventories, customerGroupPrices, superAttributes, variants, bundleOptions, linkedProducts, downloadableLinks, downloadableSamplesRelation blocks — all null on the listing; populated only on the detail query.

Actions

ActionWhat it does
CopyDuplicates an existing product into a new draft product (a fresh SKU is generated).
Mass deleteDeletes several products at once — indices: [1, 22]. Missing IDs are skipped.
Mass update statusBulk enable/disable — indices: [1, 22], value: 0 (0 = disable, 1 = active).
Export (CSV)The datagrid "Export" button is REST only (binary file streams aren't expressible over GraphQL) — see Export Products.

Operations in this menu

ActionOperation
List productsadminCatalogProducts query
Product detailadminCatalogProduct(id:) query
Create productcreateAdminCatalogProduct mutation
Update productupdateAdminCatalogProduct mutation
Delete productdeleteAdminCatalogProduct mutation
Copy productcreateAdminCatalogProductCopy mutation
Mass deletecreateAdminCatalogProductMassDelete mutation
Mass update statuscreateAdminCatalogProductMassUpdateStatus mutation
Upload imagesREST only (binary)
Reorder imagesreorderAdminCatalogProductImage mutation
Delete imagedeleteAdminCatalogProductImage mutation
List inventoriesadminCatalogProductInventories query
Update inventoriesupdateAdminCatalogProductInventory mutation
List customer-group pricesadminCatalogProductCustomerGroupPrices query
Add customer-group pricecreateAdminCatalogProductCustomerGroupPrice mutation
Update customer-group priceupdateAdminCatalogProductCustomerGroupPrice mutation
Delete customer-group pricedeleteAdminCatalogProductCustomerGroupPrice mutation

The canonical product listing is List products (adminCatalogProducts query) above. There is also a separate slim Add-Product Search (adminProducts query) used only by the Create-Order "Add Product" modal — not the product listing.

All Products operations require an admin Bearer token — see Authentication. Reads require catalog.products.view; writes require the matching catalog.products.create / .edit / .delete permission.

Released under the MIT License.