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

1. Create the charge on the server

This step will create a charge on the server and return the inAppPurchase object required for the next step.

On the server, use the chargeUser method to create a charge:

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

export async function POST(request: Request) {
  try {
    const { userId, experienceId } = await request.json();

    const result = 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,
        },
      },
    });

    if (!result.chargeUser?.inAppPurchase) {
      throw new Error("Failed to create charge");
    }

    return Response.json(result.chargeUser.inAppPurchase);
  } catch (error) {
    console.error("Error creating charge:", error);
    return Response.json({ error: "Failed to create charge" }, { status: 500 });
  }
}

2. Confirm the payment on the client

In this step the user will be prompted to confirm the previously created charge in a modal.

This function requires the iFrame SDK to be initialized. See iFrame Overview for more information.

Use the iframe SDK to open a payment modal:

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

export default function PaymentButton({
  userId,
  experienceId,
}: {
  userId: string;
  experienceId: string;
}) {
  const iframeSdk = useIframeSdk();
  
  const [receiptId, setReceiptId] = useState<string>();
  const [error, setError] = useState<string>();
  
  async function handlePurchase() {
    try {
      // 1. Create charge on server
      const response = await fetch("/api/charge", {
        method: "POST",
        body: JSON.stringify({ userId, experienceId }),
      });
      
      if (response.ok) {
        const inAppPurchase = await response.json();
        // 2. Open payment modal
        const res = await iframeSdk.inAppPurchase(inAppPurchase);
        
        if (res.status === "ok") {
          setReceiptId(res.data.receipt_id);
          setError(undefined);
        } else {
          setReceiptId(undefined);
          setError(res.error);
        }
      } else {
        throw new Error("Failed to create charge");
      }
    } catch (error) {
      console.error("Purchase failed:", error);
      setError("Purchase failed");
    }
  }
  
  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,
    },
  });
}