> This page is for For Developers.

> 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.

# Iframe SDK

> Interact with the whop website from within your app.

Whop apps are embedded into the site using iFrames. This SDK provides a type-safe way for you to communicate with the Whop application using a request/response style API powered by `window.postMessage`.

Since this package relies on `window.postMessage`, it only works in **Client Components** or client side javascript.

### Relevant Packages

* `@whop/iframe` - The main package for the iframe SDK.
* `@whop/react` - A React wrapper for Whop Apps including helpers for the iframe SDK.

---

## Setup

The main function exported from the `@whop/iframe` package is the `createSdk` function. When called, this function sets up a listener for messages from the main Whop site, using `window.on('message', ...)`. It is also exposed through the `WhopIframeSdkProvider` component from `@whop/react`.

### React

If you're using React, it is recommended to use the `WhopIframeSdkProvider` component from `@whop/react` to provide the iframe SDK to all child components.

#### Mount provider in root layout

```javascript
// app/layout.tsx
import { WhopIframeSdkProvider } from "@whop/react";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode,
}) {
  return (
    <html lang="en">
      <body>
        <WhopIframeSdkProvider>{children}</WhopIframeSdkProvider>
      </body>
    </html>
  );
}
```

#### Consume the iframe SDK in a component

```javascript
// components/example.tsx
import { useIframeSdk } from "@whop/react";

export const Example = () => {
  const iframeSdk = useIframeSdk();

  return (
    <button
      onClick={() => iframeSdk.openExternalUrl({ url: "https://example.com" })}
    >
      Open External URL
    </button>
  );
};
```

### Other Frameworks

For other frameworks, you can use the `createSdk` function from `@whop/iframe` to create an instance of the iframe SDK.

#### Create the iframe SDK instance

```javascript
// lib/iframe-sdk.ts
import { createSdk } from "@whop/iframe";

export const iframeSdk = createSdk({
  appId: process.env.NEXT_PUBLIC_WHOP_APP_ID,
});
```

#### Use the iframe SDK instance

```javascript
// index.ts
import { iframeSdk } from "../../../lib/iframe-sdk";

const navigationButtonElement = document.querySelector("button");

if (navigationButtonElement) {
  navigationButtonElement.addEventListener("click", () => {
    iframeSdk.openExternalUrl({ url: "https://example.com" });
  });
}
```

> **Check**
>
> We have now setup the SDK and iFrame.

## Opening External Links

Once the iframe SDK is initialized, you can use it to open external links. This will close your app and navigate to a new website.

**`React`**

```javascript React
"use client";
import { useIframeSdk } from "@whop/react";

export default function Home() {
	const iframeSdk = useIframeSdk();

    function openLink() {
    	iframeSdk.openExternalUrl({ url: "https://google.com" });
    }

    return <button onClick={openLink}>Click me to open Google</button>;

}

```

**`Vanilla JS`**

```javascript Vanilla JS
import { iframeSdk } from "../../../lib/iframe-sdk";

const navigationButtonElement = document.querySelector("button");

if (navigationButtonElement) {
  navigationButtonElement.addEventListener("click", () => {
    iframeSdk.openExternalUrl({ url: "https://google.com" });
  });
}
```

### Opening User Profiles

If you want to display a Whop user profile, you can use the `openExternalUrl` method and pass their profile page link which looks like `https://whop.com/@username`.

The Whop app will intercept this and display a modal containing their user profile instead of navigating away.

**`React`**

```javascript React
"use client";
import { useIframeSdk } from "@whop/react";

export default function Home() {
	const iframeSdk = useIframeSdk();

    function openProfile() {
    	iframeSdk.openExternalUrl({ url: "https://whop.com/@j" });
    }

    return <button onClick={openProfile}>View Profile</button>;

}

```

**`Vanilla JS`**

```javascript Vanilla JS
import { iframeSdk } from "../../../lib/iframe-sdk";

const profileButtonElement = document.querySelector("button");

if (profileButtonElement) {
  profileButtonElement.addEventListener("click", () => {
    iframeSdk.openExternalUrl({ url: "https://whop.com/@j" });
  });
}
```

> **Info**
>
> You can also use a user ID instead of username. The final link should look
> like this: `https://whop.com/@user_XXXXXXXX`

## In-App Purchases

The iframe SDK provides a method to trigger in-app purchases directly within your app. This allows you to accept payments for one-time purchases or subscriptions using Whop's checkout.

To process in-app purchases, you'll need to:

1. Create a checkout configuration on your server (with plan details and metadata)
2. Use the iframe SDK's `inAppPurchase` method to open the payment modal
3. Handle the response and validate the payment via webhooks

**`React`**

```tsx React
"use client";
import { useIframeSdk } from "@whop/react";
import { useState } from "react";

export default function PaymentButton() {
    const iframeSdk = useIframeSdk();
    const [paymentId, setPaymentId] = useState<string>();

    async function handlePurchase() {
        // 1. Create checkout configuration on server
        //    (in this example this is a nextjs server action, but it could also be a plain API route)
        const checkoutConfiguration = await createCheckoutConfiguration(/* can pass options here */);

        // 2. Open payment modal
        const res = await iframeSdk.inAppPurchase({
            planId: checkoutConfiguration.plan.id,
            id: checkoutConfiguration.id
        });

        if (res.status === "ok") {
            setPaymentId(res.data.receipt_id);
        } else {
            // handle errors
        }
    }

    return <button onClick={handlePurchase}>Purchase</button>;

}

```

**`Vanilla JS`**

```javascript Vanilla JS
import { iframeSdk } from "../../../lib/iframe-sdk";

const paymentButton = document.querySelector("button#payment-button");

paymentButton.addEventListener(
    "click",
    async function onPaymentButtonClick() {
        // 1. Create checkout configuration on server
        const checkoutConfiguration = await createCheckoutConfiguration(/* can pass options here */);

        // 2. Open payment modal
        const res = await iframeSdk.inAppPurchase({
            planId: checkoutConfiguration.plan.id,
            id: checkoutConfiguration.id
        });

        if (res.status === "ok") {
            const paymentId = res.data.receipt_id;
            // Send this id to your backend to validate, or rely on webhooks.
            // User has purchased the item, and it can be unlocked.
        } else {
            // handle errors
        }
    }
);
```

> **Info**
>
> For a complete guide on setting up in-app purchases including creating
> checkout configurations, handling webhooks, and validating payments, see the
> [Accept payments documentation](/developer/guides/accept-payments).