Skip to main content

Server side implementation

To use the embedded component, you need to generate an access token for the sub-merchant’s company. This token grants temporary access to the payout portal for that specific company.
// app/api/token/route.ts
import Whop from "@whop/sdk";
import type { NextRequest } from "next/server";

const whop = new Whop({
	apiKey: process.env.WHOP_API_KEY,
});

export async function GET(request: NextRequest) {
	// Authenticate your user here
	const companyId = request.nextUrl.searchParams.get("companyId");

	if (!companyId) {
		return new Response(null, { status: 400 });
	}
	const tokenResponse = await whop.accessTokens
		.create({
			company_id: companyId,
		})
		.catch(() => {
			return null;
		});
	if (!tokenResponse) {
		return new Response(null, { status: 500 });
	}
	const token = tokenResponse.token;
	return Response.json({
		token,
	});
}

Create Access Token API

See the full API reference for generating access tokens and all available parameters

Client side setup

npm install @whop/embedded-components-react-js @whop/embedded-components-vanilla-js

Client side implementation

"use client";

import type { WhopElementsOptions } from "@whop/embedded-components-vanilla-js/types";

import {
	BalanceElement,
	Elements,
	PayoutsSession,
	WithdrawButtonElement,
} from "@whop/embedded-components-react-js";
import { loadWhopElements } from "@whop/embedded-components-vanilla-js";

const elements = loadWhopElements();

const appearance: WhopElementsOptions["appearance"] = {
	classes: {
		".Button": {
			height: "40px",
			"border-radius": "8px",
		},
		".Button:disabled": {
			"background-color": "gray",
		},
		".Container": {
			"border-radius": "12px",
		},
	},
};

export function BalancePage({ companyId }: { companyId: string }) {
	return (
		<Elements appearance={appearance} elements={elements}>
			<PayoutsSession
				token={() =>
					fetch(`/api/token?companyId=${companyId}`)
						.then((res) => res.json())
						.then((data) => data.token)
				}
			>
				<section
					style={{ display: "flex", flexDirection: "column", gap: "8px" }}
				>
					<div
						style={{ height: "95.5px", width: "100%", position: "relative" }}
					>
						<BalanceElement fallback={<div>Loading...</div>} />
					</div>
					<div style={{ height: "40px", width: "100%", position: "relative" }}>
						<WithdrawButtonElement fallback={<div>Loading...</div>} />
					</div>
				</section>
			</PayoutsSession>
		</Elements>
	);
}