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); // nullbridge.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:
| Parameter | Type | Description |
|---|---|---|
planSlug | string | The 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 timestampbridge.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 nullbridge.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:
| Parameter | Type | Description |
|---|---|---|
newPlanSlug | string | Slug 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
| Method | Operation | Description |
|---|---|---|
getPlans | getPlans | Fetch all active plans |
getSubscription | getSubscription | Fetch current store subscription |
requestSubscription | requestSubscription | Initiate subscription approval flow |
cancelSubscription | cancelSubscription | Cancel at period end |
reactivateSubscription | reactivateSubscription | Undo a pending cancellation |
switchPlan | switchPlan | Change plan with proration |
Revenue & Payouts
Track your plugin earnings and request payouts through the Developer Portal. Understand commission calculation and payout requirements.
Review Process
All public plugins go through a manual review before being listed in the marketplace. Understand what reviewers check and how to prepare your submission.