Billing & Monetization

Billing SDK Reference

Complete reference for all App Bridge billing methods. Query plans, manage subscriptions, and handle errors from inside your plugin.

Setup

All billing methods are available through the App Bridge hook:

import { useAppBridge } from "@whatalo/plugin-sdk/bridge";

function MyComponent() {
  const bridge = useAppBridge();
  // bridge.billing.*
}

Methods

bridge.billing.getPlans()

Returns all active pricing plans for your plugin.

getPlans(): Promise<BillingPlanResponse[]>

Returns: Array of BillingPlanResponse objects. Returns an empty array if no active plans exist.

const plans = await bridge.billing.getPlans();

for (const plan of plans) {
  console.log(plan.slug);       // "pro"
  console.log(plan.name);       // "Pro"
  console.log(plan.price);      // 29.99
  console.log(plan.currency);   // "USD"
  console.log(plan.interval);   // "monthly" | "annual" | null
  console.log(plan.trialDays);  // 14
  console.log(plan.features);   // ["Advanced analytics", "Unlimited reports"]
  console.log(plan.isPopular);  // true
}

bridge.billing.getSubscription()

Returns the current store's active subscription to your plugin, or null if the store has no subscription.

getSubscription(): Promise<BillingSubscriptionResponse | null>
const sub = await bridge.billing.getSubscription();

if (!sub) {
  // No subscription — show upgrade prompt
  return;
}

console.log(sub.planSlug);          // "pro"
console.log(sub.planName);          // "Pro"
console.log(sub.status);            // "active"
console.log(sub.trialEndsAt);       // "2026-04-15T00:00:00.000Z" | null
console.log(sub.currentPeriodEnd);  // "2026-04-30T00:00:00.000Z" | null
console.log(sub.cancelAtPeriodEnd); // false
console.log(sub.canceledAt);        // null

bridge.billing.requestSubscription(planSlug)

Initiates the subscription flow for the given plan. The admin host redirects the merchant to an approval page. The merchant sees the plan details, price, and trial period before confirming.

requestSubscription(planSlug: string): Promise<void>

Parameters:

ParameterTypeDescription
planSlugstringThe slug of the plan to subscribe to (e.g., "pro")
await bridge.billing.requestSubscription("pro");

This method does not return a value. The host handles the page redirect after the merchant approves. If the merchant cancels on the approval page, no subscription is created.


bridge.billing.cancelSubscription()

Cancels the current subscription at the end of the current billing period. The merchant keeps full access until the period ends — they are not charged again afterward.

cancelSubscription(): Promise<void>
await bridge.billing.cancelSubscription();
// sub.cancelAtPeriodEnd is now true
// sub.canceledAt is now set to the cancellation timestamp

bridge.billing.reactivateSubscription()

Undoes a cancellation. Only available while the subscription is still within its active billing period (i.e., cancelAtPeriodEnd is true and the period has not yet ended).

reactivateSubscription(): Promise<void>
await bridge.billing.reactivateSubscription();
// sub.cancelAtPeriodEnd is now false
// sub.canceledAt is now null

bridge.billing.switchPlan(newPlanSlug)

Switches the current subscription to a different plan. Proration is applied: the merchant receives credit for unused time on the current plan, applied immediately toward the new plan cost.

switchPlan(newPlanSlug: string): Promise<void>

Parameters:

ParameterTypeDescription
newPlanSlugstringSlug of the plan to switch to
await bridge.billing.switchPlan("enterprise");

Type Reference

BillingPlanResponse

interface BillingPlanResponse {
  slug: string;
  name: string;
  price: number;       // Major currency units (e.g., 29.99)
  currency: string;    // "USD"
  interval: string | null;  // "monthly" | "annual" | null
  trialDays: number;
  features: string[];
  isPopular: boolean;
}

BillingSubscriptionResponse

interface BillingSubscriptionResponse {
  planSlug: string;
  planName: string;
  /** "pending" | "trialing" | "active" | "past_due" | "canceled" | "expired" */
  status: string;
  trialEndsAt: string | null;        // ISO timestamp or null
  currentPeriodEnd: string | null;   // ISO timestamp or null
  cancelAtPeriodEnd: boolean;
  canceledAt: string | null;         // ISO timestamp or null
}

Error Handling

All billing methods throw on failure — they do not return { success: false }. Use try/catch for error handling:

try {
  await bridge.billing.requestSubscription("pro");
} catch (error) {
  bridge.toast.show("Subscription failed. Please try again.", {
    variant: "error",
  });
}

Common failure reasons:

  • Network timeout (5 second limit per action)
  • Plan slug does not exist or is inactive
  • No active subscription when calling cancel/reactivate/switchPlan
  • Subscription already in a terminal state

Available Operations

MethodOperationDescription
getPlansgetPlansFetch all active plans
getSubscriptiongetSubscriptionFetch current store subscription
requestSubscriptionrequestSubscriptionInitiate subscription approval flow
cancelSubscriptioncancelSubscriptionCancel at period end
reactivateSubscriptionreactivateSubscriptionUndo a pending cancellation
switchPlanswitchPlanChange plan with proration

On this page