Leave Localhost logoLeave LocalhostDocs
Recipes

Add a New Billing Plan

Add a plan to the provider-neutral billing catalog: define it, attach capabilities, and map it to a real provider product.

Add a plan to the provider-neutral catalog. The catalog (packages/backend/convex/billing/plans.config.ts) is the single source of truth and works the same across Stripe, Polar, and Lemon Squeezy. The full guide is Billing Catalog; this is the short path.

1. Add the plan entry

enterprise_monthly: {
  planKey: "enterprise_monthly",
  displayName: "Enterprise",
  interval: "month",
  sortOrder: 4,
  capabilityKeys: [
    "feature.pro",
    "feature.enterprise",
    "workspace.members.invite",
    "workspace.members.limit.unlimited",
    "billing.portal",
  ],
},

2. Register new capabilities

If the plan unlocks something new, add the key to permissions/capabilities.ts and its validator in permissions/validators.ts. See Capabilities.

3. Add the plan key to the validator

Add it to billingPlanKeyValidator in plans.config.ts. Validators are explicit so unknown plan keys fail closed.

4. Map the provider product

Add the plan to providerPlanEnvMappings for each provider you support, then set the env var to the real product/price ID:

stripe: { STRIPE_ENTERPRISE_MONTHLY_PRICE_ID: "enterprise_monthly" },
STRIPE_ENTERPRISE_MONTHLY_PRICE_ID=price_xxx

5. Expose it in checkout and pricing UI

Call checkout with the internal planKey, never a provider id:

await createCheckout({ planKey: "enterprise_monthly" });

Keep authorization capability-based so every provider maps to the same internal plan. To turn the new capability into a gated feature, continue with Add a New Paid Feature.

On this page