Where this code goes, and what it assumes
Where this code goes, and what it assumes
Examples on this page are fragments. They render inside the provider you mounted
in the Quickstart:If something below does not work, one of these is usually missing. Each links
straight to the step that sets it up.
- Component registered —
app.use(creem)inconvex/convex.config.ts - Secrets set —
CREEM_API_KEYandCREEM_WEBHOOK_SECRETin Convex env - Billing API exported —
convex/billing.tscallingcreem.api({ resolve }) - Webhook registered —
creem.registerRoutes(http)inconvex/http.ts - Products created — one Creem product per plan and billing cycle
- Products synced —
npx convex run billing:syncBillingProducts - Styles imported —
@creem_io/convex/stylesafter the Tailwind import - Catalog defined —
billingCatalogmapping plan IDs to product IDs - Provider mounted —
<CreemConvexProvider>around your billing UI
Gating UI with BillingGate
BillingGate conditionally renders based on which billing actions are available in the snapshot (checkout, portal, cancel, reactivate):
- React
- Svelte
Account page
Usage limits
Catalog plans can carrylimits (arbitrary numeric keys like projects or aiMessages). evaluateUsageLimits compares your app’s usage counters against the active plan’s limits:
UI permissions
BillingPermissions controls which widget buttons are enabled. Use it for role-based UI, such as letting only org admins manage billing. Set it once at the provider:
Account page
Account widgets
Billing portal
Opens the Creem customer portal, which is where payment methods, billing details, and invoice documents live. It hides itself when the entity has no Creem customer record yet, since customers are created on first checkout:Account page
customers.portalUrl in the connected API.
Billing history
Paginated transaction history, backed by Creem’s transaction search. This renders transaction rows, not invoice documents:Account page

transactions.search in the connected API. Export transactionsSearch from convex/billing.ts and connectCreemApi wires it automatically.
Portal-only today. Payment methods, billing details, and invoice documents are handled by
Creem’s hosted portal, which
<BillingPortal> opens for the customer. Prefer them embedded in
your own UI as Widgets? Vote for payment method, billing preference, and invoice
APIs.Payment recovery
When a subscription is past due or a payment failed, surface it and route the user to the portal to fix their payment method:Account page

snapshot.paymentRecoveryState (or accepts an explicit state). The button reads customers.portalUrl from the provider like every other connected widget, and renders nothing when no portal action is wired.
Checkout success
Show a confirmation banner when the user returns from checkout. Creem’s query parameters are parsed for you:Account page
useCheckoutSuccessParams() hook returning the parsed params.
Status banners
Presentational components for specific states, fed from the snapshot:Server-side entitlement checks
The same snapshot powers backend enforcement:convex/projects.ts
Checking a single subscription
When you gate onsubscriptions.getCurrent rather than the snapshot, test the
status - never the mere existence of a subscription. A returned
subscription may be unpaid or paused, in which case it must not grant
access:
isActiveSubscriptionStatus treats active, trialing, scheduled_cancel,
and past_due as entitling. past_due is a payment-retry window rather than a
loss of access - surface it with
PaymentRecoveryBanner instead of cutting the user off.
