API guide
Whop checkout: from a payment link to a verified order

Follow a documented Whop checkout flow: create a hosted payment link, guide the buyer, and verify signed payment webhooks before fulfilling an order.
Contents
Contents
In collaboration with Whop.
Create a checkout configuration on your server, send the buyer to its purchase_url, and fulfill the order only after a verified payment.succeeded webhook. This documented route suits an application that wants Whop to host checkout while keeping order fulfillment in its own backend. A return page helps the buyer understand progress; it does not establish that payment succeeded.
APIScout retains editorial control. This guide follows official documentation. The examples are documented, unexecuted adaptations. We have not created a checkout, processed a payment, or tested webhook delivery. Example identifiers and order references are illustrative.
| Integration decision | Use here | Application responsibility |
|---|---|---|
| Where the buyer pays | Hosted checkout link | Send the buyer to the returned URL |
| What establishes payment | Signed server webhook | Match it to the intended order |
| What a return page does | Show progress | Keep access pending until backend confirmation |
| What happens on redelivery | Repeat event may arrive | Avoid repeating fulfillment |
Prepare the account and order
Start with a Whop account and a server-held Account API key. Whop's authentication guide recommends narrowing permissions to the operations your application needs. Keep that key out of browser bundles and source control. Store a separate webhook signing secret for incoming events.
For this example, choose an existing variant and store its ID on your server. Whop's current terminology calls this a variant, although its identifier still starts with plan_. Before opening checkout, create a local pending order and associate it with your application's customer, intended variant and expected payment details. That record gives the webhook handler something to reconcile against.
API versioning matters here. The version changelog records the checkout rename from plan_id to variant_id, and from inline plan to variant. Older examples can therefore use different names legitimately. The following request pins an explicit API version; keep its body and version together.
Create one hosted checkout
The checkout-configuration reference documents POST /checkout_configurations. It accepts an existing variant_id or an inline variant, which are mutually exclusive. Its response includes purchase_url; configuration metadata is copied to payments and memberships.
This server-side JavaScript adaptation uses an existing variant. It assumes you have already persisted the illustrative order and generated an idempotency key for this specific checkout-creation operation. We did not execute it.
const token = process.env.WHOP_API_KEY;
const accountId = process.env.WHOP_ACCOUNT_ID;
const variantId = process.env.WHOP_VARIANT_ID;
const operationKey = process.env.CHECKOUT_OPERATION_KEY;
if (!token || !accountId || !variantId || !operationKey) {
throw new Error("Missing server checkout configuration");
}
const response = await fetch(
"https://api.whop.com/api/v1/checkout_configurations",
{
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
"Api-Version-Date": "2026-11-07",
"Idempotency-Key": operationKey,
},
body: JSON.stringify({
account_id: accountId,
variant_id: variantId,
metadata: { order_id: "demo_order_001" },
}),
},
);
if (!response.ok) throw new Error(`Whop HTTP ${response.status}`);
const checkout = await response.json();
if (typeof checkout.purchase_url !== "string") {
throw new Error("Checkout URL missing");
}
console.log(checkout.purchase_url);
Choose the variant and order reference from trusted server state, rather than accepting a browser-supplied price or arbitrary order ID. Whop's idempotency guide says to reuse the same key when retrying the same operation and use a fresh key for a distinct operation. This guards checkout creation; it does not replace deduplication in your webhook handler.
The example targets production. Whop's quickstart warns that production checkout links take real money. Reading this example establishes neither a test environment nor permission to charge anyone.
To exercise the same request without moving money, send it to the sandbox API base, https://sandbox-api.whop.com/api/v1. The sandbox has its own dashboard at sandbox.whop.com and its own API keys. Whop says the two environments share no accounts, keys, products or webhooks, so the account and variant IDs must also come from the sandbox. Its test card list gives 4242 4242 4242 4242 for a successful payment.
Follow the buyer without trusting the browser
Send the buyer to purchase_url through your application's checkout action. When configuring a return destination, keep its job limited to showing progress and offering a retry path. Read the application's order status from your backend before presenting access as available.
Whop's checkout integration guide explains why navigation and frontend completion callbacks are unsuitable fulfillment triggers: the buyer may close the page, redirects can fail, and URL parameters can be edited. Its specific callback and return-parameter examples describe the embedded Checkout element; they are not assumptions about every hosted-link return flow.
For a delayed outcome, show that confirmation is pending. A positive-looking URL must never unlock a download or customer account by itself.
Verify the webhook before fulfilling
Register an HTTPS endpoint for payment.succeeded and store its signing secret as WHOP_WEBHOOK_SECRET. Whop's webhook guide documents Standard Webhooks signatures and an SDK helper that verifies the raw body before returning the parsed event.
Create a new v1 webhook using Create Webhook: send POST /api/v1/webhooks with your HTTPS url, events: ["payment.succeeded"], and api_version_date: "2026-11-07", matching the checkout request's version pin. Do not send an api_version request field. Check that the created webhook reports api_version: "v1" and the intended api_version_date. The checkout request's REST header does not configure this webhook pin. Webhook versioning independently controls the envelope and payment data; keep that contract aligned with the account and variant reconciliation below.
This TypeScript function illustrates signature verification. It is not a complete request handler, durable queue or fulfillment implementation, and it has not been executed.
import { unwrapWebhook } from "@whop/sdk/helpers";
export async function verifyWhopEvent(request: Request) {
const secret = process.env.WHOP_WEBHOOK_SECRET;
if (!secret) throw new Error("Missing webhook signing secret");
return unwrapWebhook(await request.text(), {
headers: Object.fromEntries(request.headers),
key: secret,
});
}
Reject verification failures. For a verified payment event, reconcile the payment with your pending order, expected account, variant and payment details. Do not grant access solely because metadata contains a familiar order ID. This reconciliation is our implementation recommendation; a valid signature establishes the event's authenticity, not that it belongs to the order you meant to fulfill.
Persist accepted work durably before acknowledging it. Whop documents at-least-once delivery, a repeated webhook-id on retries, and a response requirement of less than five seconds. Use a unique event record and an idempotent order transition so duplicate deliveries cannot issue another entitlement. Queue email or other slow work after durable acceptance. Our webhook failure guide provides broader implementation context.
Choose the next integration step
Keep the hosted link when your immediate requirement is one checkout and backend-controlled fulfillment. Evaluate the Checkout element when you need the checkout embedded, or Payment Elements when you need to own more of the form; Whop documents these as separate integration paths.
Testing needs a separate decision. The sandbox page provides API sandbox configuration and test cards. It also documents Whop Elements in the sandbox: set environment to "sandbox" when you create the Elements instance. We have not run an embedded test checkout, so confirm that path in the sandbox before you rely on it.
This documentation-led guide establishes a design, not an observed payment result. Before release, validate your chosen flow, permission set, signature failures and duplicate handling in an approved environment. For broader provider selection, use our payment API evaluation guide and payments directory. Start implementation with Whop's official quickstart.