These are the terms the rest of the guide uses.

A platform is the external backend or POS a seller connects through. A seller is the marketplace participant whose listings Snapcaster hosts. One platform can connect multiple sellers. A subscription is the event family a platform receives: orders, inventory, or both. Each seller connects to one platform, so the platform’s subscription applies to every seller on it. A company whose sellers need different subscriptions registers one platform for each subscription.

The canonical catalog is Snapcaster’s master TCGplayer product and SKU reference. A product is one card printing, and a SKU is its exact condition, language, and finish variant. The catalog supplies the descriptive name, set, condition, language, finish, and image for buyer browse.

A listing is one seller’s offer for one canonical SKU. It has the price, the on-hand quantity, and an optional externalRef that Snapcaster returns unchanged, so you can match the listing to your own records.

A matched listing has a skuId in the canonical catalog. Snapcaster stores an unmatched listing, but buyers cannot browse it until its SKU exists in the catalog. GET /me counts matched and unmatched listings separately, and GET /listings explains each listing’s status.

The catalog, not your request, sets a listing’s product. For a matched SKU, productId is optional. A productId that names a different product than the catalog holds for the skuId is rejected with PRODUCT_MISMATCH and stores nothing for it. An unmatched SKU still needs productId. When the catalog later gains the SKU, the listing takes the catalog’s product.

On-hand is the physical stock quantity the seller’s inventory source reports. For a platform-source seller, your platform owns and pushes this number.

Committed is stock sold through Snapcaster that the platform’s latest eligible on-hand snapshot has not yet accounted for. Snapcaster owns this number and uses it to prevent overselling between the sale and your next push.

Available is what a buyer can purchase. At checkout, Snapcaster calculates it as On-hand - Committed - Reservation. Browse shows On-hand - Committed. Always send on-hand, not available.

EventYour on-handUnits committedUnits available in browse
You push 4404
A buyer purchases 1413
You push 3 after reflecting the sale303

The push in the last row releases the hold only when the steps in Release the hold on sold units happen in order.

Every listing write is a snapshot of the stock your system measured at one instant. Send that instant as asOf, a UTC timestamp with at most millisecond precision. Each item of POST /listings and POST /listings/bulk carries its own asOf.

DELETE /listings takes { skuIds, asOf }, and a request without asOf returns HTTP 400 INVALID_REQUEST. POST /listings/purge takes { asOf }.

Snapcaster evaluates batch items in request order, so a SKU repeated in one batch goes through the same freshness checks each time. A newer snapshot advances the SKU’s watermark even if its quantities are unchanged. A snapshot with the same timestamp returns noop if its contents are identical, and SNAPSHOT_CONFLICT if they differ. An older snapshot returns STALE_SNAPSHOT. These are per-item results, so check every result even when the batch response succeeds. Sync a full catalog shows which asOf to send for a file or export, and how to retry a write whose response was lost.

A deletion keeps its watermark after the listing is gone, and also covers SKUs that were never stored. A purge removes snapshots at or before its instant and keeps newer ones. It covers the whole seller, so no snapshot at or before the purge can recreate a listing, even one that arrives late. A purge older than an earlier purge returns HTTP 409 STALE_SNAPSHOT.

Buyers find a listing only when both of these hold:

  • The seller is browse-eligible, which GET /me reports as readiness.browseEligible: true once readiness.incompletePrerequisites is empty.
  • The listing is browsable, which means it is matched and active, it has a positive available quantity, and its seller is browse-eligible. GET /me counts these listings in counts.browsable, and GET /listings marks each one with browsable.

A browse-eligible seller with no browsable listing shows buyers nothing, so read counts.browsable after a push. It is 0 while the seller is suspended, on vacation, or not browse-eligible. counts.browsable counts a listing at once, and buyers see it in browse a few seconds later.

Each open requirement in incompletePrerequisites carries a code, a message, and an action, which is the request or email that closes it.

codeWhat it meansWho closes it
SELLER_ACTIVESnapcaster suspended the sellerSnapcaster, after the seller emails it through the action’s mailto: link
VACATION_DISABLEDThe seller is on vacationYour platform, with PATCH /me and {"vacation": false}
SHIPPING_OPTION_CONFIGUREDThe seller has no shipping optionThe seller
CONNECTED_ACCOUNT_CANADIANThe seller has no Canadian Stripe connected accountThe seller, in Stripe Connect onboarding
PAYOUTS_READYStripe cannot pay the seller out yetThe seller, in Stripe Connect onboarding
CURRENT_SELLER_TERMS_ACCEPTEDThe seller has not accepted the current Seller TermsThe seller
TAX_PROFILE_COMPLETEThe seller’s Canadian tax profile is incompleteThe seller
CANADIAN_SHIPMENT_ORIGIN_CONFIRMEDThe seller has not confirmed that it ships from CanadaThe seller
BILLING_AGENT_ELECTION_REQUIREDA GST/HST-registered seller has not accepted the current billing-agent electionThe seller
AUTHENTICATOR_ENROLLEDThe seller has no authenticator app for two-factor authenticationThe seller
AUTHENTICATOR_RECOVERY_VERIFIEDThe seller recovered its authenticator, and Snapcaster has not verified the recoverySnapcaster, after the seller emails it through the action’s mailto: link
OPERATOR_REVIEW_APPROVEDSnapcaster has not finished its review of the sellerSnapcaster, and the entry’s review.status says where the review stands
REPORTING_IDENTITY_REQUIREDCRA reporting rules need the seller’s reporting identity before more sales this yearThe seller
SHOP_LINK_ACTIVEApplies only to a seller that sells through a Shopify shop link, never to a platform’s sellerNot your platform
BILLING_TERMS_ACCEPTEDApplies only to a seller that sells through a Shopify shop link, never to a platform’s sellerNot your platform

Your platform closes only VACATION_DISABLED, with the marketplace API key, in production and in the sandbox. PATCH /me sets vacation to the value you send, so if the response is lost, send the same body again. Every other /api/ action is an account API request made with the seller’s Snapcaster login, and a mailto: action is an email to Snapcaster. In production the seller closes those in its Snapcaster dashboard. The sandbox has no dashboard, so the sandbox seller closes them with the requests in Finish sandbox seller setup through the account API.

The browse operations are informational, and your platform does not implement them.

STABLE fields have a fixed shape you can build against. A STABLE field can still be optional when it does not apply.

PROVISIONAL fields may change shape or be absent. Your parser must handle both cases.

Ignore unknown fields and event types, so additions to the API do not break your integration. Requests you send use camelCase, such as skuId and externalRef, and webhooks Snapcaster sends use snake_case, such as sku_id and external_ref. There are two exceptions. An address you send, such as shippingAddress on POST /orders/{orderId}/corrections, uses the same keys as the addresses Snapcaster sends, so its postal code is postal_code. The GET /listings query parameters updated_since and include_deleted are snake_case.

Need help?

Email Marketplace support.

The email includes this page and selects sandbox as the environment. Update it if you need help with production.

Never include an API key or signing secret in the message.