//Marketplace Integration Guide

Marketplace Integration Guide

This guide covers the full picture of how apps, installs, admin roles, and cloud marketplace connectors fit together in ButtrBase.

Architecture Overview

~~~ Publisher org └── marketplace_app (draft → published) ├── deployment_modes: [multi_tenant, single_tenant, ...] ├── provision_webhook: https://... ├── marketplace_listings: [aws, azure, gcp] └── app_admin_grants: [user_a, user_b]

Buyer org └── app_install ├── status: provisioning → active ├── payment_source: direct | aws_marketplace | ... └── app_deployment └── endpoint_url: https://... ~~~

---

Admin Tiers

Three distinct admin levels govern the platform:

Platform admin — credential-based, governs the ButtrBase instance. Approves app publications, manages vendor config, has cross-org visibility. JWT claim: platform_admin: true.

App admin — RBAC grant scoped to one app, held by users in the publisher org. Manages installs, webhook, listings, and delegates to teammates. JWT claim: app_admin: ["app_uuid", ...].

Org admin — existing role, governs a buyer org's installs and users.

---

Install Lifecycle

~~~ POST /api/marketplace/:slug/install │ ▼ status: provisioning │ ▼ (ButtrBase calls provision webhook) Publisher provisions tenant │ ▼ (publisher responds { endpoint_url }) status: active │ [ payment_failed ] → status: suspended │ [ DELETE /api/installs/:id ] → status: deprovisioning → deprovisioned ~~~

---

Payment Sources

| Source | Who bills the buyer | What ButtrBase does | |--------|-------------------|---------------------| | direct | ButtrBase billing | Normal subscription lifecycle | | aws_marketplace | AWS | Resolves entitlement via AWS API, meters usage | | azure_marketplace | Azure | SaaS Fulfillment API v2 token exchange + activation | | gcp_marketplace | GCP | Cloud Procurement API entitlement approval |

For marketplace sources, ButtrBase receives inbound webhook events from the cloud vendor and maps them onto the install lifecycle. Your provision webhook receives the same events regardless of payment source.

---

Provision Webhook Events

| Event | Trigger | Expected response | |-------|---------|-------------------| | install.provisioning | New install | { endpoint_url } | | install.suspended | Payment failure or manual suspend | 200 | | install.resumed | Payment recovered or manual resume | 200 | | install.deprovisioning | Buyer cancels or is deprovisioned | 200 | | install.plan_changed | Buyer upgrades or downgrades plan | { endpoint_url } (if changed) |

All events are signed with X-ButtrBase-Signature: sha256= using your webhook_secret. Always verify the signature before processing.

---

Cloud Marketplace Setup

AWS

1. Register your SaaS product in AWS Partner Central 2. Configure the SNS subscription topic ARN via PUT /api/platform/config/aws-marketplace 3. Add a listing: POST /api/marketplace/apps/:id/listings with "marketplace": "aws" 4. When a buyer subscribes on AWS, ButtrBase receives the SNS notification, resolves the entitlement, and creates an install with payment_source: aws_marketplace

Azure

1. Create a SaaS offer in Azure Partner Center and register your landing page URL 2. Configure the fulfillment API key via PUT /api/platform/config/azure-marketplace 3. Azure sends the buyer to your landing page with a marketplace_token 4. ButtrBase exchanges the token, activates the subscription, and creates the install

GCP

1. Create a SaaS solution in GCP Marketplace Producer Portal 2. Configure the Pub/Sub subscription via PUT /api/platform/config/gcp-marketplace 3. GCP publishes entitlement events to the subscription; ButtrBase processes them and creates or updates installs accordingly

---

Role Check Quick Reference

~~~typescript // After login — fetch once and cache const me = await fetch('/api/auth/me', { headers: { Authorization: Bearer ${token} } }).then(r => r.json());

me.platform_admin // boolean me.app_admin.includes(appId) // boolean — is this user an app admin? me.entitlements // string[] — active feature slugs me.roles // string[] — org roles

// Per-request role gate (backend) const claims = await bb.verifyToken(bearer); // local, no network const check = await bb.checkEntitlement(bearer, 'feature_slug'); // remote const access = await bb.checkAppAccess(bearer, appId); // remote ~~~

---

Further Reading