Skip to content

Catalog Product — Update ​

Equivalent to PUT /api/admin/catalog/products/{id}.

This is a partial patch — send only the fields you want to change inside input. Omitted fields keep their current value. Pass the product IRI as id (e.g. "/api/admin/catalog/products/42").

Every field the admin Edit Product screen exposes is editable here. Pick a product type in the Examples dropdown (top-right) to see the complete edit-form body for that type.

The examples use illustrative IRIs and ids. Replace them with ids that exist in your store — use the adminCatalogProducts query to find products, and the detail query variants connection to discover a configurable product's variant ids.

Operation ​

OperationType
updateAdminCatalogProductMutation

Input shape — named args vs extras ​

The input has named camelCase args for the common/structural fields, plus an extras object for every other attribute code:

Named argNotes
idThe product IRI. Required.
urlKey, status, visibleIndividually, guestCheckout, new, featuredCommon scalar fields.
price, cost, specialPrice, specialPriceFrom, specialPriceTo, weight, taxCategoryIdPricing & shipping scalars.
categories, channelsint[] — replace the assignment when sent, preserved when omitted.
superAttributesConfigurable super-attribute map (normally set at create).
variantsConfigurable per-variant fields, keyed by variant product id.
bundleOptionsBundle option groups.
linksGrouped associated products.
downloadableLinks, downloadableSamplesDownloadable structure.
bookingBooking structure (type ∈ default / appointment / event / rental / table).
translationsOptional locale-keyed override map.
extrasAny other attribute code — name, color, size, brand, product_number, GST, short_description, description, meta_title, meta_keywords, meta_description, length, width, height, manage_stock, up_sells, cross_sells, related_products, customizable_options — as a JSON object keyed by attribute code.

Anything not in the named-args list goes in extras (it is merged into the payload as a top-level attribute by code). Structure args replace that structure when sent — send the full set.

Field applicability by type ​

Field / blocksimplevirtualdownloadablegroupedbundleconfigurablebooking
Common attrs (name, sku, url_key, meta, color/size/brand, dimensions, settings)✅✅✅✅✅✅ (colour/size on variants)✅
price / cost / specialPrice✅✅✅— (sells linked products)price:"0" (dynamic)— (per variant)✅
categories, channels, up_sells, cross_sells, related_products✅✅✅✅✅✅✅
customizable_options (custom options)✅✅—————
Type structure——downloadableLinks / downloadableSampleslinksbundleOptionsvariantsbooking

Custom options are a Bagisto simple/virtual-only feature — sending customizable_options on any other type is ignored by the store.

Keying rules for nested structures ​

New nested rows are keyed by a prefixed marker; a numeric/bare key is treated as an existing row id:

StructureNew-row key prefix
bundleOptions option groupoption_*
bundleOptions → productsproduct_*
links (grouped)link_*
downloadableLinkslink_*
downloadableSamplessample_*
customizable_optionsoption_* (its prices → price_*)
booking → tickets (event)ticket_*
variants (configurable)the existing variant product id (numeric)

Locale & channel ​

GraphQL has no query string, so translatable fields are written to the store's default locale and channel. To target a specific locale (e.g. write the French translation while leaving English untouched), use the REST endpoint with its ?locale=fr&channel=default query parameter — see the REST Update page.

Sub-resources are not updated here ​

images, videos, inventories, and customerGroupPrices are not handled by this mutation — they have dedicated operations. If sent, they are ignored and noted in the response warnings array:

Reading the Payload ​

Select whatever you need — the payload is the product itself:

graphql
adminCatalogProduct {
  _id
  sku
  type
  status
  urlKey
  price
  weight
  warnings
}

Connections resolve on the payload too, so you can read nested data back in the same round trip — images { edges { node { _id url } } } returns this product's images.

One value is easy to misread: specialPrice reads null until its window opens. Setting specialPriceFrom to a future date stores the price but leaves the field null until that date arrives. The value is saved; it is simply not the active price yet.

Errors ​

MessageCause
Product not found.Unknown id
The sku has already been taken.Duplicate SKU
You do not have permission to manage products.Token lacks catalog.products.edit

Other validation failures — a duplicate URL key, a non-boolean value in a boolean field, a special price at or above the price, or an inverted date range — surface the same way, in errors[] with null data.

Released under the MIT License.