Whop
Whop takes the payment and keeps the membership, so RoutingCat hears of both from Whop. npx routingcat connect whop connects your Whop company: RoutingCat then receives Whop’s webhooks and turns each into the outcomes it makes, with no webhook code of yours. Your part is the checkout: it carries the visitor id, so that each payment joins the visit that led to it. This guide covers both, and what to keep apart from Whop’s own features. It builds on Track conversions.
Connect your Whop company
The site’s owner runs npx routingcat connect whop once, on their own machine:
- It asks for a Whop API key, from
WHOP_API_KEYor typed at the terminal, never written to disk. Create it in Whop’s dashboard withdeveloper:manage_webhook; the command creates the webhook in your company with it. --reconcilealso hands RoutingCat the key, kept encrypted, so that it can read back payments a failing webhook missed. The key then needspayment:basic:read,member:basic:readandplan:basic:readtoo. Without it, a period Whop failed to deliver can’t be recovered.--provehands the key over once, to prove the company is yours; RoutingCat keeps nothing.--sandboxconnects your Whop sandbox instead of the live company.
It then has Whop send its test event, which RoutingCat verifies and drops, and lists Whop’s own experiments on the company:
$ routingcat connect whop --sandbox --site lumen✓ whop connected biz_8Jk4mWzR2pLs (sandbox) · signature verified Whop's own experiments run on this account, apart from RoutingCat's: Hero copy (hero_copy) since 2026-10-12, on product prod_8Jk4mWzR2pLs Checkout layout (checkout_layout) where one changes a page RoutingCat routes, both tests blur: give each page one owner, or pass RoutingCat's membership to Whop as a targeting propertyUntil Whop’s first delivery proves the company is the one named, the connection waits, as doctor says. npx routingcat connections lists it with its latest delivery.
Pass the visitor id at checkout
Whop copies a checkout configuration’s metadata to the payment and the membership it makes, so your server creates the checkout with the visitor id in it.
Your server creates each checkout with Whop’s API, in whatever language it is written, then sends the buyer to the checkout’s purchase_url. The request, as RoutingCat’s example app makes it:
| Part | Value |
|---|---|
| Request | POST https://api.whop.com/api/v1/checkout_configurations, or https://sandbox-api.whop.com/api/v1/checkout_configurations in Whop’s sandbox |
| Headers | authorization: Bearer <your Whop API key>, api-version-date as below, and content-type: application/json |
| Body | plan_id, the plan’s id; metadata: { "rc_vid": <the rc_vid cookie's value> }, only when the request carries the cookie; and redirect_url, the page the buyer comes back to, with rc_return=whop in its query |
| Answer | purchase_url: redirect the buyer there |
The visitor id is the request’s rc_vid cookie, which RoutingCat sets on your registrable domain, so an app on a subdomain reads it too.
In an Astro endpoint, read it with cookies.get('rc_vid')?.value, and send the buyer on with redirect(purchase_url).
metadata: { rc_vid }, from therc_vidcookie, only when the visitor has one.rc_return=whoponredirect_url. The buyer’s return from Whop’s checkout is then a return, not a new arrival, sosourcesstill credits the purchase to where the visit came from.api-version-date,routingcat/outcomes’WHOP_API_VERSION, today2026-10-09-2: the newest version of Whop’s API that RoutingCat’s mapping reads.- Test in Whop’s sandbox first, at its API address, with the sandbox’s own API key and plan, and the site connected with
npx routingcat connect whop --sandbox: nothing is charged. Go live with the live address, key and plan, and the live connection. - A plain plan link carries no metadata, so a purchase made through one arrives with no visitor to join it to: create every checkout on your server, as above.
What the connection tracks
| Outcome | When |
|---|---|
purchase |
A one-time payment, or a membership’s first payment above zero, after a trial included, marked after_trial |
renewal |
Each later payment of a membership |
trial_started |
A membership that starts with a trial |
cancel_scheduled, cancel_effective |
A membership set to end, and one that has ended |
refund |
A refund that succeeded, as a negative value, or reversed |
dispute |
A dispute’s opening and its end |
Values are in major units, without tax; a payment in a currency that isn’t one of ISO 4217’s counts in US dollars. Declare in outcomes the ones you want reported, purchase at least. Refunds and disputes need no declaring: results link each to the purchase it corrects.
Keep Whop’s features apart
- Whop’s own store pages and its hosted checkout take no code of yours, so RoutingCat can’t route them. Route your own site’s pages, and send the buyer to Whop’s checkout from there.
- No
affiliate_codeor?a=in a variant: it pays a commission and changes Whop’s attribution. - Whop’s own experiments, which
connect whoplists: where one changes a page RoutingCat routes, both blur. Give each page one owner, or keep a visitor out of both.