- Galactic Core Store —
086e8d7f-b84d-41bc-8acd-3f5740ea61dc(we call it merchant A) - Galactic Test Store —
ef7b07d3-424b-4b03-b1d4-30a2d2073b61(merchant B)
Operator keys and store keys
Two kinds of API key separate everything on this page:- A store key (
tybrite_pk_*/tybrite_sk_*) is scoped to one merchant. Catalog reads return only that store’s products and writes act on that store alone, which is what a single merchant’s own storefront uses. - An operator key is issued for a marketplace deployment and aggregates across all active merchants
in that marketplace. Discovery reads return the combined catalog, each row stamped with its source
merchant_store_id, and the operator can run a unified checkout that fans a single basket out to the right merchants.
tybrite_pk_*) covers the
read surfaces a storefront calls from the browser — discovery, marketplace info, collections, ad
slots. The secret operator key (tybrite_sk_*) runs on your server for the unified checkout, which
starts a payment, and the unified shopper profile.
Operator keys work on the discovery and marketplace surfaces (products, categories, search,
reviews, marketplace info, unified checkout, the unified profile, ad slots, collections, and
cross-merchant trending recommendations). Per-merchant surfaces like promotions, gift cards, posts,
and per-merchant cart writes reject an operator key with
403 — those belong to a single
merchant’s own store key.SDK calls in marketplace mode
Most standard GC SDK calls work unchanged under an operator key: a marketplace storefront is built from the sameclient.products / client.search / client.cartWishlist / client.returns as a
single-store one. The table below covers what does change, and where a marketplace-only call replaces
a standard one.
Discovery, cart, and recommendations aggregate automatically; anything tied to one merchant —
returns, reviews, promotions, store info — takes that merchant’s
storeId; and checkout, the unified
profile, collections, and ads exist only in marketplace mode.
The storefront API and the operator back-office
1. Aggregated discovery — combined, then narrowed
Discovery endpoints called with an operator key return results aggregated across every active merchant. Each product row carries amerchant_store_id identifying the merchant that sells it, so
the same listProducts call returns rows from multiple merchants.
Response
merchant_store_id and merchant_store_name, so
a single page of results spans the whole marketplace. storeId narrows discovery to one merchant
within it — the same call, returning only that merchant’s rows:
Response
merchant_store_id: ef7b07d3-…, merchant B alone.
Cross-merchant trending recommendations
type: 'trending' recommendations called with the operator key return a cross-merchant rail. Each
item is stamped with the merchant_store_id that sells it, which is what links a card through to the
right merchant’s product.
Response
2. Marketplace info
The marketplace’s own identity and branding — name, logo, tagline, contact, and whether unified checkout and commission are enabled — is what the storefront shell renders from. It requires an operator key; a single-store key gets403 and calls getStoreInfo instead.
Response
marketplace, mode, unified_checkout, and commission_enabled flags always come back. The
branding fields — name, logo_url, primary_color, tagline, contact, address — are null until
the operator sets them in their admin, so a storefront needs fallbacks for their absence.
storeId returns one merchant’s full store info, in the same shape as a single-store
getStoreInfo, which is what a per-merchant shop page renders from:
storefront.marketplace.getMarketplaceInfo({ storeId: 'ef7b07d3-424b-4b03-b1d4-30a2d2073b61' }).
A merchant not active in the marketplace returns 404.Currency and pricing have different owners in a marketplace. The storefront currency is
marketplace-wide, being the operator’s deployment-level default, so the whole aggregated catalog
renders in one currency rather than a different one per merchant. Dynamic pricing rules are
per-merchant: each merchant authors their own rules for their own products, and the operator cannot
set a merchant’s prices. Commission and payout rules are the operator’s, configured in their admin,
and separate from both.
3. Unified split checkout — a cart that spans two merchants
A single shopper cart spanning multiple merchants checks out as one order with one payment. Both merchants from step 1 go into a single basket here — items from merchant A (Galactic Core Store) and merchant B (Galactic Test Store) — with each line item naming the merchant it belongs to inmerchant_store_id. The marketplace validates the items, reserves stock per merchant, resolves
commission per merchant, and starts one payment for the whole basket. It is a server-side call on the
secret operator client.
Response
merchant_breakdown has one entry per merchant in the basket, against exactly one client_secret:
the shopper pays total_amount once on the storefront, and the marketplace splits the money.
The commission math
The operator earns a commission on each merchant’s slice — around 8% here, set by thecommission_rule_id the operator configured in their admin — and the breakdown carries it directly:
For each merchant,
gross_amount − commission_amount = net_amount (415.80 − 33.26 = 382.54), and the
group’s total_amount is the sum of the gross amounts, which is what the shopper pays in one
payment. The operator keeps the summed commission and each merchant is owed their summed net.
Stock is reserved at checkout, each merchant slice getting its own
reservation_ids, so concurrent
shoppers cannot oversell the last units. An item that cannot be held returns
400 insufficient_stock, and no order or payment is created. Marketplace-wide operator promotions
apply automatically and are not passed. A payment provider that cannot be reached returns
502 provider_error.Applying a merchant’s own discount to its slice
The optionaldiscounts array reduces one merchant’s subtotal with that merchant’s own promotion,
gift card, or both. The response then carries a non-empty discount_breakdown, an
operator_funded_discount total, and a per-merchant discount_amount, with operator-funded
promotions attributed back to the operator — which is what identifies who paid for a discount:
discounts array is keyed by merchant_store_id, and each entry’s promotion_id and
gift_card_code apply to that merchant’s portion only. In the response, discount_breakdown gains
one entry per discounted merchant, carrying merchant_discount, gift_card_amount, and the
operator_funded_discount share; discount_total is the basket-wide reduction; and that merchant’s
merchant_breakdown entry shows its discount_amount and reduced gross_amount.
The server is the price authority here, as in the single-store checkout: the request carries
identifiers, never amounts. The multi-merchant checkout recomputes every item price from the
catalog and resolves discounts itself — a
discounts entry only names a promotion_id or
gift_card_code, and the server independently computes the discount that promotion or gift card
actually grants, the operator-funded share, every gross_amount / discount_amount /
merchant_gross / commission, and the single payment total, then charges exactly that. A named
discount that does not validate — expired, ineligible, belonging to another merchant — returns
400 discount_invalid rather than being applied. Because the request carries no client-supplied
discount_amount or per-item price, a manipulated basket cannot lower what is charged or inflate a
merchant’s payout. The resolved breakdown is held server-side and used verbatim to finalize the
per-merchant child orders once payment succeeds, so nothing sent after checkout can change it.4. Fulfillment → per-merchant child orders
The shopper completes the single payment with theclient_secret from step 3. There is no fulfill
endpoint to call: fulfillment is driven internally off the payment-success event, and the observable
outcome is what an integration builds against.
- The paid order group splits into one child order per merchant, each landing in that merchant’s own
order list with its
merchant_net_amountandcommission_amount, so each merchant fulfills and ships only their own items. - The operator’s split ledger records the gross, commission, and net per merchant — the same numbers
from the
merchant_breakdown— and each merchant’s net is queued for payout to their connected Stripe account. - The group flips to
paid.
children entry maps a merchant to the online_order_id created in that merchant’s order list,
carrying the same net_amount from the checkout breakdown — 137.08 for B, the two
nets that summed to $519.62 above.
Payout depends on a connected merchant account, and the
warnings array reports the Stripe Connect
transfer state per merchant. A merchant who has not finished Stripe Connect payout onboarding —
done in the merchant’s admin, not via the API — has no connected payout account, so their net
cannot be transferred yet. Their child order is still created and the shopper is still charged;
their funds wait until they connect a payout account. An empty warnings array means every
merchant’s transfer went through.5. Unified shopper profile
Once the shopper from step 3 has bought from more than one merchant, one call returns their unified profile: identity, the merchants they have a relationship with, and their full cross-merchant order history. It takes the session token from the shopper’s sign-in asxCustomerToken, and because it
reads the shopper’s own data it runs server-side on the secret operator client.
Response
customer record at each merchant, and customer.ids lists all
of them. The stores array is the shopper’s per-merchant relationship, carrying preferred_store
and spend totals, and orders is their order history across every merchant, newest first.
Returns are per-merchant: a return belongs to the merchant whose order it is, and there is no
marketplace-wide return. A shopper lodges and tracks a return against the specific merchant order,
so the return call requires that merchant’s
storeId, and that merchant approves and processes it
in their own admin. Returning customer covers the returns flow.6. Sponsored placements and curated sections
The marketplace operator monetizes the storefront with sponsored ad slots and merchandises it with curated collections. Both are operator-key and read-only on the render side; the bookings, rate cards, and curation behind them are operator back-office, per the boundary above. The storefront reads the resolved placements and fires beacons.Filling an ad slot
A named slot — a hero banner, a category strip, search results — returns its active placements. A slot can carry sponsored placements, which are paid, markedsponsored: true, and rendered with
their disclosure_label, and curated fallback placements, which the operator hand-picks and which
are not labelled. context scopes a slot to a category or search term.
Response
placements array means the slot has no active booking, sponsored or curated, leaving the
storefront’s own organic content in its place. A live placement looks like this:
Impression and click beacons
Each rendered placement fires oneimpression beacon when it becomes visible and a click beacon
when the shopper clicks it, both carrying the placement’s booking_id. The response is
202 Accepted, with billable reporting whether the event counted toward billing after
de-duplication — informational, and not something the storefront acts on.
billable comes back false, still with recorded: true, when the beacon was de-duplicated or
filtered as invalid traffic — a repeat impression in the same session, for example. The field is
informational, and rendering does not depend on it.Curated merchandising collections
The operator’s curated sections (“Trending now”, “Featured shops”) list first, and one section’s members resolve from its slug. Curation itself is operator back-office; the storefront reads the result.Response
collections array means the operator has not curated any sections yet. Where sections
exist, each carries its slug, name, placement_kind, and homepage flags:
Response
What’s next
- Storefront checkout is the single-merchant equivalent — the same shopper journey against one store.
- Shoppers review products and message merchants; both work cross-merchant with an operator key.
- Catalog sync brings merchant catalogs into the marketplace.

