Skip to main content
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.
1

Mount provider in root layout

// 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>
  );
}
2

Consume the iframe SDK in a component

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

Create the iframe SDK instance

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

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

Use the iframe SDK instance

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

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

if (navigationButtonElement) {
  navigationButtonElement.addEventListener("click", () => {
    iframeSdk.openExternalUrl({ url: "https://example.com" });
  });
}
We have now setup the SDK and iFrame.
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.
"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>;
}

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.
"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>;
}
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
"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>;
}
For a complete guide on setting up in-app purchases including creating checkout configurations, handling webhooks, and validating payments, see the Payins documentation.