Mercur

v2.4.0: Stripe & Magento 2 Connectors + seller regions

Nov 2, 2026

Mercur v2.4.0 connects to more of the outside world.

  • Payouts move to a thin core module + new Stripe Connector.
  • New Magento 2 Connector lets an external storefront sell marketplace offers.
  • Operators can assign sellers to regions.
  • The panels get a layout composer and deeper extension points.
  • Checkout and vendor lists get a performance pass.

Medusa was bumped to version 2.22.0, which requires Node 22.22+. This release has breaking changes, so please read What's Changed before you upgrade.

What's New

Stripe Connector

Core payouts are now shaped like Medusa's payment module: one provider per marketplace, one payout per seller order, and one payout_reversal per later refund. An order that isn't ready goes on_hold and is re-decided on the next run.

Core still schedules nothing. @mercurjs/stripe-connector-plugin brings the operations: seven scheduled jobs, settlements that net payouts, reversals and adjustments per seller and currency, operator adjustments, capture validation and failed-operation alerts.

Operators get Integrations → Stripe and Settings → Stripe, plus widgets on the seller and order pages. Vendors get their own Stripe page. If you use @mercurjs/payout-stripe-connect today, see What's Changed for the migration.

Magento 2 Connector

@mercurjs/magento2-connector-plugin lets a Magento 2 storefront sell marketplace offers while Mercur keeps sellers, split orders, commissions, and payouts. It ships HMAC-signed webhooks with retries and redelivery, and an external payment provider that authorizes at checkout and captures when Magento invoices the order.

Storefront refunds are mirrored onto the Mercur order, and there's an admin screen at /settings/magento. The Magento side is the separate mercurjs/magento2-connector Composer package.

Read the Magento 2 Connector announcement to explore more.

Regions

Operators decide which regions a seller operates in from the region page, the seller page, or Create Seller. Vendors see and price only in their assigned regions, and the offer grids get one column per region.

Admin keeps full visibility of prices across all regions. New sellers get the store's default region, and existing sellers have no regions until you assign them.

Layout composer

Admin product detail and vendor offer detail now render through a LayoutComposer that uses Medusa's entry IDs. Plugins, the Medusa project, and the host app are ordered layers where later wins, and any layer can contribute routes, widgets, layouts/, _layouts.ts and _navigation.ts.

Custom-fields configs can also hide, replace, or add columns and fields on embedded tables, spreadsheet grids, and built-in form fields, using the existing list and forms keys.

Vendor onboarding

Each onboarding step is now a tab of the seller onboarding form zone, so you can add, remove, reorder, or mark steps optional from a custom-fields config. The store handle is now required, with a live check against the new GET /vendor/sellers/handle-availability.

Going back after a failed Finish no longer wipes what the user typed.

Offer conditions

Operators manage conditions under Settings → Offer Conditions, and vendors pick one when creating or editing an offer.

Lead time defaults

Lead time gets its UI and a marketplace-wide default, set in Settings → Marketplace, on the store, and on the offer. GET /store/offers returns effective_leadtime_to_ship, resolved from offer to store to marketplace.

Telemetry

Mercur now sends anonymous telemetry from your server. It's on by default and prints nothing at boot, and it helps us see how many installations exist, which versions they run, and whether they keep running.

The server sends a startup event and a daily heartbeat with a random installation ID, versions, runtime, OS and infrastructure details, feature flags, and one-time milestones such as the first approved seller or first paid payout. Marketplace counts are sent as range buckets, never exact numbers. Only first-party plugins are named, custom ones are just counted, and each event says whether the install was seeded with demo data.

Every CLI command now reports its name, flag names, exit code, and duration, with flag values redacted unless they're a boolean or a fixed choice. The CLI stops sending blocks.json contents, aliasPrefix, CPU model and email, and the email prompt is gone.

Opt out with MERCUR_DISABLE_TELEMETRY, DO_NOT_TRACK or withMercur({ projectConfig: { mercur: { telemetry: false } } }). Telemetry is also off in CI, under NODE_ENV=test and in worker processes. Set MERCUR_TELEMETRY_DEBUG=true to print payloads instead of sending them.

Every event and property is listed on the telemetry docs page.

Storefront

  • Added a cart drawer that opens instantly, optimistic cart edits, and a quantity picker on the product page, so pages no longer wait on the cart.
  • Made POST /store/carts/:id/complete return the seller orders.

Core

  • Added an offerPricesUpserted hook, plus previous values, snapshots, and updated_by on the other offer hooks.
  • Added getStatistics on the seller and offer modules, with GET /admin/sellers/statistics and GET /admin/offers/statistics.
  • Added a deleted_at filter and with_deleted on admin offers and sellers, so a delta sync can see removals.
  • Added order_group.metadata, copied from cart.metadata.
  • Added is_replay on the paymentRefunded hook.

What's Changed

Admin & Vendor Panel

  • Made sellers region-scoped (breaking) – GET /vendor/regions now returns assigned regions only, GET /vendor/regions/:id returns 404 for the others, and a vendor offer or shipping price on an unassigned region returns 400. Set a default region under Settings → Store for new sellers, then link existing ones from the seller page or with POST /admin/sellers/:id/regions and { "add": ["reg_…"] }.
  • Changed the seller lead time default (breaking) – new sellers no longer default to a lead time of 2. They start at null and use the marketplace default from Settings → Marketplace. Existing sellers keep their current value, including 2, and clearing a store's lead time moves it to the marketplace default. If you ran the migration on a v2.3.9 canary, it cleared values of 2, so those sellers need them set again.
  • Scoped GET /vendor/payments through the order's payment collection (breaking), so shared, uncaptured cart-stage payments are not listed.
  • Pushed vendor list seller scoping into SQL EXISTS subqueries instead of id IN lists that grow with lifetime volume.

Storefront

  • Moved the storefront to Next 16 with Cache Components (breaking) – every route has a prerendered shell, the default first page of a listing sits in the HTML, and catalog reads are cached. Catalog prices are fetched anonymously, so customer-group price lists no longer show on catalog pages (the cart still applies them), and canonical and structured-data URLs now come from NEXT_PUBLIC_BASE_URL.
  • Removed orders.items.variant.product from store order groups (breaking) – asking for it explicitly returns 400. Use orders.items.product_handle and orders.items.product_title.

Core

  • Bumped Medusa to 2.22.0 (breaking) – it drops Node 20 and requires Node 22.22+. To pick up the October 2026 Node.js security releases, we recommend Node 24.22.1+, or 22.23.4+ if you stay on Node 22.
  • Removed @mercurjs/payout-stripe-connect (breaking) – install @mercurjs/stripe-connector-plugin and point the payout module at @mercurjs/stripe-connector-plugin/providers/payout-stripe-connect. If you also adopt the plugin's payment provider, add pp_stripe-connector_<id> to your regions.
  • Changed the payout module API (breaking) – createPayoutWorkflow is replaced by createOrderPayoutsWorkflow. On IPayoutProvider, createPayoutAccount becomes createAccount, and retrieveAccount and reversePayout are now required. PayoutStatus.CANCELED becomes ABORTED, and existing rows are migrated.
  • Made offers honour the product–seller allowlist (breaking) – createOffersWorkflow now refuses a product restricted to other sellers or rejected by the operator. Products with no link stay open to every seller.
  • Restructured the payout tables, added the region_seller link, order_group.metadata, a telemetry table and list indexes, and made seller.default_leadtime_to_ship nullable – run migrations before upgrading.
  • Loaded the commission rate table once per checkout, and added list indexes on order groups, offers, payouts, reviews and commission rules.

What's Fixed

Admin & Vendor Panel

  • Refetched admin and vendor product lists on search, filter, and sort.
  • Kept the date filter popover open while typing a custom date.
  • Loaded plugin extensions in the panels' ESM build, which silently started without them.
  • Fixed the 500 on GET /admin/products?sku=.
  • Stopped Edit prices on a vendor offer from wiping every price when saved before regions loaded.
  • Added status, bank payout, and period end filters to vendor Stripe settlements.

Storefront

  • Confirmed offer stock against the cart's total demand per inventory item, so buyers learn at add-to-cart rather than at checkout.
  • Subtracted reserved stock from availability on GET /store/offers.
  • Returned items.offer and items.offer.seller on store cart routes, so carts group by the right seller.
  • Stopped GET /store/order-groups returning 400 without fields, which crashed the storefront's order page.
  • Ignored an empty currency_code on POST /store/carts.

Core

  • Allocated cart credit lines across split orders, so the credit-covered part no longer shows as owed. Fully credit-covered orders still stay on hold for payout.
  • Compensated commission lines, payment captures, and links when checkout is canceled after completion, so no marketplace records stay behind.
  • Fixed checkout lock units: timeouts passed in milliseconds meant a lock wait of about 8 hours and a TTL of about 33. Concurrent completion under processPaymentWorkflow is now locked too.
  • Fixed in-place updates of quantity-tiered offer prices never completing.
  • Emitted product.published when an admin publishes a product.

Other

  • Set the store default region in the seed, so seeded installs can create priced sellers.
  • Cleared peer-dependency warnings on fresh installs by aligning tiptap and pinning @opentelemetry/api.
  • Rewrote the architecture page and the platform module docs, with new figures.
  • Split use cases into standalone marketplace and marketplace inside a store.
  • Split the Magento 2 integration into focused pages and added a demo video.
  • Pointed legacy redirects to existing pages.

More product updates

Ready to build?

Read the release notes, then see the product – open the demo, or book a walkthrough on your terms.