Marketplace
The marketplace is where your finished product is discovered and subscribed to. As a builder you publish a listing for your package, describe and categorize it, gather reviews from the orgs that use it, and rely on a set of public, cached endpoints to bootstrap your client apps before anyone signs in. This page covers how to create and manage a listing, how reviews and subscriptions work, and the public discovery surface that powers your storefront.
Pro The marketplace is part of the SaaS Builder, included with the Backbuild Pro build-and-ship platform. See pricing.
Two halves: public browse and managed listings
The marketplace has a deliberately split surface. One half is public and unauthenticated: the browse, plan, and bootstrap endpoints that prospects and running clients hit before they have a session. The other half is the authenticated management surface where you, the builder, create and edit your listing, and where subscribers post reviews and start subscriptions.
| Surface | Auth | Used by |
|---|---|---|
Browse & discovery (GET /v1/marketplace/listings, /packages, /plans) | None (rate-limited per IP) | Prospects, marketing pages, plan pickers |
Client bootstrap (GET /v1/marketplace/app-config, /build-config, /resolve-domain) | None (cached) | Your running apps before login |
Listing management (POST/PATCH/DELETE /v1/marketplace/listings) | Required + permission | You, the builder |
| Reviews & subscriptions | Required + permission | Subscribing organizations |
Because the public half is open to anyone, it is rate-limited per client IP and validates every query parameter strictly; unknown parameters are rejected. You do not need to do anything special to benefit from this; it is on by default for the discovery surface.
Creating a listing
A listing is the public-facing entry for your product on the marketplace. It
points at a template you own and carries the marketing metadata a shopper
sees: title, description, category, tags, pricing summary, and screenshots.
Create one with a POST; the listing is created under your
organization and starts in a non-public state until you publish it.
POST /v1/marketplace/listings
Authorization: Bearer <token>
Content-Type: application/json
{
"template_id": "019d3f6a-...-...",
"title": "Acme Field Service",
"description": "Scheduling, dispatch, and invoicing for field teams.",
"category": "operations",
"tags": ["scheduling", "dispatch", "invoicing"],
"pricing_type": "subscription",
"price_cents": 4900,
"currency": "USD",
"screenshots": [
{ "url": "https://cdn.example.com/shots/dashboard.png", "alt": "Dashboard" },
{ "url": "https://cdn.example.com/shots/dispatch.png", "alt": "Dispatch board" }
]
}
# Response (201)
{ "success": true, "data": { "...listing..." } } | Field | Required | Notes |
|---|---|---|
template_id | yes | The template this listing publishes. Must be one your org owns. |
title | yes | Display title, 1–500 characters. |
description | no | Long-form description, up to 10,000 characters. |
category | no | A category key for filtering and grouping (up to 100 chars). |
tags | no | Up to 50 free-form tags used for search and discovery. |
pricing_type | no | One of free, one_time, or subscription. |
price_cents | no | Headline price in the smallest currency unit (cents). |
currency | no | Three-letter ISO currency code, e.g. USD. |
screenshots | no | Up to 50 screenshot entries shown in the listing gallery. |
The headline pricing_type and price_cents are the
summary a shopper sees on the listing card. The full set of purchasable tiers
comes from your pricing plans,
served separately through the public plans endpoint described below.
Listing status and publishing
A listing moves through a lifecycle: draft while you prepare it,
pending_review once submitted, published when it is
live and discoverable, and suspended if it is taken down. You
move the listing forward by updating its status on the
PATCH endpoint.
PATCH /v1/marketplace/listings/<listingId>
Content-Type: application/json
{
"description": "Updated copy with the new dispatch features.",
"tags": ["scheduling", "dispatch", "invoicing", "routing"],
"status": "published"
} Only published listings appear on the public browse surface. Updates take only the fields you want to change; at least one field is required.
Managing your own listings
To see your listings, including drafts and unpublished ones, use the management list. The public browse endpoint only ever returns published listings; the management endpoint defaults to showing all of your own listings across every status so you can find your drafts.
# Your listings (all statuses by default)
GET /v1/marketplace/listings/manage?status=draft&page=1&page_size=50
# Narrow to published only
GET /v1/marketplace/listings/manage?mine_only=false To inspect a single listing by ID, supply the publisher organization it belongs to:
GET /v1/marketplace/listings/<listingId>?publisher_org_id=<yourOrgId> Descriptions, screenshots, and categories
The descriptive metadata on a listing is what makes it findable and convincing. A few practical notes:
- Description is long-form copy (up to 10,000 characters). Use it for the value proposition, key features, and who the product is for.
- Screenshots populate the listing gallery. Each entry is a hosted image you point at by URL; provide a handful of representative views of the product in use.
- Category places the listing in a single bucket used by the browse filter, while tags are a broader set of keywords that also feed search. A shopper can filter the browse list by category and sort the results.
The public browse endpoint accepts a free-text search, a
category filter, and a sort of rating,
newest, or downloads, so choosing accurate
categories and tags directly affects where your product shows up.
# Public browse: published listings only
GET /v1/marketplace/listings?search=field+service&category=operations&sort=rating Reviews
Organizations that use a product can leave a review: a 1-to-5 rating and optional text. Reviews are a discovery signal: the browse endpoint can sort by rating, so accumulated reviews influence your placement. A review is posted against a specific listing and its publisher organization.
POST /v1/marketplace/reviews
Content-Type: application/json
{
"listing_id": "019d5c02-...-...",
"publisher_org_id": "019d3f6a-...-...",
"rating": 5,
"review_text": "Cut our dispatch time in half."
} As a builder you can list the reviews relevant to your organization, with an optional filter to a single listing:
GET /v1/marketplace/reviews?listing_id=<listingId>&page=1&page_size=50 Subscriptions
A marketplace subscription records that one organization has subscribed to a published listing. This is the lightweight marketplace-level subscription used for listing discovery and access, distinct from the metered, Stripe-backed plan subscriptions your tenants hold (covered under Tenants & Subscriptions and Payments).
POST /v1/marketplace/subscriptions
Content-Type: application/json
{
"listing_id": "019d5c02-...-...",
"expires_at": "2027-01-01T00:00:00Z"
}
The subscribing organization is taken from the authenticated session, so a
subscriber cannot subscribe on another org’s behalf. You normally omit
publisher_org_id; if you do send it, it must match the
listing’s real publisher or the request is rejected, so a subscriber
can never spoof who the listing belongs to. Cancel a subscription with its ID:
DELETE /v1/marketplace/subscriptions/<subscriptionId> Public bootstrap endpoints
Before a visitor signs in, your client app still needs to know which product
it is, how to brand itself, and which plans to offer. A set of public,
unauthenticated, cached endpoints under /v1/marketplace provides
exactly that. They are safe to call on every page load and are designed for
fast first paint.
| Endpoint | What it returns |
|---|---|
GET /v1/marketplace/resolve-domain | Resolves a custom domain to the owning organization and package, so the client knows which product it is serving. |
GET /v1/marketplace/app-config | The full application configuration (branding and presentation) for a domain or package, for pre-auth rendering. |
GET /v1/marketplace/build-config | Platform-specific build configuration for a domain and platform: the settings a built client reads. |
GET /v1/marketplace/plans | The published pricing plans for a package, for the signup plan picker. |
GET /v1/marketplace/addons | Add-ons applicable to a chosen main plan. |
GET /v1/marketplace/packages | Published packages: the general browse list, or the curated signup roll-up. |
A typical client boot sequence fans out across several of these on the first page load: resolve the domain, pull the app-config to brand the page, then load plans for the signup picker.
# 1. Which product is this domain?
GET /v1/marketplace/resolve-domain?domain=app.yourproduct.com
# 2. Brand and configure the pre-auth UI
GET /v1/marketplace/app-config?domain=app.yourproduct.com
# 3. Plans to show on signup
GET /v1/marketplace/plans?saas_package_id=<packageId>&visibility=signup&page_size=100 Resolving a domain
Your apps are served from your own custom
domains. The resolve endpoint maps a domain to the org and package behind
it, so a generic client binary can figure out which product configuration to
load. It returns 404 if the domain is not mapped.
GET /v1/marketplace/resolve-domain?domain=app.yourproduct.com
# (legacy alias: GET /v1/marketplace/resolve?domain=...) App configuration
The app-config endpoint returns the full configuration used to render your
product’s shell before login: theme, branding, and presentation.
Supply either a domain or a package_id. The public
variant is cached and serves the branding an anonymous visitor sees.
GET /v1/marketplace/app-config?domain=app.yourproduct.com
GET /v1/marketplace/app-config?package_id=<packageId>
Two variants are tenant-internal and therefore require an authenticated token
whose organization matches the request: passing a
subscriber_org_id (the per-tenant configuration) or
draft=true (the pre-release configuration of a staged change).
The plain public branding view needs neither and stays open.
Build configuration
The build-config endpoint hands a running client its platform-specific
settings. Both domain and platform are required;
platform is one of ios, android,
windows, macos, linux, or
web. See App
Configurations & Builds for how these settings are produced.
GET /v1/marketplace/build-config?domain=app.yourproduct.com&platform=ios Plans for signup
The plans endpoint serves the published, read-only pricing tiers a shopper
picks from at signup. Pass the saas_package_id (either the
package UUID or its package slug) and optionally
visibility=signup to get only the curated signup set rather than
your full catalog. The response carries the plans plus any promotions and
grouping configuration, so the picker can render exactly as you intend.
# All published plans for a package (UUID or slug)
GET /v1/marketplace/plans?saas_package_id=<packageId>
# Curated signup set, full page of results
GET /v1/marketplace/plans?saas_package_id=acme-field-service&visibility=signup&page_size=100 Curation is advertising-only: the signup set narrows what is shown on the public picker, but your full catalog remains available for in-app upgrades. Add-ons (such as extra credit or storage) are picked after a main plan and come from the separate add-ons endpoint, which requires the package UUID.
GET /v1/marketplace/addons?saas_package_id=<packageId>&plan_slug=business-gold Packages roll-up
To surface multiple of your packages on a single signup page, where a shopper
first picks a product and then a plan within it, use the packages endpoint
in signup mode with either your org_id or a domain.
Without visibility=signup, the same endpoint returns a general
published-package browse list with optional search and
sort.
# Curated multi-package signup roll-up
GET /v1/marketplace/packages?visibility=signup&org_id=<yourOrgId>
# General published browse
GET /v1/marketplace/packages?search=field&sort=newest Caching and rate limits
The public discovery and bootstrap endpoints set cache headers so they can be served fast and called on every load. Browse and plan responses carry a short public cache; app-config and build-config are cached longer. When you update your listing, plans, or branding, the cached configuration refreshes for the domains pointing at your package. The public surface is also rate-limited per client IP to keep enumeration and abuse in check; legitimate browsing, which fans out across several of these endpoints per page, sits comfortably inside the limit.
Permissions
Listing writes are permission-gated within your organization: creating,
updating, and deleting a listing each require the corresponding marketplace
permission, posting a review requires the review permission, and subscribing
or cancelling requires the subscribe permission. Every write is scoped to your
organization and audit-logged with the acting user. A caller without the right
permission receives a 403; an unknown listing or subscription
returns a 404; a subscriber that supplies a mismatched publisher
is rejected as a client error.
API reference
Public: browse & discovery (no auth)
| Method & path | Description |
|---|---|
GET /v1/marketplace/listings | Browse published listings. Optional search, category, sort (rating, newest, downloads). |
GET /v1/marketplace/packages | List published packages. search + sort (newest, name); or visibility=signup with org_id or domain for the signup roll-up. |
GET /v1/marketplace/plans | Published pricing plans. saas_package_id (UUID or slug), visibility (all, signup), page, page_size (max 100). |
GET /v1/marketplace/addons | Add-ons for a chosen plan. saas_package_id (required), optional plan_slug, page, page_size. |
GET /v1/marketplace/resolve-domain | Resolve a custom domain to org + package. Legacy alias: GET /v1/marketplace/resolve. |
GET /v1/marketplace/app-config | App configuration for a domain or package_id. subscriber_org_id / draft=true variants require a matching auth token. |
GET /v1/marketplace/build-config | Build configuration. domain + platform required. |
GET /v1/marketplace/build-targets | Active build targets. Optional domain, platform, org_id, environment. |
Authenticated: listing management
| Method & path | Description |
|---|---|
POST /v1/marketplace/listings | Create a listing. Body: template_id, title, optional description, category, tags, pricing_type, price_cents, currency, screenshots. Responds 201. |
GET /v1/marketplace/listings/manage | List your org’s own listings (all statuses by default). Optional mine_only, page, page_size, search, category, status, pricing_type. |
GET /v1/marketplace/listings/:id | Get one listing. Requires publisher_org_id. |
PATCH /v1/marketplace/listings/:id | Update a listing (any subset of the create fields plus status). |
DELETE /v1/marketplace/listings/:id | Delete a listing. |
Authenticated: reviews & subscriptions
| Method & path | Description |
|---|---|
POST /v1/marketplace/reviews | Create a review. Body: listing_id, publisher_org_id, rating (1–5), optional review_text. Responds 201. |
GET /v1/marketplace/reviews | List reviews for your org. Optional listing_id, page, page_size. |
POST /v1/marketplace/subscriptions | Subscribe to a published listing. Body: listing_id, optional publisher_org_id (must match if sent), expires_at. Responds 201. |
DELETE /v1/marketplace/subscriptions/:id | Cancel a marketplace subscription. |
Related: SaaS Packages (publishing a package), Pricing Plans (the tiers served on the plans endpoint), App Configurations & Builds (what app-config and build-config deliver), and Store & App Distribution (publishing native builds to the app stores). Full request/response schemas are in the API Reference.
Frequently asked questions
- How do prospects discover my product?
- Through public browse of published listings, with search, category, and sorting by rating, newest, or downloads. Only published listings appear publicly.
- Do reviews affect where my product ranks?
- Customers can leave a rating and text review, and reviews inform how listings sort in discovery.
- Is a marketplace listing the same as my pricing plans?
- No. A marketplace listing is discovery-level. The plans customers actually subscribe to and pay for are defined separately. See Pricing Plans.
- Does a listing show up before I publish it?
- No. A listing moves through draft and review states and appears publicly only once published.