Skip to main content
Drive a store through its lifecycle from your own server code, for example to auto-approve vetted sellers or to suspend a store when a risk check fails. Each transition is a workflow that validates the current status, writes the change, emits an event, and exposes a hook.

Moderate a store

1

Approve a pending store

approveSellerWorkflow moves a pending_approval store to open and stamps approved_at.
src/api/admin/stores/[id]/vet/route.ts
2

Suspend and reinstate a store

suspendSellerWorkflow takes an optional reason, which it saves in status_reason. unsuspendSellerWorkflow reopens the store and clears the reason.
3

Terminate a store

terminateSellerWorkflow accepts a pending_approval or suspended store. Suspend an open store first.
To undo it, run unterminateSellerWorkflow. It returns the store to suspended, and you reopen it with unsuspendSellerWorkflow.

Reject a pending application

Mercur has no separate reject workflow. Run suspendSellerWorkflow on the pending_approval store with a reason: it stamps rejected_at and keeps the store out of the Store API. Terminate it afterwards if the decision is final.

Handle a failed transition

Each workflow checks the starting status and fails with a NOT_ALLOWED error when the transition isn’t allowed. Nothing is written in that case. Pass throwOnError: false to read the error instead of catching it.
An open store makes notAllowed true here, with the message “Cannot terminate an open seller. Suspend or close first.” The workflow also fails when the seller id doesn’t exist, because its lookup step runs with throwIfKeyNotFound.

Extend a transition with a hook

Each lifecycle workflow exposes a hook that receives seller_id and additional_data. Register a handler to run your own step inside the transition.
src/workflows/hooks/seller-approved.ts
The other hooks follow the same shape: sellerSuspended, sellerUnsuspended, sellerTerminated, and sellerUnterminated.

Run side effects from a subscriber

Subscribe to the lifecycle events for work that shouldn’t block the transition, such as emails. Each event carries { id }, the seller id.
src/subscribers/store-suspended.ts

Next steps