Whop runs alongside Coinflow in production — no rip-and-replace. One provider replaces Coinflow for both payins and payouts, with 100+ payment methods and unified seller disbursements. Seven days to first live dollar.
This file gives Cursor and Claude Code full context about your Whop migration. Every file path, schema change, and code example — ready to implement.
Save as CLAUDE.md in your project root. Open Cursor. Say “implement the Whop migration.”
The codebase contains legacy payment code that is no longer active. Understanding what’s live vs dead is critical before making changes.
app/api/coinflow-webhook/route.tsapp/api/onramp/webhook/route.tsapp/lib/stripe.tsWhop runs alongside Coinflow in production. No staging needed, no new dependencies. Routing is controlled by env vars.
PAYMENT_PROVIDER env var defaults to "coinflow". Per-user override: WHOP_TEST_USER_IDS=uuid1,uuid2. All routing lives in one file — app/lib/payments.ts — not scattered across files.Whop client, webhook controller, seller routes, Supabase migration. Coinflow stays default. Deploy with zero behavior change.
Add your admin UUIDs to WHOP_TEST_USER_IDS. Buy packs, purchase CatchCoins, do a cashout — all with real money via Whop.
Add 5–10 trusted users to the test list. Verify pack fulfillment, CatchCoins crediting, seller payouts, and webhook reliability.
Set PAYMENT_PROVIDER=whop globally. Coinflow code stays as fallback until you’re confident. First live dollar.
Coinflow → Whop. All flows go through app/lib/payments.ts for provider routing.
How your existing schemas map to Whop. New columns are added alongside existing ones — nothing removed.
| Your Schema | File / Table | Whop Entity | New Columns |
|---|---|---|---|
profiles |
Supabase — profiles table |
Company (connected account) | whop_company_id TEXT, whop_payout_status VARCHAR(20) |
catchback_transactions |
Supabase — catchback_transactions |
Payment / Transfer | whop_payment_id TEXT, whop_transfer_id TEXT |
cashout_transactions |
Supabase — cashout_transactions |
Transfer / Withdrawal | whop_transfer_id TEXT, whop_withdrawal_id TEXT |
| (new table) | whop_webhook_events |
Idempotency tracking | event_id, event_type, payload |
Side-by-side: Coinflow today vs. the Whop equivalents.
/api/coinflow-webhookwhop.checkoutConfigurations.create() for checkoutwhop.transfers.create() for seller payoutswhop.companies.create() + KYC for enrollment/api/whop/webhookCoinflow webhook events map to Whop events. Both endpoints run simultaneously during transition.
| Coinflow Pattern | Whop Event | What Happens |
|---|---|---|
/api/coinflow-webhook (payment complete) |
payment.succeeded |
Assign cards, credit CatchCoins, create transaction record |
/api/onramp/webhook (onramp complete) |
payment.succeeded |
Same fulfillment — unified under one event |
| Coinflow payout status check | withdrawal.created |
Track seller withdrawal initiation |
| Coinflow KYC status | verification.succeeded |
Auto-update whop_payout_status to “completed” |
| (none) | payment.failed |
Log failure, show retry UI |
/api/coinflow-webhook and /api/onramp/webhook endpoints remain active during the transition. They only become dead code after the global cutover to Whop.Where Whop fits. Orange is new, green stays, gray is legacy dead code. Coinflow and Whop coexist during transition.
┌─────────────────────────────┐
│ CatchBack Web App │
│ Next.js 15 / Vercel │
└──────────────┬──────────────┘
│
┌──────────────▼──────────────┐
│ app/lib/payments.ts │
│ Provider Router (NEW) │
│ PAYMENT_PROVIDER env var │
└───────┬──────────────┬──────┘
│ │
┌────────────────▼───┐ ┌──────▼─────────────────┐
│ Coinflow (active) │ │ Whop (NEW) │
│ ├ Payins │ │ ├ Checkout API │
│ ├ Payouts │ │ ├ Companies API │
│ └ Webhooks │ │ ├ Transfers API │
└────────────────────┘ │ └ Webhooks │
└──────────────────────────┘
┌─────────────────────┐
│ Legacy (dead code) │ ┌──────────────────────────┐
│ ├ Stripe (28 files) │ │ Supabase (PostgreSQL) │
│ └ PayPal (3 files) │ │ Auth, DB, RLS — unchanged│
└─────────────────────┘ └──────────────────────────┘
Tracks seller readiness in profiles.whop_payout_status.
| State | Meaning | Can Do | Blocked |
|---|---|---|---|
| pending | Whop Company created, KYC not started | List cards, earn CatchCoins | Withdraw to bank/crypto |
| in_progress | KYC started but not verified | List cards, earn CatchCoins | Withdraw to bank/crypto |
| completed | KYC verified, payout method added | Everything — list, earn, withdraw | Nothing |
| failed | KYC rejected | List cards, earn CatchCoins | Withdraw — must retry KYC |
One week to first live dollar. Coinflow stays live the entire time.
Most of your stack is unchanged. Whop replaces only the Coinflow payment layer.