This guide is the complete setup sequence in one page, with validation steps — optimized for AI
agents and for careful step-by-step integration (agents can fetch it as markdown by appending
.md to this page’s URL). For learning the component and ongoing development, start with the
Quickstart and its sibling pages.- Set up the Convex component and webhook route.
- Export the connected Convex billing API.
- Define the browser-side billing catalog.
- Wrap your billing UI in
CreemConvexProvider. - Choose the billing path you need: subscriptions, one-time products, credits, account tools, or usage gates.
- Existing webhook paths in your app and payment provider dashboard, such as
/api/stripe/webhook,/api/billing/webhook,/webhooks/lemonsqueezy, or other custom billing endpoints. Keep them only if another live billing flow still depends on them. - Public client env vars for the old billing UI, such as product, price, plan, checkout, or publishable-key variables in
VITE_*,NEXT_PUBLIC_*, orPUBLIC_*namespaces. - Server env vars for the old billing system, such as API keys, webhook signing secrets, customer portal configuration, price IDs used by server actions, or framework route secrets.
- Background jobs, scheduled syncs, or server functions that still read the old billing env vars or process the old webhook events.
1. Install
Install the package plus the peer dependencies for the frontend framework you use.2. Register the Convex component
Create or updateconvex/convex.config.ts:
CREEM_SERVER=test points the component at the Creem test API, matching a test-mode API key. Set it to prod (or omit it) when deploying with a production key.
If you use credit packs, also set a server-side product ID. Do not trust a browser-exposed product ID for webhook fulfillment:
3. Export the Convex billing API
Createconvex/billing.ts. Replace the resolver with your real auth and entity logic. entityId is the billing owner; use the user ID for user billing or the org/team ID for organization billing.
export const creem = new Creem(...)exports a normal server-side object for other Convex modules such ashttp.ts; it does not register a client-callable Convex function.- Functions returned by
creem.api({ resolve })become public when exported fromconvex/billing.ts. resolvemust authenticate the caller and authorize the selected user or organization. Generated functions then bind customers, subscriptions, transactions, and credit reads to that resolvedentityId.- Privileged credit operations are intentionally absent from the generated public API. Put grants and spending behind app-owned actions whose amount, reference, and idempotency policy are controlled on the server.
- Export only capabilities your UI needs. If you omit
subscriptions.cancel, cancel buttons disappear. - Use
cancelMode: "scheduled"when canceling should keep access until the current period ends. Use"immediate"when cancellation should end access immediately. - Put credit grants in the server catalog because webhooks run on the server.
syncBillingProductsis intentionally aninternalAction. Trigger it from the Convex CLI, dashboard, or another trusted internal function, not from browser UI.- App-owned credit spending, such as
generateImage, should callcreem.credits.debitForEntitywith server-controlled business inputs. The credits widget only displays and refreshes balance state.
4. Register the webhook route
Create or updateconvex/http.ts:
Create the products
Every plan in your catalog maps to a Creem product. Create them in the dashboard, or with the CLI. Running it throughnpx avoids installing anything globally on the developer’s machine:
CREEM_API_KEY in step 2. brew and global npm installs are also available; see the CLI guide.
Repeat for every plan and billing cycle you offer. A plan billed monthly and yearly needs two products. creem products list --json prints the IDs for scripting.
--billing-period accepts every-month, every-three-months, every-six-months, or every-year, and is required when --billing-type is recurring. Use --billing-type onetime for one-time products and credit packs.
Sync them into Convex
Once the products exist, pull their metadata into Convex:5. Add CSS
Import the package CSS in your app CSS entry point:6. Define the browser billing catalog
Create a shared catalog file in your frontend. Import from the framework entry you are using (/svelte or /react).
creemProductIdsmaps billing cycles to Creem product IDs.- Supported recurring cycles are
every-month,every-three-months,every-six-months, andevery-year. - If a plan has multiple cycles, the interval selector appears automatically.
- Product IDs used only by frontend widgets may live in your framework’s public client env namespace, such as Vite
VITE_*, Next.jsNEXT_PUBLIC_*, or SvelteKitPUBLIC_*. Trusted webhook fulfillment data must live in Convex env vars.
7. Connect Svelte
In Svelte, initialize Convex once withsetupConvex, create a ConnectedBillingApi, and wrap widgets in CreemConvexProvider. The provider is the required integration boundary. ConvexCreemProvider is not an exported component name; the package exports CreemConvexProvider.
CreemConvexProvider. Do not pass api={...} directly to Subscription.Root, Product.Root, BillingPortal, or BillingHistory.
The provider-level ConnectedBillingApi decides which paths are available:
Use
createCreemSvelte when you want one typed binding object:
uiModel directly once for account-level UI such as payment recovery and usage gates:
8. Connect React
React uses the sameConnectedBillingApi shape. The difference is your normal Convex React client setup.
9. Choose your billing path
Use the closest path as your starting point.
The external paths are:
/creem/events— Convex HTTP webhook endpoint for Creem.- Creem checkout URL — opened by
checkouts.create. - Creem customer portal URL — opened by
customers.portalUrl. - Your checkout success URL — defaults to the current page path when
successUrlis not passed.
10. Environment placement checklist
Use your app framework’s public client env namespace only for values the browser needs to render widgets or start checkout, such as product IDs referenced by the frontend catalog:.env files:
.env* files, hosting provider env settings, CI secrets, Convex env, and the payment provider dashboard. Search for the old provider name and old public prefixes so unused webhook secrets, price IDs, product IDs, publishable keys, and API keys do not linger.
11. Validation
Before shipping an integration:- Type-check and lint your app with your project’s usual commands.
- Run
timeout 30 npx convex dev --onceand confirm the deployment pushes without errors. - Complete a test-mode checkout with a test card and confirm the webhook writes billing state (check the Convex dashboard data browser and logs).
- Confirm the widgets reflect the new subscription without a page reload.