āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā š shadcn/directory/clerk/clerk-docs/guides/billing/for-b2b ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
Clerk billing for B2B SaaS allows you to create plans and manage subscriptions for companies or organizations in your application. If you'd like to charge individual users, see Billing for B2C SaaS. You can also combine both B2C and B2B billing in the same application.
<Include src="_partials/billing/enable-billing" />Subscription plans are what your customers subscribe to. There is no limit to the number of plans you can create. If your Clerk instance has existing custom permissions, the corresponding features from those permissions will automatically be added to the free plan for orgs. This ensures that organization members get the same set of custom permissions when billing is enabled, because all organizations start on the free plan.
To create a plan, navigate to the Plans page in the Clerk Dashboard. Here, you can create, edit, and delete plans. To setup B2B billing, select the Plans for Organizations tab and select Add Plan. When creating a plan, you can also create features for the plan; see the next section for more information.
[!TIP] What is the Publicly available option?
Plans appear in some Clerk components depending on what kind of plan it is. All plans can appear in the
<PricingTable />component. If it's an organization plan, it can appear in the<OrganizationProfile />component. When creating or editing a plan, if you'd like to hide it from appearing in Clerk components, you can toggle the Publicly available option off.
Features make it easy to give entitlements to your plans. You can add any number of features to a plan.
You can add a feature to a plan when you are creating a plan. To add it after a plan is created:
[!TIP] What is the Publicly available option?
Plans appear in some Clerk components depending on what kind of plan it is. All plans can appear in the
<PricingTable />component. If it's an organization plan, it can appear in the<OrganizationProfile />component. When adding a feature to a plan, it will also automatically appear in the corresponding plan. When creating or editing a feature, if you'd like to hide it from appearing in Clerk components, you can toggle the Publicly available option off.
You can create a pricing page by using the <PricingTable /> component. This component displays a table of plans and features that customers can subscribe to. It's recommended to create a dedicated page, as shown in the following example.
You can use Clerk's features, plans, and permissions to gate access to content using authorization checks. There are a few ways to do this, but the recommended approach is to either use the has() method or the <Protect> component.
The has() method is available for any JavaScript-based framework, while <Protect> is a component, and therefore, is only available for React-based frameworks.
[!IMPORTANT] Permission-based authorization checks link with feature-based authorization checks. This means that if you are checking a custom permission, it will only work if the feature part of the permission key (
org:<feature>:<permission>) is a feature included in the organization's active plan. For example, say you want to check if an organization member has the custom permissionorg:teams:manage, whereteamsis the feature. Before performing the authorization check, you need to ensure that the user's organization is subscribed to a plan that has theteamsfeature. If the user's organization is not subscribed to a plan that has theteamsfeature, the authorization check will always returnfalse, even if the user has the custom permission.
has()Use the has() method to test if the organization has access to a plan:
const hasPremiumAccess = has({ plan: 'gold' })
Or a feature:
const hasPremiumAccess = has({ feature: 'widgets' })
The has() method is a server-side helper that checks if the organization has been granted a specific type of access control (role, permission, feature, or plan) and returns a boolean value. has() is available on the auth object, which you will access differently depending on the framework you are using.
[!TIP] Why aren't custom permissions appearing in the session token (JWT) or in API responses (including the result of the
has()check)?
Custom permissions will only appear in the session token (JWT) and in API responses (including the result of the
has()check) if the feature part of the permission key (org:<feature>:<permission>) is a feature included in the organization's active plan. If the feature is not part of the plan, thehas()check for permissions using that feature will returnfalse, and those permissions will not be represented in the session token.For example, say you want to check if an organization member has the custom permission
org:teams:manage, whereteamsis the feature. The user's organization must be subscribed to a plan that has theteamsfeature for authorization checks to work. If the user's organization is not subscribed to a plan that has theteamsfeature, the authorization check will always returnfalse, even if the user has the custom permission.
<Tabs items={[ "Plan", "Feature", "Permission"]}>
<Tab>
The following example demonstrates how to use has() to check if an organization has a plan.
<Include src="_partials/billing/checking-plan-using-has-function" />
</Tab>
<Tab>
The following example demonstrates how to use `has()` to check if an organization has a feature.
<Include src="_partials/billing/checking-feature-using-has-function" />
</Tab>
<Tab>
The following example demonstrates how to use `has()` to check if an organization has a permission.
<Include src="_partials/billing/checking-permission-using-has-function" />
</Tab>
</Tabs>
<Protect>The <Protect> component protects content or even entire routes by checking if the organization has been granted a specific type of access control (role, permission, feature, or plan). You can pass a fallback prop to <Protect> that will be rendered if the organization does not have the access control.
<Tabs items={["Plan", "Feature", "Permission"]}>
<Tab>
The following example demonstrates how to use <Protect> to protect a page by checking if the organization has a plan.
<Include src="_partials/billing/checking-plan-using-protect" />
</Tab>
<Tab>
The following example demonstrates how to use `<Protect>` to protect a page by checking if the organization has a feature.
<Include src="_partials/billing/checking-feature-using-protect" />
</Tab>
<Tab>
The following example demonstrates how to use `<Protect>` to protect a page by checking if the organization has a permission.
<Include src="_partials/billing/checking-permission-using-protect" />
</Tab>
</Tabs>ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā