Skip to main content
The MarketplaceService class (accessed via client.marketplace) is the entry point for building a multi-merchant marketplace storefront — one shopfront where many independent merchants are aggregated into a single shopping experience, a single cart can span several merchants, and one payment is automatically split to each merchant. If you’re building a normal single-store storefront, you don’t need this service at all — use products, cart, orders, etc. directly. This page is for marketplace deployments.

Before you start: how a marketplace works in Tybrite

A few concepts make everything else click.
  • Marketplace vs. merchant. A marketplace aggregates many merchants (each is an independent store with its own catalog, pricing, and inventory). The marketplace operator sets commission and branding; merchants keep full control of their own products.
  • The operator key. A marketplace storefront authenticates with a single marketplace operator key (a publishable key, tybrite_pk_..., minted by the operator). You use this one key for everything the storefront does: browsing the aggregated catalog, rendering a single merchant’s shop page, signing shoppers in, previewing carts, and checking out. You do not juggle per-merchant keys.
  • Aggregated reads. When you call the normal catalog endpoints (products, taxonomy, search) with the operator key, they automatically return results across every active merchant, and each product/result is stamped with the merchant_store_id it came from. Pass storeId to narrow any of them to one merchant.
  • One shopper, every merchant. A shopper signs up once and can buy from any merchant. Their identity belongs to the marketplace, and they hold no customer record with any merchant. A purchase is tied to the credential it was placed with — a Galactic Core shopper session (x-auth-token) or an assertion signed by the marketplace’s own backend (x-external-auth) — and getMarketplaceCustomer returns every purchase tied to that credential across the marketplace.
  • The marketplace wallet. Credit the marketplace issues to a shopper — for example when a dispute is decided as credit rather than a refund — is held by the marketplace, not by a merchant. getMarketplaceWallet returns the balance, and checkout can spend it.
  • Unified split checkout. A single cart may contain items from several merchants. One marketplaceCheckout call creates one payment for the whole basket; after the shopper pays, each merchant is paid their share (gross minus commission) automatically. You never move money yourself.
Use the marketplace operator key for everything on this page (and for aggregated products/taxonomy/search reads). It’s a publishable key, safe for the browser. Merchant-side setup (a merchant connecting their payout account) and operator back-office (payout reports) are not part of this API — they happen in the admin apps.

The typical integration flow

A marketplace storefront usually wires up in this order:
  1. Identify the marketplace — getMarketplaceInfo() to get the name, logo, colors, and which capabilities are on.
  2. Browse — client.products.listProducts(), client.taxonomy.listCategories(), client.search.searchProducts() with the operator key for the aggregated catalog.
  3. Shop a single merchant (optional) — pass storeId to the reads above + getMarketplaceInfo({ storeId }) for that merchant’s shop page.
  4. Sign the shopper in — client.authentication.register / login (operator key) → you get a shopper session token.
  5. Build a cart client-side — collect line items, each tagged with its merchant_store_id.
  6. Show the total — marketplaceCheckoutQuote() with the cart and the delivery address returns each merchant’s shipping line and the total, without reserving anything.
  7. Check out — marketplaceCheckout() → returns a client_secret; complete the payment with Stripe.js on the storefront.
  8. Order confirmation / account — the order finalizes automatically on payment success; getMarketplaceCustomer() shows the shopper’s cross-merchant history and getMarketplaceWallet() their marketplace credit.

Methods

getMarketplaceInfo

Read information about the marketplace. This is usually the first call your storefront makes. It has two modes, controlled by whether you pass storeId:

Mode 1 — Marketplace identity & branding (no storeId)

Returns the marketplace’s own name, branding, contact details, and which capabilities are enabled. Use it to render your storefront chrome (logo, colors, name) and to feature-detect (e.g. only show the fee line if commission_enabled).

Mode 2 — One merchant’s full store context (storeId)

Returns the same comprehensive payload as client.system.getStoreInfo, but for a single merchant inside the marketplace. This is what you render on a merchant’s shop page header — their business info, a catalog summary with a small sample of products, payment methods, shipping, CMS content, and feature flags — in one call. It’s also ideal as context for an AI shopping agent describing one merchant.
The catalog block returns counts plus a small sample of products (each with a few fields: id, name, category, price, image). It is intentionally not the full catalog — use client.products.listProducts({ storeId }) to actually browse and paginate a merchant’s products.
Parameters Responses

marketplaceCheckout

Check out a cart that may contain items from multiple merchants in one call. Each line item names the merchant it belongs to. Tybrite validates the items against the live marketplace catalog, resolves commission per merchant, and creates one payment for the entire basket. The response gives you a client_secret to complete the payment on the storefront (with Stripe.js), the shipping charged per merchant in shipping_breakdown, and a per-merchant merchant_breakdown (gross, discount, shipping, commission, net) you can display. You can also apply discounts. Pass an optional discounts array to apply a merchant’s own promotion or gift card to that merchant’s portion of the basket — each entry names a merchant_store_id and an optional promotion_id and/or gift_card_code, and the discount reduces only that merchant’s subtotal. Marketplace-wide promotions run by the operator apply automatically — you don’t pass them. The response then reports discount_total, the operator_funded_discount (the share the operator funded), a per-merchant discount_breakdown, and discount_amount + merchant_gross on each merchant_breakdown entry. The shopper. Pass the shopper’s credential to tie the purchase to them: xAuthToken (a Galactic Core shopper session, also accepted as xCustomerToken) or xExternalAuth (an assertion signed by the marketplace’s own backend with the marketplace’s signing secret). Send at most one. With neither, the checkout is a guest checkout. The credential a purchase was placed with is what later lets the shopper see it in getMarketplaceCustomer, return it and dispute it. A guest purchase is added to an account once that account has verified the email address it was bought with, by a one-time code or a sign-in link. Currency. Every price is charged in the marketplace’s currency. A merchant who prices in another currency is converted with the exchange rate the marketplace sets for that currency — items, the merchant’s discounts, gift-card amounts and delivery fees alike, each rounded to the marketplace currency’s minor units. A merchant whose currency has no rate in the marketplace cannot be bought from there: the checkout answers 400 item_currency_unsupported. Shipping. Each merchant’s items are delivered, and priced, separately, so the checkout carries one shipping line per merchant. By default a merchant’s own delivery rates price their line, converted to the marketplace’s currency; items the marketplace ships itself are priced by the marketplace’s own delivery rates (pricing: operator_rate). A merchant’s line is priced using shipping_destination or, when that is omitted, the located shipping_address. The marketplace may instead charge a flat rate per merchant, and may set a free-shipping threshold: a merchant whose items total at least that much ships free. To offer carrier options, call marketplaceCheckoutQuote with a street shipping_address and a parcel per merchant in shipping_selections, then send the chosen option’s rate_id and rate_source here. Shipping is paid to whoever ships the items: the merchant, or the marketplace when it ships on the merchant’s behalf. A shipping amount is never read from the request; total_amount includes shipping and shipping_total reports it. The wallet. A signed-in shopper can spend their marketplace wallet: wallet_amount spends up to that amount, and use_wallet: true spends as much as the checkout allows. The balance is held while payment is pending and returned if the payment fails or is abandoned. The charge never falls below the payment provider’s minimum for the currency, so a wallet does not pay for a whole basket on its own. The response reports wallet_applied, and total_amount is the amount charged after it. Each merchant is still paid their full net, because the marketplace operator funds the wallet. Sending either wallet field without a shopper credential answers 401.
Once the payment succeeds, the order finalizes automatically — Tybrite creates each merchant’s order, splits the funds, reduces stock, and links the shopper to each merchant. You do not make any follow-up API call.
Stock is reserved at checkout. When you call marketplaceCheckout, the items are held against each merchant’s inventory immediately (so two shoppers can’t buy the last unit at once), and the hold is converted to a real stock reduction when payment succeeds. If an item can’t be held, the call fails with 400 insufficient_stock and no order or payment is created. Holds expire automatically (a short window) if the payment is never completed, returning the stock to availability — so an abandoned checkout never permanently locks inventory.
You don’t resolve commission separately. The merchant_breakdown in this response already contains the per-merchant gross/commission/net. (If you need to show fees on the cart page before checkout, compute them from your own displayed prices, or call checkout when the shopper is ready — there is no separate public commission endpoint.)
Request body Retrying safely (idempotencyKey) Shopper credential (optional, at most one) Response (201)
Response
total_amount is the amount charged: the basket after every discount, plus shipping, less wallet_applied. In merchant_breakdown, gross_amount is a merchant’s portion before discount and merchant_gross after the merchant’s own discount. shipping_charged is the shopper’s shipping for that merchant’s items; shipping_amount is the part the merchant receives and shipping_retained the part the marketplace keeps when it ships the items itself (fulfillment_mode: "operator"). shipping_commission is commission on the merchant’s shipping, when the marketplace charges it. net_amount is what the merchant receives: merchant_gross plus shipping_amount, less commission_amount, which includes any shipping_commission. Responses

marketplaceCheckoutQuote

What marketplaceCheckout will charge for a basket, per merchant, before the shopper pays. It takes the same body and runs the same computation as the checkout, but holds no stock, creates no order and starts no payment, so a storefront can call it whenever the basket or the address changes. The quote carries each merchant’s shipping line and never includes commission or what a merchant is paid. When a merchant’s entry in shipping_selections carries a parcel and the request carries a street shipping_address, that merchant’s carrier options are listed in shipping.rates. Send the chosen option’s rate_id and source (as rate_source) to marketplaceCheckout. Carrier options are not offered for items the marketplace ships itself.
Request body The same fields as marketplaceCheckout. customer_email is not required, and the wallet fields are not read, because a quote charges nothing. Response (200)
Response
total_amount is what the checkout will charge before any wallet balance. merchandise_total is a merchant’s items after discounts. shipping.pricing names what priced the line: seller_rate (the merchant’s own delivery rate), carrier_rate (a chosen carrier option), flat (the marketplace’s flat rate) or free. shipping.fulfilled_by is seller or marketplace. Responses

getMarketplaceCustomer

Return a shopper’s marketplace profile — their identity, the merchants they have bought from, and their order history across every merchant in this marketplace — in one response. Use it for the shopper’s account page. A purchase belongs to the shopper when it was placed with their credential. A purchase made as a guest belongs to them once they have verified the email address it was bought with, by a one-time code or a sign-in link; registering an account with that address is not enough. customer.email_verified reports which applies. A marketplace shopper holds no customer record with any merchant, so customer.ids is empty. The call takes the operator key plus exactly one shopper credential: xAuthToken (a Galactic Core shopper session, also accepted as xCustomerToken) or xExternalAuth (an assertion signed with the marketplace’s signing secret).
Response (200)
Response
stores has one entry per merchant the shopper bought from here, derived from their orders; total_purchases and total_spent count paid orders only. Responses

getMarketplaceWallet

Return the shopper’s marketplace wallet: the balance the marketplace has credited them — for example when a dispute is decided as credit rather than a refund — and the credits that make it up, newest first (up to 50). The balance is held by the marketplace, not by any merchant, is kept separately in sandbox and production, and is spent at checkout with wallet_amount or use_wallet on marketplaceCheckout. The call takes the operator key plus exactly one shopper credential, as for getMarketplaceCustomer.
Response (200)
Response
balance is the spendable total in currency (the marketplace’s settlement currency). On each credit, amount is what was credited and balance what remains of it; status is one of active, depleted, expired or void, and source says why it was issued. Responses

Aggregated reads (the marketplace catalog)

You don’t use MarketplaceService for browsing — you use the normal services with the operator key, and they automatically aggregate across every active merchant. Each product/result carries its source merchant_store_id.

Single merchant “shop page”

To render one merchant’s storefront inside the marketplace, pass storeId (the merchant’s id) to the aggregated reads. Everything narrows to that one (active) merchant:

Reading a product’s reviews on the marketplace

With the operator key, you can read approved reviews for a product, but you must say which merchant owns it via storeId (required for operator keys). Submitting, deleting, or voting on reviews is still done with a shopper session, not the operator key.
storeId only narrows results when you use an operator key. With a single-store key it’s ignored (you’re already scoped to one store). On reviews, an operator key requires storeId and may only read approved reviews.

Returns on the marketplace

A return always belongs to one merchant — the merchant whose order is being returned. So with the operator key, every client.returns shopper action takes a required storeId (the merchant from the order) alongside the shopper’s credential. A shopper’s returns are therefore per-merchant: to show “all my returns” across the marketplace, fetch each merchant the shopper ordered from and merge the lists in your storefront. The order must be one the shopper bought through the marketplace: a purchase placed with their credential, or a guest purchase made with an email address they have verified. The shopper holds no customer record with the merchant, and a marketplace return is refund-only:
  • createReturn with return_type: 'store_credit' answers 400.
  • getStoreCredit answers 400; the shopper’s marketplace credit is read with getMarketplaceWallet.
  • acceptReturnCredit answers 409, because a marketplace return never carries a store-credit offer.
Credit on a marketplace is issued through a dispute instead: when the operator decides a dispute as credit, the amount is added to the shopper’s marketplace wallet.
The same storeId applies to getReturn and requestReturnRefund. The storeId must be an active merchant in this marketplace. See the Returns reference for the full method set.
This is a shopper acting on their own returns at one merchant. There is no cross-merchant “all returns” feed in the API — operator oversight of returns is a back-office concern, handled in the operator’s admin, not through the SDK.

Curated collections (homepage merchandising)

A marketplace operator can curate merchandising sections for the storefront — for example “Trending now”, “Featured shops”, or a seasonal promotion rail. Each section groups products, merchants, or promotions the operator hand-picked (or auto-curated) to merchandise the storefront. Use them to build your homepage. Two operator-key methods cover this: listMarketplaceCollections returns the sections, and getMarketplaceCollection returns one section’s resolved members. Curating the sections themselves is an operator back-office task in the Super Admin app — not part of this API.

listMarketplaceCollections — the storefront’s curated sections

Response

getMarketplaceCollection — one section’s members

Response

Blending curated collections with sponsored + organic

Curated collections, sponsored placements, and organic recommendations are complementary — a typical homepage interleaves all three. Fetch them together:

Advertising / sponsored placements

A marketplace storefront can show placements in named slots (a hero banner, a category strip, a search-results rail), blended in with your organic listings or recommendations. A slot returns two kinds of placement:
  • Sponsored (sponsored: true) — paid spots that promote a merchant’s products or shop. These must be rendered with their disclosure_label.
  • Curated fallback (curated: true, sponsored: false) — placements the marketplace operator hand-picks to fill a slot when no paid placement is available. These are not labelled as sponsored.
Two operator-key methods cover the whole storefront side: getAdSlot fetches what to show in a slot, and logAdEvent reports impressions and clicks. Booking placements, setting rates, and managing slot inventory are operator back-office tasks done in the Super Admin app — they’re not part of this API.
Paid placements carry a disclosure_label (for example "Sponsored"), and advertising-disclosure rules in most jurisdictions require it to be rendered wherever sponsored is true, so a shopper can distinguish it from an organic result. Curated fallback placements (sponsored: false) are not paid advertising and do not carry the label.

getAdSlot — what to show in a slot

Response
For a 'promotion' placement (or a promotion item in a curated collection), the payload gives you a promotion_id and a merchant_store_id. Fetch the promotion’s detail — and the products it features — with client.promotions.getPromotion({ id: promotion_id, storeId: merchant_store_id }). See PromotionsService → Getting the products in a promotion for how each promotion type (percentage / fixed / bundle / bogo) resolves its products.

Blending with organic recommendations

Sponsored placements sit alongside organic results, not in place of them. A common pattern is to fetch both and interleave:

logAdEvent — impression & click beacons

Fire one impression per placement when it becomes visible, and a click when the shopper clicks it. Beacons are fire-and-forget.
The response is { recorded: true, billable }. billable tells you whether the event counted toward billing after de-duplication and invalid-traffic filtering — it’s informational, so you don’t need to act on it.

What is NOT in this API

These are deliberately not SDK methods, because they’re administrative, not storefront actions:
  • A merchant connecting their payout account (Stripe Connect onboarding) — the merchant does this from their own admin/POS, not over the storefront API.
  • Running or viewing operator payout reports — the operator does this from the Super Admin app.
  • Setting commission rules / marketplace branding — configured by the operator in the Super Admin app; you only read the resulting branding via getMarketplaceInfo.
So the public marketplace surface is exactly: getMarketplaceInfo, marketplaceCheckout, getMarketplaceCustomer, getMarketplaceWallet, listMarketplaceCollections, getMarketplaceCollection, getAdSlot, logAdEvent, plus the operator-key behavior of the catalog/search/auth/reviews/recommendations reads.

Putting it together — a minimal storefront


Error handling

All marketplace methods follow the standard response-code contract and throw a typed ApiError: