Private or Marketplace

manifest.type — the one-customer custom app versus an app any tenant can install, what each implies, and why it is independent of pricing.

manifest.type decides who may ever install your app. It is required, and it is the field that distinguishes a custom app built for one customer from a Marketplace app.

manifest.json
"type": "private"
ValueWho may installListed in the Marketplace
privateOnly the owner tenantNever
publicAny tenant, once the operator publishes itYes

private — the custom app

Only the owner tenant may install and invoke the app, and it is never listed in the Marketplace. This is the right value for anything built for a single customer.

It is the type most partner work starts as, and there is nothing second-class about it. A private app is a full app: its own tables, its own capabilities on the public gateway, its own Cockpit screens, its own schedules. The only difference is reach.

What being private means in practice:

  • Your customer's data model is yours to shape. You are not designing for every merchant on the platform, so you can encode this business's rules directly.
  • You still write a real contract. The capabilities you publish become that tenant's API, their generated SDK methods, and their API Explorer entries. Their own integrations read your summary fields.
  • You still need a billing.json. For a private app it is mostly a formality — type: "free" and move on. See Billing.
  • The consent screen still applies. One customer is still a human reading your access register and clicking install. See Consent.

public — the Marketplace app

Once the operator publishes it, any tenant may install and invoke it, and it appears in the Marketplace.

Going public changes what you have to think about, in ways that are easier to design for from the start than to retrofit:

You do not know the data. Row counts, label lengths, null columns, locales, currencies: all of it varies. A list that renders beautifully for your first customer is the screen every other merchant judges you by.

You cannot assume which apps are installed. A capability you call must be declared as both a grant and a dependency, and a market-scoped setting needs the markets app to actually be there.

Configuration replaces assumptions. Every business rule you hardcoded for one customer becomes a setting or a vocabulary — or a decision you make for everybody and defend.

The listing is the product. billing.json's listing block is what a merchant reads before they trust you: the description, the highlights, the features, and the reason for every permission you ask for.

Versioning discipline stops being optional. With one customer you can coordinate a change. With fifty you cannot, so a breaking change is a new capability key on a new route and both serve traffic until callers move. See Versioning.

Support is a field in a file. billing.json's support block is where a merchant's operator looks when something breaks at 4 p.m.

It is independent of pricing

type declares reach. billing.json declares pricing. They are orthogonal, and the four combinations are all legitimate:

type: privatetype: public
billing.type: freeA custom app for one customer — the common caseA free Marketplace app
billing.type: paidA custom app billed through the platformA paid Marketplace app with plans
billing.type: includedRareHow the platform's own commerce apps reach tenants

A public app can be free, and a private app still needs a billing.json. Neither file can be inferred from the other.

Choosing, and changing your mind

Start private when you are building for a named customer, which is nearly always. It is the smaller promise: nobody else can install it, so nobody else's data can surprise you and nobody else's expectations are yours to meet.

Going from private to public later is a field edit, but it is not a small change in substance — it is the moment all of the assumptions above become load-bearing. Before you flip it:

  • Read your schema.json for anything specific to one customer's business.
  • Read your handlers for hardcoded codes, thresholds and locales.
  • Fill in the listing block properly, including a reason for every permission.
  • Test against a tenant that is not the one you built it for.

Going from public back to private does not un-install it from the tenants who already have it. Treat publishing as the one-way door it effectively is.

Next steps

Was this page helpful?