Open app
Moonborn — Developers

Marketplace publishing

Submit a persona to the Moonborn marketplace, pass moderation, and let others install or fork your listing.

The marketplace is the cross-org distribution channel: you publish a persona, it goes through moderation, downstream users install or fork it. This tutorial covers the publisher side.

1. Prepare the persona

Before submission, run a manual audit and check the distinctiveness score. Listings that fail audit get auto-rejected by the moderation queue.

const audit = await client.personas.runAudit({ id: persona.id });
if (audit.overallScore < 4.0) {
  console.log('Refine the persona before publishing — audit too low.');
}

2. Submit the listing

const listing = await client.marketplace.publishListing({
  personaId: persona.id,
  license: 'CC-BY-4.0',
  priceCents: 0,
  description:
    'A character-consistent customer-support persona tuned for SaaS onboarding.',
});
 
console.log(listing.status); // "in_review"

License options: CC-BY-4.0, CC-BY-SA-4.0, CC0-1.0, plus a Moonborn-specific commercial-use license for paid listings. The license affects what forks are permitted (ShareAlike means downstream forks must keep the same license).

3. Wait for moderation

Every new listing enters in_review. The default policy gates through human review; the SLA target is marketplace.moderation.review_sla_hours (default 48 hours).

Three outcomes:

  • published — the listing is live, downstream installs/forks unlocked.
  • unpublished — rejected; the listing returns a verdict reason and a remediation hint.
  • in_review — held for deeper review (typically when the auto-policy flagged something a human needs to confirm).

Subscribe to marketplace.listing.published and marketplace.listing.unpublished webhook events if you want to wire the outcome into your own product.

4. Manage the listing

Once published, you can update metadata without re-submitting:

await client.marketplace.updateListing({
  id: listing.id,
  description: 'Updated: now handles billing escalations cleanly.',
});

To unpublish manually:

await client.marketplace.unpublishListing({ id: listing.id });

Listings remain in the lineage tree even when unpublished — downstream forks aren't broken, but the listing stops appearing in /v1/marketplace/listings.

5. Read installs and forks

const detail = await client.marketplace.getListing({ id: listing.id });
console.log(detail.downloads, detail.forks, detail.ratingsAvg);

Every install bumps downloads. Every fork bumps forks and writes a lineage edge with attribution back to your listing (see Lineage + fork tree).

6. Commerce (Enterprise)

Paid listings require marketplace.commerce.enabled (Enterprise tier-gate) and a creator Stripe Connect account. Revenue split is marketplace.commerce.revenue_share (default 0.7 — 70% creator, 30% platform).

const creator = await client.marketplace.onboardCreator();
console.log(creator.stripeOnboardingUrl);
// Send the user there to complete Stripe Connect onboarding.

Payouts trip when the creator's pending balance crosses marketplace.commerce.payout_min_usd (default $50). An hourly reconciliation cron audits usage_events against Stripe records.

Honest scope

Marketplace ships persona templates. It does not ship chat history, memory state, or workspace-scoped configuration. Each installation runs against the installer's own workspace.

Next