Skip to main content
Run the checkout split yourself when you build a custom completion flow, or hook into it when you need to block a checkout or set the initial status of each seller’s order.

Before you begin

You need the following:
  • A cart ready to complete: items bought through offers, a shipping method for each seller that ships, and a payment session
  • Mercur’s cart completion in place: Mercur’s cart completion route already runs this workflow, so you only need your own route for a custom flow

Complete a cart from a custom route

1

Run the workflow

Call completeCartWithSplitOrdersWorkflow with the cart id. Set throwOnError: false so you can handle payment errors yourself.
src/api/store/carts/[id]/place/route.ts
The workflow returns { order_group_id }. It runs once per cart: a second call for the same cart returns the existing group’s id.
2

Return the group to the shopper

Load the group with query.graph and send it back instead of the bare id:
ContainerRegistrationKeys comes from @medusajs/framework/utils.

Handle a failed payment authorization

The workflow authorizes the payment session after it creates the orders. If authorization fails, the workflow rolls back: it deletes the group, and Medusa’s steps undo the orders, links, and reservations. Mercur’s own route answers PAYMENT_AUTHORIZATION_ERROR and PAYMENT_REQUIRES_MORE_ERROR with a 200 that carries the cart and the error, so the storefront can retry payment. Do the same in a custom route:
Throw every other error so Medusa’s error handler responds with the matching status.

Block a checkout with the validate hook

The validate hook runs before the split and receives the workflow input and the cart. Throw to stop the checkout:
src/workflows/hooks/validate-split-cart.ts
The hook runs on every cart completion, including completions started by a payment webhook through processPaymentWorkflow.

Set the initial order status with setOrderStatus

Child orders start as pending. Return a status from the setOrderStatus hook to change that, for example when sellers must accept an order before they fulfill it:
src/workflows/hooks/set-split-order-status.ts
status applies to every child order. status_by_seller_id overrides it for the sellers you list. Return nothing to keep pending.

React to the new group

The split emits order_group.created with the group id, and order.placed once for each child order. Subscribe to the first for purchase-level work, such as a single confirmation email, and to the second for per-seller work. The event reference has a subscriber example.

Next steps