The billing entity
Every subscription, order, and credit balance belongs to one billing entity, identified by theentityId your resolver returns. It is the first decision you make and the most awkward one to change later.
For personal billing, return the user ID. For organization or team billing, return the org ID. Checkout metadata and webhook resolution follow automatically, with no other code changes:
The billing state model
Billing state comes from four places. Three of them store data. The fourth is derived from the other three, and that distinction is worth learning early:
Write to the first three through checkout, webhooks, and
creem.appPlans.activate. Do not treat access as a source of truth. It is recomputed on every read.
snapshot (generated by creem.api({ resolve })) and creem.getBillingSnapshot(ctx, { entityId }) both return this shape. Everything is synced into Convex, so reading it is a local reactive query with no Creem API round-trip.
Easily confused pairs
The connected API contract
Widgets hold no Convex function references of their own. Every backend call goes through oneConnectedBillingApi object they read from the provider, and its fields decide what the UI can do. Export and wire only what your product should allow.
connectCreemApi maps the conventional convex/billing.ts export names onto that shape for you. Every reference is typed by function kind, args, and return type, so a missing or mis-wired export is a compile error rather than a blank widget:
Building the object by hand still works when you wrap the generated functions in your own RBAC actions. See Advanced → Custom auth and RBAC.
Where to go next
- Wire the entity and export the API: Quickstart
- Enforce access on the server: Entitlements
- Custom auth, RBAC, and webhook middleware: Advanced
- Exact signatures and props: Reference