Skip to main content
Stage a product edit as a ProductChange instead of writing to the product, so it goes through the same review as an edit from the Vendor panel. Use this when you build your own edit surface, such as a bulk editor or an import.

Before you begin

You need the following in place:
  • A Mercur server with @mercurjs/core installed through withMercur()
  • A product id, and the id of the actor making the edit, such as a seller id (sel_…)

Stage a field edit

productEditUpdateProductWorkflow compares your update with the product and stages one action per field that differs.
1

Create the route

Add a route under /admin so Medusa authenticates the caller, and pass the update to the workflow. The workflow returns the staged change.
src/api/admin/custom/products/[id]/edit/route.ts
The route answers 202 because the edit isn’t on the product yet. With the default product_request flag on, result.status is pending.
2

Handle an open change

If the same created_by already has a pending change on the product, the workflow throws a NOT_ALLOWED error before it stages anything. Medusa’s error handler turns it into a 400 response. Cancel the open change with cancelProductChangeWorkflow, or wait for an operator to resolve it.
3

Read the staged actions

Load the change with its actions to show the seller what’s waiting for review.
Each UPDATE action carries field, value, and previous_value in details.
If no field differs, the workflow still stages a change, with no actions. Compare the input yourself first when an empty change would confuse your reviewers.

Stage variant and attribute edits

Variants and attributes have their own edit workflows, with the same pending check. productEditUpdateVariantsWorkflow takes a list of typed operations:
Each operation becomes a VARIANT_ADD, VARIANT_UPDATE, or VARIANT_REMOVE action. An update whose fields all match the current variant stages nothing. For attributes, pass add, remove, and update arrays to productEditUpdateAttributesWorkflow, in the same shapes as the attribute batch.

Stage actions directly

For a mixed change, build the actions yourself and pass them to stageProductChangeWorkflow. It skips the diff and the pending check, so check for an open change first.
Every action needs its own product_id. The workflow fills in product_change_id for you.

Apply an edit without review

Pass auto_confirm: true to stageProductChangeWorkflow or productEditDeleteProductWorkflow to confirm and apply the change in the same run. Use it for trusted sources, such as an operator tool. The change still lands in the trail as confirmed, and product-change.confirmed still fires.

Attach custom data with additional_data

productEditUpdateProductWorkflow and productEditUpdateAttributesWorkflow accept additional_data and pass it to their productChangeCreated hook. Use the hook to store your own data on the change:
src/workflows/hooks/product-change-created.ts
The hook runs after staging and auto-confirm, so product_change is the record the workflow returns.

Next steps