Whop × Refr

Payout Integration Guide

Replace Stripe Connect payouts with Whop — 180+ countries, instant cashout, built-in KYC and 1099 compliance. Stripe stays for pay-ins. Side-by-side, no rip-and-replace.

Stripe Connect Payouts → Whop Transfers Stripe KYC → Whop KYC Stripe Pay-ins stay Subscriptions stay No new dependencies

Start Here — Drop This Into Your Repo

This file gives Cursor and Claude Code full context on the payout migration. Every file path, schema change, and TypeScript code example — scoped to payouts only.

Save as CLAUDE.md in your project root. Open Cursor. Say “implement the Whop payout migration.”

Replace Stripe Connect payouts with Whop in the refr-app codebase. PAYOUTS ONLY — Stripe stays for pay-ins, subscriptions, invoices. Key files: src/pages/api/stripe/connect/* (add Whop path alongside Stripe), src/pages/api/stripe/payouts/* (add Whop transfers), src/pages/api/stripe/webhook/connect.ts (add Whop webhook). Create src/lib/whop.ts (API client), src/lib/payout-provider.ts (routing), src/pages/api/whop/webhook.ts (webhook handler). Add payout_provider + whop_company_id columns to accounts table. Remove scheduled make-transfers edge function — payouts are now user-initiated via embedded Whop PayoutsSession. Use PAYOUT_PROVIDER env var for global routing, accounts.payout_provider for per-user override. Stripe stays default until full rollout.

⚙ Rollout Strategy

Whop runs alongside Stripe Connect in production. Stripe handles ALL pay-ins, Whop handles payouts for opted-in users.

ℹ
PAYOUT_PROVIDER env var defaults to "stripe". Per-user override: accounts.payout_provider column. All routing lives in src/lib/payout-provider.ts — one function, not scattered across files.
1

Build

Whop client, webhook handler, migration, both payout paths. Stripe stays default. Deploy with zero behavior change.

2

Internal Test

Set accounts.payout_provider to "whop" on your own test accounts. Transfer real money.

3

New Signups

July 1st: new assignors/referees default to Whop. Existing accounts stay on Stripe Connect.

4

Full Migration

Transition existing accounts over 3–6 months. Stripe Connect path stays as fallback.

⚡ Money Flow

How funds move from organizations to assignors and referees via Whop.

Referee / Assignor Payout

Organization Stripe Pay-in
→
Platform Whop Balance
→
Transfer Ref Wallet
→
User-initiated Withdrawal

Replaces stripe.transfers.create in src/pages/api/stripe/connect/transfers.ts. Scheduled batch edge functions removed — withdrawals are now user-initiated.

Submerchant Onboarding & KYC

Referee Signs up
→
Whop Account Created
→
First Withdrawal KYC Triggered
→
Verified 1099 Compliant

Replaces stripe.accounts.create + stripe.accountLinks.create in src/pages/api/stripe/connect/account.ts. KYC only at first withdrawal — $5K hold limit pre-KYC.

□ Your Code → Whop

How your existing schemas and modules map to Whop. Only payout-related tables change.

Your SchemaFileWhop EntityNew Columns
accountssupabase/migrations/schema_init.sqlCompany (connected account)whop_company_id TEXT, payout_provider TEXT
transactionssupabase/migrations/schema_init.sqlTransfer (ctt_xxx)provider TEXT, status TEXT
profilessupabase/migrations/schema_init.sql—No changes
customerssupabase/migrations/schema_init.sql—No changes (Stripe pay-in)
gamessupabase/migrations/schema_init.sql—No changes (fee logic stays)
New tablemigrationWebhook idempotencywhop_webhook_events

▣ What Changes

Side-by-side: the Stripe Connect calls you have today vs. the Whop equivalents. Only payout routes change.

Stripe Connect (Today)

  • accounts.create — onboard referee
  • accountLinks.create — KYC link
  • transfers.create — send payout
  • accounts.retrieve — check status
  • Scheduled batch edge functions
  • 5-day ACH settlement

Whop (After)

  • POST /companies — create account
  • POST /account-links — KYC link
  • POST /transfers — send payout
  • GET /companies/{id} — check status
  • User-initiated withdrawals
  • 1–3 day settlement (70% within 24h)

⚡ Webhook Mapping

Stripe pay-in webhooks stay unchanged. Only Connect payout events get a Whop equivalent.

Stripe Connect EventWhop EventWhat Happens
account.updatedcompany.createdSet accounts.completed = true after verification
None (batch function)transfer.completedTransfer to referee confirmed
Nonewithdrawal.completedReferee withdrew to bank/crypto
Nonewithdrawal.failedWithdrawal failed — alert user
Nonepayment.succeededPlatform top-up confirmed
ℹ
Three webhook endpoints coexist: /api/stripe/webhook (pay-ins — unchanged), /api/stripe/webhook/connect (Stripe Connect accounts), and /api/whop/webhook (Whop payout events).

▣ Architecture

Where Whop fits. Orange is new, green stays unchanged. Both payout providers coexist.

          ┌────────────────────┐
          │ Organizations      │    PAY-INS (Stripe — unchanged)
          │ (invoices, charges) │
          └─────────┬──────────┘
                    │
          ┌─────────┴──────────┐
          │ Stripe Checkout     │
          │ Invoices, Subs      │
          └─────────┬──────────┘
                    │
          ┌─────────┴──────────┐
          │ Refr Platform       │    PAYOUTS (provider routing)
          │ getPayoutProvider()  │
          └────┬─────────────┬────┘
               │             │
   provider=   │             │   provider=
   "stripe"    │             │   "whop"
               │             │
    ┌───────┴───┐   ┌────┴───────┐
    │ Stripe     │   │ Whop API    │
    │ Connect    │   │ /transfers  │
    └─────┬─────┘   └────┬───────┘
          │                  │
          │             ┌───┴───────┐
          │             │ Ref Wallet  │
          │             │ (user-init) │
          │             └────┬───────┘
          │                  │
    ┌─────┴────────────┴────┐
    │  Assignor / Referee      │
    │  Bank / Crypto / Venmo    │
    └────────────────────────┘

⏰ Timeline — 1 Week

Payouts-only scope keeps this tight. Stripe stays live for pay-ins the entire time.

Day 1–2
Build
  • Whop client + provider routing
  • DB migration (2 cols + 1 table)
  • Webhook handler
  • Deploy — Stripe still default
Day 3–4
Wire & Test
  • Connect account creation + KYC flow
  • Transfer + withdrawal end-to-end
  • Embedded PayoutsSession in finance page
  • Test with real money on internal accounts
Day 5–6
Validate
  • Flip 5–10 trusted assignors to Whop
  • Confirm transfer parity + webhooks
  • Verify Stripe pay-ins still work
Day 7
Go Live
  • New signups default to Whop
  • Existing accounts migrate in waves
  • Stripe Connect stays as fallback

✓ What Stays the Same

Most of your stack is unchanged. Whop replaces only the payout and onboarding layer.

✓ Stripe Checkout
✓ Stripe Invoices
✓ Stripe Subscriptions
✓ Stripe Billing Portal
✓ Next.js 13.5 + React 18
✓ Supabase PostgreSQL
✓ NextAuth + JWT
✓ Netlify hosting
✓ Game scheduling
✓ Fee calculation logic
✓ Yardstik background checks
✓ No new dependencies
~ accounts table (2 new cols)
~ finance page (payout embed)
✓
Bottom line: All pay-in flows (checkout, invoices, subscriptions, billing portal) are completely untouched. Stripe Elements stays. Fee calculation stays. The Whop client uses built-in fetch — no new dependencies.