Collecting Payments

First, create the charge on the server using the Whop API. Then you can either:

  1. Open a modal in your app using the iframe SDK (recommended)
  2. Redirect the user to Whop’s checkout page

Server-Side: Create the Charge

// app/api/charge/route.ts
import { whopApi } from "@/lib/whop-api";
import { NextResponse } from "next/server";

export async function POST(request: Request) {
  try {
    const { userId, experienceId } = await request.json();
    
    const chargeUser = await whopApi.chargeUser({
      input: {
        amount: 100,
        currency: "usd",
        userId: userId,
		  // metadata is information that you'd like to receive later about the payment.
        metadata: {
          creditsToPurchase: 1,
          experienceId: experienceId,
        },
        redirectUrl: `https://whop.com/experiences/${experienceId}`
      },
    });

    return NextResponse.json({
      checkoutUrl: chargeUser?.chargeUser?.checkoutSession?.purchaseUrl,
      planId: chargeUser?.chargeUser?.checkoutSession?.planId
    });
  } catch (error) {
    console.error("Error creating charge:", error);
    return NextResponse.json({ error: "Failed to create charge" }, { status: 500 });
  }
}

Client-Side: Handle Payment (Option 1 - Modal)

Use the iframe SDK to open a payment modal (recommended for better UX):

"use client";

import { useIframeSdk } from "@whop/sdk";

export default function PaymentButton({ userId, experienceId }: { 
  userId: string;
  experienceId: string;
}) {

  const iframeSdk = useIframeSdk();
  const [receiptId, setReceiptId] = useState<string>();
  const [error, setError] = useState<string>();

  const handlePurchase = async () => {
    try {
      // 1. Create charge on server
      const response = await fetch("/api/charge", {
        method: "POST",
        body: JSON.stringify({ userId, experienceId })
      });
      const data = await response.json();
      
      if (!data.planId) {
        throw new Error("No plan ID returned");
      }

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

      if (res.status === "ok") {
        setReceiptId(res.data.receipt_id);
        setError(undefined);
      } else {
        setReceiptId(undefined);
        setError(res.error);
      }
    } catch (error) {
      console.error("Purchase failed:", error);
      setError("Purchase failed");
    }
  };

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

Client-Side: Handle Payment (Option 2 - Redirect)

Alternatively, redirect the user to Whop’s checkout page:

"use client";

export default function PaymentButton({ userId, experienceId }: {
  userId: string;
  experienceId: string;
}) {
  const handlePurchase = async () => {
    try {
      const response = await fetch("/api/charge", {
        method: "POST",
        body: JSON.stringify({ userId, experienceId })
      });
      const data = await response.json();
      
      if (data.checkoutUrl) {
        window.location.href = data.checkoutUrl;
      } else {
        throw new Error("No checkout URL returned");
      }
    } catch (error) {
      console.error("Purchase failed:", error);
    }
  };

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

Sending Payouts

You can send payouts to any user using their Whop username. The funds will be transferred from your company’s ledger account.

Transfer Funds

import { whopApi } from "@/lib/whop-api";

async function sendPayout(
  companyId: string, 
  recipientUsername: string, 
  amount: number
) {
  // 1. Get your company's ledger account
  const experience = await whopApi.getExperience({ experienceId });
  const companyId = experience.experience.company.id;
  const ledgerAccount = await whopApi.getCompanyLedgerAccount({ companyId });

  // 2. Pay the recipient
  await whopApi.payUser({
    input: {
      amount: amount,
      currency: "usd",
      // Username or ID or ledger account ID of the recipient user
      destinationId: recipientUsername,
      // Your company's ledger account ID that can be retrieve from whopApi.getCompanyLedgerAccount()
      ledgerAccountId: ledgerAccount.company?.ledgerAccount.id!,
      // Optional transfer fee in percentage
      transferFee: ledgerAccount.company?.ledgerAccount.transferFee
    }
  });
}