> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cfosilvia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# REFERRAL SYSTEM

# Referral System Architecture

## Overview

The referral system allows users to invite friends to the platform. Each user gets a unique referral link based on their `clerk_id`. Referrals are tracked and marked as "completed" when the referred user connects their first account (via Plaid or SnapTrade).

## Key Features

* **Simple Link-Based Referrals**: No custom codes needed - uses clerk\_id directly
* **Automatic Tracking**: Tracks signups and account connections automatically
* **Completion Criteria**: Referral is completed when referred user connects an account
* **Statistics Dashboard**: Users can see total signups and completed referrals

## Database Schema

### Table: `referrals`

Tracks all referral relationships and their completion status.

| Column | Type | Description |
| - | - | - |
| `id` | UUID | Primary key |
| `referrer_clerk_id` | TEXT | Clerk ID of the user who shared the link |
| `referred_clerk_id` | TEXT | Clerk ID of the user who signed up (UNIQUE) |
| `signup_completed_at` | TIMESTAMPTZ | When the referred user signed up |
| `is_completed` | BOOLEAN | TRUE when account is connected |
| `created_at` | TIMESTAMPTZ | Record creation timestamp |
| `updated_at` | TIMESTAMPTZ | Last update timestamp |

**Note**: The `referrals` table is the single source of truth. No additional columns needed in `all_users` table.

## API Routes

### 1. GET `/api/referrals/stats`

Get referral statistics for the authenticated user.

**Authentication**: Required (Clerk)

**Response**:

```json theme={null}
{
  "total_signups": 5,
  "completed_referrals": 3,
  "pending_referrals": 2,
  "referrals": [
    {
      "id": "uuid",
      "referred_clerk_id": "user_xxxxx",
      "signup_completed_at": "2025-11-03T10:00:00Z",
      "is_completed": true,
      "created_at": "2025-11-03T10:00:00Z"
    }
  ]
}
```

### 2. POST `/api/referrals/track-signup`

Track a new referral signup. Should be called during user registration when a referral link was used.

**Authentication**: None (called during signup process)

**Request Body**:

```json theme={null}
{
  "referred_clerk_id": "user_xxxxx",
  "referrer_clerk_id": "user_yyyyy"
}
```

**Response**:

```json theme={null}
{
  "success": true,
  "referral_id": "uuid"
}
```

### 3. POST `/api/referrals/mark-completed`

Mark a referral as completed when the referred user connects their first account.

**Authentication**: None (called by system)

**Request Body**:

```json theme={null}
{
  "clerk_id": "user_xxxxx"
}
```

**Response**:

```json theme={null}
{
  "success": true,
  "message": "Referral marked as completed"
}
```

### 4. GET `/api/referrals/validate-referrer?ref=abc123xyz456`

Validate that a referrer exists and get their clerk\_id. Used when someone clicks a referral link.

**Authentication**: None (public endpoint)

**Response**:

```json theme={null}
{
  "valid": true,
  "referrer_clerk_id": "user_xxxxx",
  "referrer_name": "John",
  "message": "You've been referred by John!"
}
```

## Referral Link Generation

### How It Works

Each user gets a **unique random 12-character string** stored in `all_users.referral_link`. This is used in their referral URL instead of exposing their clerk\_id.

```typescript theme={null}
function ReferralSection() {
  const [referralLink, setReferralLink] = useState('')
  
  useEffect(() => {
    // Fetch or generate the user's unique referral link
    async function fetchLink() {
      const response = await fetch('/api/referrals/get-link')
      const data = await response.json()
      setReferralLink(`${window.location.origin}?ref=${data.referral_link}`)
      // Example: https://silvia.com?ref=abc123xyz456
    }
    fetchLink()
  }, [])
  
  return (
    <div>
      <p>Share your referral link:</p>
      <input value={referralLink} readOnly />
      <button onClick={() => navigator.clipboard.writeText(referralLink)}>
        Copy Link
      </button>
    </div>
  )
}
```

### Link Format

```
https://yourapp.com/?ref=abc123xyz456
```

Where `abc123xyz456` is a unique 12-character random string stored in the user's `referral_link` column.

### API: GET `/api/referrals/get-link`

Fetches or generates the user's unique referral link.

**Authentication**: Required (Clerk)

**Response**:

```json theme={null}
{
  "referral_link": "abc123xyz456"
}
```

## Integration Points

### 1. User Signup (Clerk Webhook)

When a new user signs up via a referral link:

1. Store the `ref` parameter from the URL (in localStorage or session)
2. After Clerk creates the user, call `/api/referrals/track-signup` with:
   * `referred_clerk_id`: New user's clerk\_id
   * `referrer_clerk_id`: Value from the `ref` parameter

**Location to integrate**: `app/api/webhooks/clerk/route.ts` (user.created event)

### 2. Account Connection

When a user connects their first account (Plaid or SnapTrade):

Call `/api/referrals/mark-completed` with the user's `clerk_id`.

**Locations to integrate**:

* `app/api/connect-bank/route.ts` (Plaid connection success)
* `app/api/snaptrade/process-connection/route.ts` (SnapTrade connection success)

Example integration:

```typescript theme={null}
// After successful account connection
try {
  await fetch('/api/referrals/mark-completed', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ clerk_id: userId })
  });
} catch (error) {
  // Don't fail the connection if referral tracking fails
  console.error('Failed to mark referral as completed:', error);
}
```

### 3. Settings Page (Frontend)

Display the user's referral link and statistics.

**Location to create**: `app/settings/page.tsx` or a new referrals section

Example component structure:

```typescript theme={null}
// Get user's clerk_id
const { userId } = useAuth();

// Generate referral link
const referralLink = `${window.location.origin}?ref=${userId}`;

// Fetch stats
const { data: stats } = useQuery({
  queryKey: ['referral-stats'],
  queryFn: async () => {
    const res = await fetch('/api/referrals/stats');
    return res.json();
  }
});

// Display:
// - Referral link (with copy button)
// - Total signups: stats.total_signups
// - Completed referrals: stats.completed_referrals
// - Pending referrals: stats.pending_referrals
```

## Implementation Checklist

* [x] Create database migration (`sql-queries/create-referrals-table.sql`)
* [x] Create API routes:
  * [x] `/api/referrals/stats` - Get user's referral statistics
  * [x] `/api/referrals/track-signup` - Track new referral signup
  * [x] `/api/referrals/mark-completed` - Mark referral as completed
  * [x] `/api/referrals/validate-referrer` - Validate referrer exists
* [ ] Integrate with Clerk webhook (track signups)
* [ ] Integrate with Plaid connection (mark completed)
* [ ] Integrate with SnapTrade connection (mark completed)
* [ ] Create frontend UI in Settings page
* [ ] Add referral link sharing functionality
* [ ] Add referral statistics display

## Future Enhancements (TBD)

* Reward system for completed referrals
* Email notifications when referrals complete
* Referral leaderboard
* Custom referral campaigns
* Referral analytics (conversion rates, etc.)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.