//Installing a Marketplace App

Installing a Marketplace App

This tutorial covers finding an app in the marketplace, installing it into your org, polling until it is active, and accessing the provisioned endpoint.

Prerequisites

  • An authenticated ButtrBase session with an active org
  • Org admin rights (required to initiate an install)

---

Step 1 — Browse the Marketplace

~~~http GET /api/marketplace Authorization: Bearer ~~~

Or search by name:

~~~http GET /api/marketplace?q=datasync ~~~

Find the slug of the app you want to install (e.g. datasync-pro).

---

Step 2 — View App Details

~~~http GET /api/marketplace/datasync-pro ~~~

Check the available deployment_modes, pricing_model, and base_price_cents before committing.

---

Step 3 — Install

~~~http POST /api/marketplace/datasync-pro/install Authorization: Bearer Content-Type: application/json

{ "deployment_mode": "single_tenant", "plan_id": "pro", "quantity": 1 } ~~~

~~~jsonc // 202 Accepted { "install_id": "inst_01def...", "status": "provisioning" } ~~~

ButtrBase immediately calls the publisher's provision webhook. The install is active once the publisher's webhook responds with an endpoint URL.

---

Step 4 — Poll Until Active

~~~typescript async function waitForInstall(installId: string, token: string) { for (let i = 0; i < 20; i++) { const res = await fetch(/api/installs/${installId}, { headers: { Authorization: Bearer ${token} }, }); const install = await res.json();

if (install.status === 'active') return install; if (install.status === 'provisioning_failed') throw new Error('Provisioning failed');

await new Promise(r => setTimeout(r, 3000)); } throw new Error('Timed out waiting for install'); }

const install = await waitForInstall(installId, token); console.log('Ready at:', install.endpoint_url); ~~~

---

Step 5 — Access the Install

Once active, the install record contains the endpoint_url of your running instance:

~~~jsonc { "install_id": "inst_01def...", "app": { "name": "DataSync Pro", "slug": "datasync-pro" }, "status": "active", "endpoint_url": "https://acme.datasync.example", "deployment_mode": "single_tenant", "payment_source": "direct", "current_period_end": "2026-06-17T00:00:00Z" } ~~~

Direct your users to endpoint_url. The app knows which org it is serving because ButtrBase issued scoped credentials during provisioning.

---

Checking Access from the App's Frontend

After navigating to the app, its frontend can call:

~~~http GET /api/marketplace/apps/:app_id/access Authorization: Bearer ~~~

To confirm the install is active and whether the current user has admin rights within the app's own context:

~~~jsonc { "is_app_admin": false, "is_org_owner": true, "install_status": "active", "install_id": "inst_01def..." } ~~~

---

Deprovisioning

To cancel and remove the install:

~~~http DELETE /api/installs/inst_01def... Authorization: Bearer ~~~

Status transitions to deprovisioning, then deprovisioned once the publisher tears down the tenant. Billing stops at the end of the current period.