Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,301 @@
---
page_id: 9c7d4e5a-6b8f-4c2a-9e3d-1f5a7c8b2d6e
title: B2B SaaS billing with organizations and per-user pricing
sidebar:
order: 1
tableOfContents:
maxHeadingLevel: 3
description: Implement a standard B2B SaaS architecture with organization-scoped access control, administrator-managed billing, and per-user pricing using metered features.
metadata:
topics: [billing, b2b, organizations, per-user pricing, metered usage, implementation]
sdk: []
languages: []
audience: [developer]
complexity: intermediate
keywords: [b2b saas, per-user pricing, seat-based billing, metered features, organization billing, implementation guide]
updated: 2026-01-15
featured: false
deprecated: false
ai_summary: Complete guide to implementing B2B SaaS billing with organizations, per-user seat-based pricing, metered features, and administrator-managed subscriptions.
---
Comment thread
Arobce marked this conversation as resolved.

This guide explains how to implement a **standard B2B SaaS billing architecture** using organizations, administrator-managed billing, and **per-user (seat-based) pricing** with metered features.

By the end of this guide, you will have:

- Organization-scoped access control
- A per-user billing model backed by metered features
- A billing admin role to manage subscriptions
- Multiple supported organization join patterns
- A strategy for tracking seat usage accurately



### What you need
Comment thread
Arobce marked this conversation as resolved.

- A Kinde account with admin access (Sign up for free)
- A Stripe account (Sign up for free)
- An application connected to Kinde



## Step 1: Connect Stripe

Connect your **Stripe** account from the Kinde dashboard.

1. Go to **Dashboard > Billing > Payment management**
2. Select **Connect Stripe**
3. Follow the Stripe onboarding flow

After connecting Stripe:

- Test and live environments are supported
- Billing plans published in Kinde automatically sync to Stripe
- Stripe products and prices are managed by Kinde

**Learn more:** [Manage Stripe connection](https://docs.kinde.com/billing/payment-management/manage-stripe-connection/)



## Step 2: Create a billing plan in Kinde

Create and configure an organization-scoped billing plan with metered pricing.

### Create an organization billing plan

1. Go to **Dashboard > Billing**
2. Select **Add a plan**
3. In **This plan is for**, select **Organizations**
4. Enter a name, description, key, and currency
5. Select **Save**

![Create an organization plan](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/1c756f99-8534-4805-8b42-5e8a6ee48b00/public)

This plan represents the subscription that organizations will purchase.

### Add a metered feature for user seats

Add a **metered feature** to represent per-user (seat-based) pricing.

1. Open the organization plan
2. Scroll to **Features and pricing**
3. Select **Add feature**
4. Select **New metered**

Configure the feature:

- **Feature name:** `Users`
- **Key:** `user`
This key is required when submitting metered usage.
- **Maximum units:**
Leave empty for unlimited users, or set a limit if required.
- **Unit measurement name:** `user` or `seat`
- **Pricing model:** Per unit
- **Price per unit:** Fixed price per user
- **Line item description:** `User seats`

Select **Save**.

### Add an optional base subscription charge

If your pricing model requires a fixed base fee in addition to per-user pricing:

1. In the same plan, select **Add feature**
2. Select **Fixed charge**
3. Configure the feature:
- **Name:** Base subscription fee
- **Price:** Optional (can be `$0.00`)

![Base subscription fee](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/fbbe9660-8386-4791-f06b-52f7c787e900/public)

This allows you to combine a flat subscription fee with per-user billing.

### Publish the billing plan

Billing plans must be published before they can be used.

1. Open the billing plan
2. Select **Publish**

After publishing, the plan:

- Appears in pricing tables
- Can be selected during signup
- Syncs to Stripe



## Step 3: Configure Kinde billing plan

Set up pricing tables, billing roles, and organization creation settings.

### Create a pricing table

Pricing tables allow users to select a plan during signup.

1. Go to **Dashboard > Billing > Pricing tables**
2. Create or customize a pricing table
3. Toggle **Make live**

Save the **pricing table key**, as it is required during signup.

### Create a Billing Admin role

Organization billing should be managed by administrators.

1. Go to **Settings > Roles**
2. Select **Add role**
3. Configure the role:
- **Name:** Billing Admin
- **Key:** `billing-admin`
- **Assign to the creator if organizations self-sign up:** Enabled
- **System permission:** `org:write:billing`
4. Select **Save**

Users with this role can manage subscriptions, plans, and payment methods for their organization.

### Enable organization creation during signup

Allow users to create organizations when signing up.

1. Go to **Settings > Environment > Organizations**
2. Enable **Organization creation during signup**



## Step 4: Enable org creation in your application

Implement organization creation during signup and configure user join flows.

### Handle the first user (organization creator)

The first user creates the organization and selects a plan.

#### Trigger organization creation from your application

```jsx
<RegisterLink
orgName="Paid Users Organization"
isCreateOrg
pricingTableKey="your_pricing_table_key"
>
Sign up your company
</RegisterLink>
```

#### Use a direct authorization URL

```bash
https://<your_subdomain>.kinde.com/oauth2/auth
?response_type=code
&client_id=YOUR_CLIENT_ID
&redirect_uri=YOUR_REDIRECT_URI
&scope=openid profile email
&is_create_org=true
&pricing_table_key=YOUR_PRICING_TABLE_KEY
```

#### Organization Signup behavior

1. The user registers
2. A new organization is created
3. The user is assigned the Billing Admin role
4. The pricing table is displayed
5. Payment details are collected
6. The organization is created with an active subscription

### Add users to an existing organization

Additional users can join an existing organization using multiple supported approaches.

Before enabling any join flow:

- Ensure the required authentication methods are enabled
- Go to **Org > Policies** and enable **Allow org members to be auto-added**

#### Option 1: Manually add users (dashboard)

Administrators can add users directly from the dashboard.

- No custom code required
- Intended for internal or low-volume usage

#### Option 2: Allow self sign-up using an organization code (recommended)

Users join by signing up or logging in with an organization code.

```jsx
<RegisterLink orgCode="org_8d350c10295bf">
Sign up
</RegisterLink>
```

```jsx
<LoginLink orgCode="org_8d350c10295bf">
Sign in
</LoginLink>
```
Comment thread
Arobce marked this conversation as resolved.

Behavior:

- The user authenticates
- The user is automatically added to the organization

This is the recommended default for most B2B SaaS applications.

#### Option 3: Auto-add users from allowed domains

Users are automatically added based on their email domain.

1. Enable **Allow org members to be auto-added**
2. Enable **Auto-add users from allowed domains**
3. Add allowed domains (for example, `company.com`)

Example:

A user signing up with `jane@acme.com` is automatically added to the Acme organization.



## Track seat usage for billing

Kinde does not automatically calculate seat counts for metered billing. Your application must submit usage updates.

### When to submit usage

Common triggers include:

- A user is added to an organization
- A user is removed or deactivated
- A scheduled reconciliation job (recommended)

### How to submit usage

Submit usage using one of the following:

- Management API
- Workflows
Example: [Track org seat usage workflow](https://github.com/kinde-starter-kits/workflow-examples/blob/main/billing/trackOrgSeatUsageWorkflow.ts)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This repo lead to a 404 error, and I couldn't find it in the examples, can you recheck please?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This repo is yet to be merged @tamalchowdhury .

@onderay, I need your help with this one. Could you please check this PR and help to merge: kinde-starter-kits/workflow-examples#24?

Once it's merged, this should be resolved.

- Billing webhooks

This ensures billing reflects the number of active users in the organization.



## Troubleshooting

### Pricing table not shown during signup

Verify the following:

- The pricing table is **live**
- **Settings > Billing > Billing experience > Show pricing table during signup** is enabled
- The `pricingTableKey` matches the intended pricing table



## Conclusion

You now have a complete B2B SaaS billing setup with organization-scoped access control, administrator-managed subscriptions, and per-user pricing using metered features.

From here, you can extend this architecture with additional metered features, scheduled usage reconciliation, or custom organization join flows using the Management API.
5 changes: 5 additions & 0 deletions src/data/sidebarData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,11 @@ const sidebarData = [
label: "Billing user experience",
autogenerate: {directory: "billing/billing-user-experience"},
collapsed: false
},
{
label: "Implementation guides",
autogenerate: {directory: "billing/implementation-guide"},
collapsed: false
}
]
},
Expand Down