Overview
Add subscription plans, checkout, trials, and seat-based pricing to your app.
BuildBase handles subscription billing end-to-end. Use the headless PricingPage component for checkout, and openWorkspaceSettings('subscription') for management. Everything else — Stripe integration, plan switching, trials, invoices — is handled automatically.
Warning
Billing requires setup in the BuildBase dashboard before the SDK components will work:
- Connect Stripe — Go to Billing → Credentials and enter your Stripe API keys (use test keys for development)
- Create at least one plan — Go to Billing → Plans, create a plan with a name, price, and billing interval
- Publish a plan version — Plans use versioning. Create and publish at least one version so it appears on the pricing page
- Set up a pricing group — Go to Billing → Pricing Groups. Group your plans so
PricingPageknows what to display
Without these steps, PricingPage renders empty plans and selectPlan() fails.
import { PricingPage } from '@buildbase/sdk/react';
function Pricing() {
return (
<PricingPage slug="main-pricing">
{({ loading, error, plans, selectPlan }) => {
if (loading) return <p>Loading plans...</p>;
if (error) return <p>{error}</p>;
return (
<div className="grid grid-cols-3 gap-4">
{plans.map((plan) => (
<div key={plan._id}>
<h3>{plan.name}</h3>
<button onClick={() => selectPlan(plan._id, 'monthly', 'usd')}>
Choose {plan.name}
</button>
</div>
))}
</div>
);
}}
</PricingPage>
);
}import { useSaaSAuth } from '@buildbase/sdk/react';
function ManageBilling() {
const { openWorkspaceSettings } = useSaaSAuth();
return (
<button onClick={() => openWorkspaceSettings('subscription')}>
Manage Subscription
</button>
);
}Before you start
Create plans and pricing groups in the BuildBase dashboard first.
PricingPage
PricingPage is headless: it fetches plan data and handles checkout logic, and you render the UI through a render prop. Both slug (the pricing group to display) and children (the render function) are required.
The render prop receives:
plans— published plan versions with pricing, features, limits, and quotasitems— subscription items (features, limits, quotas) for building comparison tablesloading/error— fetch stateselectPlan(planVersionId, interval, currency)— opens the plan dialog for authenticated users, or triggers sign-in first (setredirectBaseUrlonPricingPagefor the unauthenticated flow)refetch()— refetch plan data
Optional props: loadingFallback (custom loading UI), errorFallback (custom error UI), and redirectBaseUrl (post-login redirect base for unauthenticated visitors).
openPlanPicker()
Opens the plan selection UI from anywhere in your app — perfect for "Upgrade" buttons inside feature gates or trial banners:
import { useSaaSAuth } from '@buildbase/sdk/react';
function UpgradeButton() {
const { openPlanPicker } = useSaaSAuth();
return <button onClick={() => openPlanPicker()}>Upgrade Plan</button>;
}openWorkspaceSettings('subscription')
Opens the full subscription management screen where users can:
- View current plan and billing interval
- Upgrade or downgrade
- Cancel or resume
- View invoices and payment history
- Access the Stripe billing portal
Reading subscription state
Use hooks when you need to display subscription info or conditionally render UI:
import {
useSubscription,
useTrialStatus,
WhenNoSubscription,
WhenSubscriptionToPlans,
WhenTrialEnding,
} from '@buildbase/sdk/react';
function Dashboard({ workspaceId }) {
const { subscription } = useSubscription(workspaceId);
const { isTrialing, daysRemaining } = useTrialStatus();
return (
<>
{subscription && <p>Plan: {subscription.plan?.name}</p>}
{isTrialing && <p>{daysRemaining} days left in trial</p>}
<WhenNoSubscription>
<p>
No plan yet. <a href="/pricing">Choose a plan</a>
</p>
</WhenNoSubscription>
<WhenSubscriptionToPlans plans={['starter']}>
<p>Upgrade to Pro for more features.</p>
</WhenSubscriptionToPlans>
<WhenTrialEnding daysThreshold={3}>
<p>Trial ends soon — subscribe to keep access.</p>
</WhenTrialEnding>
</>
);
}Hooks
| Hook | What it returns |
|---|---|
useSubscription(workspaceId) | Current plan, status, billing interval |
useTrialStatus() | isTrialing, daysRemaining |
useSeatStatus(workspace) | memberCount, includedSeats, canInvite, inviteBlockReason |
Conditional components
| Component | Renders when |
|---|---|
WhenSubscription | Has an active subscription |
WhenNoSubscription | No subscription |
WhenSubscriptionToPlans | On a specific plan (pass plans prop) |
WhenTrialing | In trial period |
WhenNotTrialing | Not in trial |
WhenTrialEnding | Trial ends within daysThreshold days |
Server-side
Check subscription status from your backend:
import BuildBase from '@buildbase/sdk';
const bb = BuildBase({ serverUrl, orgId, getSessionId });
const { subscription, plan } = await bb.subscription.get(workspaceId);
if (!subscription || subscription.subscriptionStatus !== 'active') {
return Response.json({ error: 'Subscription required' }, { status: 403 });
}Next Steps
- Credits & Usage — Add consumption-based billing.
- Permissions — Gate billing UI by role.