Before you begin
You need the following in place:- A Mercur server with
@mercurjs/coreinstalled throughwithMercur() - A change in
pendingstatus. Changes staypendingonly while theproduct_requestfeature flag is on, the default
Review and resolve a change
Find the pending change, then confirm or decline it.1
Find pending changes
List the pending changes on a product with their actions, so a reviewer can see what each one does.Each action’s
details holds the proposed value and the previous one, as described in Change actions.2
Confirm the change
confirmProductChangeWorkflow sets the changes to confirmed, applies their actions to the product, and emits product-change.confirmed.src/api/admin/custom/changes/[id]/confirm/route.ts
ids array. Pass internal_note or external_note to overwrite the change’s notes as you confirm it.3
Or decline it
rejectProductChangeWorkflow sets one change to declined and leaves the product untouched. Give the seller a reason in declined_reason.product-change.declined with the change id.Cancel a change
Cancel a change when it should be withdrawn rather than judged, for example when a seller retracts their own edit. Canceling frees the author to stage a new change on the product.canceled_by and canceled_at, then emits product-change.canceled.
Confirm several changes at once
confirmProductChangeWorkflow loads every id in ids before it writes anything. If one id doesn’t exist, it throws a NOT_FOUND error. If one change isn’t pending, it throws NOT_ALLOWED, and none of the changes are confirmed.
Handle a failed apply
Applying actions runs Medusa’s product workflows inside the confirm workflow. If one of them fails, for example because a variant was already deleted, the workflow compensates: it restores the change topending and clears confirmed_by and confirmed_at. Fix the cause, then confirm again.
Run your own logic on a resolution
Each resolution workflow has a hook that receives the change ids and theadditional_data you passed in:
confirmProductChangeWorkflow:productChangeConfirmed, with{ ids, additional_data }rejectProductChangeWorkflow:productChangeRejected, with{ id, additional_data }cancelProductChangeWorkflow:productChangeCanceled, with{ id, additional_data }