Skip to content

Catalog Product — Update

Updates a catalog product (any of the 7 types). This is a partial patch — send only the fields you want to change. Omitted fields keep their current value.

Endpoint

EndpointMethod
/api/admin/catalog/products/{id}PUT

Path parameters

FieldTypeRequiredNotes
idintegeryesProduct ID.

Query parameters

ParamDefaultNotes
localestore defaultThe locale that translatable fields (name, description, short_description, meta fields, …) are written to. One locale per request — repeat the call with a different ?locale= to edit another translation.
channelstore defaultThe channel used for channel-scoped attribute values.

Editing attributes by code

Every attribute on the product's family is editable by its code, sent at the top level of the JSON body (snake_case). This includes the common fields and any family-specific ones:

Field codeNotes
name, url_key, short_description, descriptionTranslatable — written to the requested ?locale=.
meta_title, meta_keywords, meta_descriptionSEO fields (translatable).
price, weightDecimal as string.
status, new, featured, visible_individually, guest_checkoutBoolean flags as 0 / 1.
tax_category_idExisting tax category id.
color, size, brand, product_number, …Any family-specific attribute, by its code.

Translatable fields write to the requested locale only — pass ?locale=fr&channel=default to target the French translation; the other locales are untouched.

Replace-on-send relations

These fields replace the product's current set when present, and are preserved when omitted:

FieldNotes
categoriesint[] — the product's category assignment.
channelsint[] — the product's channel assignment.
up_sells, cross_sells, related_productsint[] — product relation lists.

Type-structure fields

The type-specific structure keys replace that structure when sent — send the full set. See the examples: dropdown for the verified payload of each:

TypeFieldNotes
downloadabledownloadable_links, downloadable_samplesKeyed map of link/sample rows.
groupedlinksKeyed map of { associated_product_id, qty, sort_order }.
bundlebundle_optionsKeyed map of option groups (typeradio / checkbox / select / multiselect) each with a products map.
configurablevariantsKeyed by variant product id (from the create response or detail variants[].id). Replace-semantics — send every variant to keep.
bookingbookingObject with type (default / appointment / event / rental / table) plus sub-type fields (slots / tickets / pricing).

New-row key prefixes

Inside a nested structure a new row is keyed by a prefixed marker; a bare or numeric key is treated as an existing row id (and fails if it doesn't exist):

StructureNew-row key prefix
bundle_options option groupoption_*
bundle_optionsproductsproduct_*
links (grouped)link_*
downloadable_linkslink_*
downloadable_samplessample_*
customizable_optionsoption_* (its pricesprice_*)
bookingtickets (event)ticket_*
variants (configurable)the existing variant product id (numeric)

Customizable options (including file type)

customizable_options (custom options) are a Bagisto simple & virtual-only feature — the edit form shows the Custom Options accordion only for those two types, and the API ignores the field on any other type. Configurable, bundle, grouped, and downloadable products do not support them.

Each option has a type: text, textarea, select, multiselect, checkbox, radio, date, datetime, time, or file. A file option also carries a supported_file_extensions value — a comma-separated list the admin defines (e.g. pdf or jpg,png,pdf). There is no fixed API list of formats; the allowed set is whatever that option specifies, and the storefront upload rejects any other extension. Storefront clients read these options (and their supported extensions) from the product's customizableOptions and upload a matching file via the shop customizable-file upload endpoint.

Sub-resources are not updated here

images, videos, inventories, and customer_group_prices are not handled by this endpoint — they have dedicated endpoints. If sent, they are ignored and noted in the warnings array on the response:

Response

200 OK returning the full product detail payload — same shape as GET /api/admin/catalog/products/{id}.

warnings is an array of human-readable strings; it is empty when nothing was dropped, and non-empty (naming each dropped sub-resource field and the endpoint it should be sent to instead) when sub-resource fields were stripped.

Errors

HTTPCause
401 UnauthorizedMissing or invalid admin Bearer token.
403 ForbiddenAdmin role lacks catalog.products.edit.
404 Not FoundProduct not found.
422 Unprocessable EntityValidation failure (duplicate SKU / url_key, invalid boolean, special_price ≥ price, invalid date range).

Released under the MIT License.