Skip to main content

Update Product

PUT 

/api/products/:id

Update an existing product by ID. All fields are optional on update.

Required scope: products:write

Grant this scope to your token under Settings → Developer → Personal Access Tokens.

Authentication: Requires Bearer token.

Product type cannot be changed if inventory movements exist (exception: standard -> kit is allowed). Additionally, an inventory-bearing product (standard/kit/blemished/manufactured) cannot be converted to a non-inventory type (bundle/matrix) while it still carries any inventory ledger - a FIFO layer OR an inventory movement of any type (including stock_take, receipt, adjustment, transfer). This prevents orphaning stock layers and movements.

For update (PUT), additional field available:

  • initial_inventory.warehouses[].id (required with initial_inventory)
  • initial_inventory.warehouses[].quantity (required)
  • initial_inventory.warehouses[0].unit_cost (required)
  • images[].id — required only when images[].operation is delete
  • images[].operation — nullable|in:update_create,delete

Optional field: mpn (string, max 255, nullable) — manufacturer part number.

Optional field: hts_code (string, max 255, nullable) — Harmonized Tariff Schedule code.

Returns 422 if product type change is invalid.

Bundle / Kit components: When the resulting product type is bundle or kit, components[] must be present and non-empty. This applies whether you are (a) changing the type from standardbundle|kit, (b) updating an existing bundle/kit that currently has no components, or (c) sending an empty components: [] payload (which would otherwise wipe components). Returns a 422 validation error on the components field in these cases. Updates that don't touch components on a bundle/kit which already has components are unaffected. To convert a standard product that has no components yet, supply components[] in the same request as the type change — the components are saved as part of the same update, satisfying the requirement atomically.

Note (pricing tiers): When sending suppliers[].pricing[] entries with operation: updateOrCreate (or omitted), price is required and must be a numeric value >= 0 and < 100000. To remove a tier, send operation: "delete". Sending price: null will return a 422 validation error on suppliers.{i}.pricing.{j}.price.

Lot tracking fields (optional):

  • is_lot_tracked (boolean, nullable) — enable batch/lot tracking for this product.
  • lot_tracking_method (string, nullable) — required when is_lot_tracked is true. Allowed values: fifo (First-In, First-Out), fefo (First-Expiry, First-Out).

Stock unit of measure (optional):

  • stock_uom_id (integer, nullable) — id of a row in units_of_measure. When omitted, the product is auto-assigned EACH as its stock UoM on create. Pick KG, L, etc. for bulk weight or volume products so quantities, purchase orders, sales orders, and stock takes use the correct unit from day one.

Also accepts expiration_offset_months (integer 0-120, nullable) — the product's default FBA-inbound shelf-life estimate in months; blank uses the app default (10). Responses include it too.

Request

Responses

OK

Response Headers
    Content-Type