Skip to content

Monetization

Sell products in your app: one-time purchases or subscriptions. Payments, checkout, and subscription management run on Bazaar, so your app needs no payment backend.

To sell, the seller needs a plan that allows monetization (Creator for users, Business for orgs) and a payout account. Payout accounts are currently for sellers based in the US; the seller picks the country once, when setting it up. Set both up under Monetization in the dashboard, or open the same page in a popup:

bzr.monetization.openPopup();

Check whether the logged-in user can sell and get paid:

const { canMonetize, paymentsEnabled } = await bzr.monetization.status();

Bazaar charges the buyer and collects and pays the VAT or sales tax due in their country, so prices include it. Of the rest, Bazaar keeps 10% + $0.30, the app’s owner gets the app’s fee (set in the dashboard, at most 5%), and the seller the remainder. A $10.00 sale to a buyer in Germany (19% VAT) in an app with a 5% fee: $1.60 VAT, $1.14 to Bazaar, $0.42 to the app, $6.84 to the seller.

Each payment is paid out 90 days after it’s made, once what’s due to a seller reaches $25. Sellers and app owners see each month’s payments, tax, fees and their share under Monetization in the dashboard.

import { ProductRepeatInterval } from "@bzr/bazaar";
const product = await bzr.monetization.products.create({
name: "Supporter",
description: "Access to all posts",
costInCents: 500,
repeatInterval: ProductRepeatInterval.MONTH,
group: "membership",
});
  • costInCents: at least 100, in cents of the product’s currency (US dollars for now; products carry a currency field). It’s what the buyer pays, VAT or sales tax included.
  • repeatInterval: NEVER for a one-time purchase, or DAY, WEEK, MONTH, YEAR for a subscription.
  • group: optional. A subscriber can switch between subscriptions in the same group, e.g. tiers.

To sell as an org you administer, pass its ID:

await bzr.monetization.products.create(product, { sellerId: "example-org-id" });
// Your products
const products = await bzr.monetization.products.list();
// Another seller's products, optionally by group
const tiers = await bzr.monetization.products.list({
sellerId: "seller-id",
group: "membership",
});
// Only name and description can change, not the price
await bzr.monetization.products.update(product.id, { name: "Fan" });
await bzr.monetization.products.delete(product.id);

Open a popup where the user buys a product:

bzr.monetization.purchases.openPopup({ productId: product.id }, () => {
// popup closed: refresh purchases
});

Let the user pick a product from a seller’s group, or change or cancel an existing purchase:

bzr.monetization.purchases.openPopup({
sellerId: "seller-id",
group: "membership",
});
bzr.monetization.purchases.openPopup({ purchaseId: "example-purchase-id" });

purchases.make(productId, onClose) and purchases.manage(purchaseId, onClose) are short for the productId and purchaseId forms.

List the logged-in user’s purchases in this app:

import { PurchaseType } from "@bzr/bazaar";
const purchases = await bzr.monetization.purchases.list();
const subscriptions = await bzr.monetization.purchases.list({
type: PurchaseType.SUBSCRIPTION,
});

A purchase has a status, e.g. active, trialing, past_due, canceled, or refunded. Subscriptions also have nextInvoice and canceled.

List purchases of your products, with buyers:

const sales = await bzr.monetization.sales.list({ group: "membership" });
// An org's sales
const orgSales = await bzr.monetization.sales.list({
sellerId: "example-org-id",
});

Use the reserved value "$purchases" in a permission filter to give buyers access to data. It resolves to the IDs of the products the user has an active purchase of in this app:

import { GranteeType, PermissionType } from "@bzr/bazaar";
// Each post lists the product IDs that unlock it, e.g. { tiers: ["product-id"] }
await bzr.permissions.create({
collectionName: "posts",
granteeType: GranteeType.ANY,
types: [PermissionType.READ],
filter: { tiers: { $containsAny: "$purchases" } },
});

Buyers then read the seller’s collection through a context:

const seller = await bzr.createContext({ ownerId: "seller-id" });
const posts = await seller.collection("posts").getAll();

Access ends when the purchase is no longer active, e.g. a canceled subscription.