Upsert a product
Creates or updates a single product catalog entry through one endpoint. Omit id to create a new product (Distru assigns and returns its ID); pass an existing product's id to update it. An id that isn't valid, or one that doesn't belong to your company, returns a not-found error. On create you must supply at minimum name, sku, category_id, vendor_id, unit_type_id, unit_price, and inventory_tracking_method; your company settings can make more fields mandatory (for example a required description or a required product photo). name and sku must each be unique within your company.
Updates are sparse: only the fields you send are changed, and any field you omit keeps its stored value. The list- and map-valued fields replace wholesale when you send them, but omitting the field leaves the current value untouched. tags replaces the product's entire tag set when sent — any tag you leave out of the list is removed, and an empty array clears them all; omit tags to leave the current tags unchanged. custom_data likewise replaces the entire custom-field map when sent, and is left untouched when omitted. Menu placement is driven by menu_visibility: omit it to leave the product's current menu placement untouched; send DO_NOT_INCLUDE to remove it from all menus, INCLUDE_IN_ALL to place it on every menu, or INCLUDE_IN_SELECT with menus to set the exact set (that list replaces the product's full menu set — omit a menu to remove it). menus may only be sent alongside menu_visibility: it is required with INCLUDE_IN_SELECT and ignored with the other two modes, so sending menus without menu_visibility, or INCLUDE_IN_SELECT without menus, is rejected with a 400.
Some attributes are locked once established. inventory_tracking_method cannot be changed after it is first set — the only allowed transition is PRODUCT to BATCH. unit_type_id cannot be changed once the product has any inventory. Attempting either returns a validation error.
This endpoint writes only the product's catalog record. It does NOT create, move, reserve, or release inventory (add packages or batches separately), and it does NOT itself push the product to Metrc or BioTrack — products are local catalog data and only their inventory syncs to state traceability. For BioTrack companies the category_id you choose must be compatible with inventory_tracking_method (a PACKAGE-tracked product needs a category tied to a BioTrack inventory type; a non-package one needs a category that is not). Changing menu_visibility or menus changes which DistruCommerce menus and the Order Tracker surface the product. If the product is linked to a connected sales channel (LeafLink, or a POS such as Blaze/Dutchie/Treez), catalog and price edits made here propagate to that channel. The product's bill_of_materials is readable in the response but is NOT settable here — manage it through its own endpoints.
Required permission: products_permissions_create to create a new product, or products_permissions_edit (plus access to the product under team restrictions) to update an existing one.
Request body
Response
A single product
Changes
No recorded changes to this endpoint across all 1 revision of this API.