> This page is for For Users.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://whop.ferndocs.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://whop.ferndocs.com/_mcp/server.

# SaaS

> Learn how to build and run your SaaS on Whop

#### [Integrate with license keys](#license-key-integration)

Use license keys to gate access to your software.

#### [Integrate with email login](#email-login-integration)

Let users sign in via email and validate access with the SDK.

## Email login integration

If you have an existing SaaS or are building a new one, you can use Whop to direct your customers to pay and let them manage their membership.

To integrate, all you have to do is adjust your `User` table to include the `whop_user_id` and `whop_username` columns.

| Column          | Type   | Description                                                |
| --------------- | ------ | ---------------------------------------------------------- |
| `whop_user_id`  | string | Unique identifier for the user provided by Whop.           |
| `whop_username` | string | The user's Whop username, helpful for display and logging. |

**Note**
Use the Whop SDK’s `access.checkIfUserHasAccessToAccessPass` method (shown in Step 6) by passing the `whop_user_id` and the relevant access pass (product) ID to determine whether the user should be allowed to access your software.

If you would prefer to not have manage your own user table or even a database, consider building a Whop app here.

## Get your SaaS live on Whop:

#### Create your whop

Head over to [**whop.com/sell**](https://whop.com/dashboard/start/):

* Choose a name for your SaaS
* Select your custom URL
* Complete the basic setup

Your whop is now live and ready to customize.

![Launch your SaaS](/_fern-img/168ca2e0476909494a4aa85784c16ad7245e3af9d2052c30a927ecd1fc319a43.webp)

#### Create a product

* Go to your Dashboard
* Go to Products
* Click Add Product

#### Add checkout link to your website

There are two primary ways to send customers to checkout: an embedded checkout or a hosted checkout link.

### Embedded checkout

Follow these two steps to embed the checkout on your page. First, include the Whop Checkout loader script:

```html
<!-- Step 1 – Include the Whop Checkout loader -->
<script
  async
  defer
  src="https://js.whop.com/static/checkout/loader.js"
></script>
```

Then, add the checkout element where you want it to appear. Replace `plan_XXXXXXXXX` with your actual plan ID from the dashboard.

```html
<!-- Step 2 – Add the checkout element -->
<div data-whop-checkout-plan-id="plan_XXXXXXXXX"></div>
```

### Hosted checkout link

Alternatively, you can link customers to Whop’s hosted checkout page. You can get this link from your dashboard or generate one programmatically and link to the `checkoutUrl` it returns (as shown in Step 6).

```html
<!-- Hosted checkout link -->
<a href="https://whop.com/checkout/plan_xxxxxxxxx" target="_blank" rel="noopener">
  Buy now
</a>
```

If you would like to programmatically create a checkout session, you can do so with the following code:

**`pages/api/create-checkout-session.ts`**

```typescript pages/api/create-checkout-session.ts
import { whopSdk } from "~/lib/whop-sdk";

export async function createCheckoutSession(experienceId: string) {
	const checkoutSession = await whopSdk.payments.createCheckoutSession({
		planId: process.env.NEXT_PUBLIC_PREMIUM_PLAN_ID!,
		metadata: {
			customKey: "customValue",
		},
	});

	return checkoutSession;
}
```

When you receive the webhook (see below), you can use the `metadata` object to access the custom key and value you attached to the checkout session.

#### Add an app and get API keys

Go to your dashboard and add app

#### Subscribe to webhooks

Go to the dashboard section and add a webhook.

#### Check for access programmatically

**`lib/whop-sdk.ts`**

```typescript lib/whop-sdk.ts
import { WhopServerSdk } from "@whop/api";

// Instantiate the Whop SDK client.
// 👉 Replace the ENV vars below with the ones from your Whop dashboard.
export const whopSdk = WhopServerSdk({
	// Required: your App ID ("App Settings" → App ID)
	appId: process.env.NEXT_PUBLIC_WHOP_APP_ID!,

	// Required: the API key you generated in "API Keys"
	appApiKey: process.env.WHOP_API_KEY!,
});
```

**`pages/api/validate-access.ts`**

```typescript pages/api/validate-access.ts
import { whopSdk } from "~/lib/whop-sdk";

// Validate that a signed-in user has access to your premium product before
// letting them use your SaaS feature.
export async function validateAccess(whopUserId: string) {
	const result = await whopSdk.access.checkIfUserHasAccessToAccessPass({
		// Access Pass / Product ID you want to gate behind
		accessPassId: process.env.NEXT_PUBLIC_PREMIUM_ACCESS_PASS_ID!,
		// The Whop user we stored in our database
		userId: whopUserId,
	});

	return result.hasAccess; // boolean
}
```

#### Give users a way to manage their membership

You can link users here to manage their membership: [https://whop.com/@me/settings/memberships/](https://whop.com/@me/settings/memberships/).

They can simply login with the same email and they use to access your SaaS without a password.

#### Design your store page and list on marketplace

Your store page is where people can learn about your offer. Click your whop name in the top left, then select **Design store page** to open the editor. Click **Edit details** to customize:

* **Choose a clear name and headline:** Make it immediately obvious what your community offers and who it's for. Examples: "Marketing professionals sharing strategies and insights" or "Fitness enthusiasts building accountability and motivation"
* **Write a compelling description:** Focus on the value members receive and how your community will help them achieve their goals. Highlight specific benefits like exclusive content, expert guidance, peer connections, and ongoing support
* **Upload a logo:** Add a clean, simple logo to your store page
* **Add gallery images or video:** Images of events, member success stories, or a brief welcome video help potential members get to know you and what to expect when they join
* **Select the appropriate category:** This helps people discover your community when browsing Whop

![Community store page](/_fern-img/421fcb7e3d43489a961c3ba205cc39951794c8800b283c1526244b02e206071a.webp)

## License Key Integration

After purchasing a product, users are granted a unique license key that they can use to access and unlock their purchased product. As a developer, you can integrate this feature into your own software by requiring your users to enter their license key before being granted access to the product, or gate certain features of the application behind validating the current license key.

## Getting started

1. Add the software app to your whop [here](https://whop.com/apps/app_jHH5YT7jHYQANi/install/).
2. Click configure in new software app you added
3. Add software name and download link

### Validating license keys via API

If the metadata on the license key is empty (for example, the key is not yet bound to a computer), Whop's API returns a success response with status code `201`. This means that the license key is valid and can be used to access the product. Internally, the API sets the metadata of the license key that was passed in the API call.

#### Initially Setting the Metadata

**`typescript`**

```js typescript
import axios from "axios";

const setMetadata = async () => {
	try {
		const response = await axios.post(
			`https://api.whop.com/api/v2/memberships/${licenseKey}/validate_license`,
			{
				headers: {
					Authorization: `Bearer ${accessToken}`,
				},
				body: {
					metadata: {
						key: "value", // This is initially setting the key/value pair if it doesn't already exist
					},
				},
			},
		);
		return response.data;
	} catch (error) {
		throw error;
	}
};

export default setMetadata;
```

### Validating Matching Metadata

If the metadata on the license key is already set, and it matches the metadata that your software sends to Whop's API, then a success response is returned. This means that the license key is valid and can be used to access the product. Whop's API checks every key value pair in the metadata, ensuring that all fields contain the same data.

Below is example metadata that would return a successful response if you wanted to store the users hardware ID (to only allow one session per user):

**Client-side**

```json
{
	"hwid": "098H52ST479QE053V2"
}
```

**Server-side**

```json
{
	"hwid": "098H52ST479QE053V2"
}
```

### Validating Mismatched Metadata

If the metadata on the license key is set, but the metadata fields do not match the metadata that your software sends to Whop's API, a failure response with status code `400` is returned. This means that the license key is not valid and cannot be used to access the product.

Below is example metadata that would return this error.

**Client-side**

```json
{
	"hwid": "30294GLDKJ54F0SLKF"
}
```

**Server-side**

```json
{
	"hwid": "098H52ST479QE053V2"
}
```

### Removing Metadata

Users can reset their key's metadata by going to their orders - but to programmatically reset their license, you'll need to send a POST request to our [memberships endpoint](/api-reference/v2/memberships/update-a-membership) with an empty metadata body to reset it.

## Next steps

#### [Add apps to your whop](/manage-your-business)

Add apps to let your users learn how to use your software, chat with
eachother, and even order merch.