# Refgrow -- LLM Integration Context

> Refgrow is a SaaS platform for creating affiliate and referral programs. It provides an embeddable widget, tracking scripts, REST API, webhook system, CLI, and MCP server. Supports Stripe, LemonSqueezy, Paddle, Polar, and Dodo Payments as payment providers. This document provides complete context for AI coding assistants to integrate Refgrow into any web application. Last updated: 2026-05-13.

## Machine-Readable Pages

Every public page on refgrow.com is also available as plain Markdown by appending `.md` to its URL. Works for docs, blog posts, comparison pages, glossary, calculators, marketing pages, anything that doesn't require auth.

Examples:

- https://refgrow.com/docs/cli.md
- https://refgrow.com/docs/api-reference.md
- https://refgrow.com/docs/widget.md
- https://refgrow.com/docs/mcp-server.md
- https://refgrow.com/pricing.md
- https://refgrow.com/blog/post-slug.md
- https://refgrow.com/alternative/rewardful.md
- https://refgrow.com/affiliate-marketing-glossary.md

Pull just the page you need; same content as the rendered HTML without chrome. Lower-token alternative to scraping the live site.

Dashboard and other private pages (settings, billing, dashboard, portal, etc.) return 404 in markdown form by design.

For the developer surface that AI agents can drive directly:

- REST API v1: https://refgrow.com/docs/api-reference.md (Bearer `rgk_` keys)
- OpenAPI 3.1 spec: https://refgrow.com/api/v1/openapi.json (import into ChatGPT Custom GPT Actions, Postman, Bruno, etc.)
- CLI: `npm install -g @refgrow/cli` -> https://refgrow.com/docs/cli.md
- MCP server: `npx @refgrow/mcp` -> https://refgrow.com/docs/mcp-server.md

---

## Table of Contents

1. [What is Refgrow?](#what-is-refgrow)
2. [Quick Integration (4 Steps)](#quick-integration)
3. [Tracking Script -- Detailed Setup](#tracking-script)
4. [Affiliate Dashboard Widget](#affiliate-dashboard-widget)
5. [Payment Provider Integration](#payment-provider-integration)
   - [Stripe](#stripe-integration)
   - [LemonSqueezy](#lemonsqueezy-integration)
   - [Paddle](#paddle-integration)
   - [Polar](#polar-integration)
   - [Dodo Payments](#dodo-integration)
6. [REST API Reference](#rest-api-reference)
   - [Authentication](#api-authentication)
   - [Affiliates](#affiliates-api)
   - [Conversions](#conversions-api)
   - [Referrals](#referrals-api)
   - [Coupons](#coupons-api)
   - [Error Handling](#error-handling)
   - [Rate Limits](#rate-limits)
7. [Webhook Events](#webhook-events)
8. [Widget Customization](#widget-customization)
9. [Affiliate Portal](#affiliate-portal)
10. [Messages](#messages)
11. [MCP Server](#mcp-server)
12. [Framework Integration Examples](#framework-integration-examples)
13. [Troubleshooting](#troubleshooting)

---

## What is Refgrow?

Refgrow is an affiliate/referral program platform for SaaS businesses. It lets you:

- Add a tracking script to detect referral clicks and set cookies
- Embed an affiliate dashboard widget where affiliates track performance and earnings
- Automatically track conversions via webhook integrations with Stripe, LemonSqueezy, Paddle, and Polar
- Manage affiliates, referrals, conversions, and coupons via REST API
- Use an MCP server for AI-assisted affiliate program management
- Configure commissions (percentage or fixed), per-product and per-affiliate overrides
- Pay affiliates via PayPal, Wise, or manually
- Host an Affiliate Portal at {slug}.refgrow.com (or your custom domain) as an alternative to the embedded widget
- Send Messages to affiliates directly from the dashboard
- Support 9 languages out of the box

Website: https://refgrow.com
Docs: https://refgrow.com/docs
API Base URL: https://refgrow.com/api/v1

---

## Quick Integration

### Step 1: Add Tracking Script

Add to the `<head>` of all pages:

```html
<script
  src="https://scripts.refgrowcdn.com/latest.js"
  data-project-id="YOUR_PROJECT_ID"
  async defer>
</script>
```

Replace `YOUR_PROJECT_ID` with your actual project ID from the Refgrow dashboard.

### Step 2: Embed Affiliate Dashboard

Add where you want the affiliate dashboard to appear:

**With user email (user is logged in):**

```html
<div id="refgrow"
  data-project-id="YOUR_PROJECT_ID"
  data-project-email="user@example.com">
</div>
<script src="https://scripts.refgrowcdn.com/page.js" async defer></script>
```

**Without user email (standalone affiliate page):**

```html
<div id="refgrow"
  data-project-id="YOUR_PROJECT_ID">
</div>
<script src="https://scripts.refgrowcdn.com/page.js" async defer></script>
```

### Step 3: Track User Registrations (Optional)

After successful user signups, call:

```javascript
Refgrow(0, 'signup', 'user@example.com');
```

### Step 4: Connect Payment Provider

Choose your payment provider in the Refgrow dashboard Integration tab:
- **Stripe** -- Automatic webhook setup. Enter your Stripe Secret Key.
- **LemonSqueezy** -- Create webhook at `https://refgrow.com/webhook/lemonsqueezy/YOUR_PROJECT_ID`
- **Paddle** -- Create webhook at `https://refgrow.com/webhook/paddle/YOUR_PROJECT_ID`
- **Polar** -- Create webhook at `https://refgrow.com/webhook/polar/YOUR_PROJECT_ID`
- **Manual tracking** -- Use `Refgrow(amount, 'purchase', 'email')` or the REST API

---

## Tracking Script

### Script URL

```
https://scripts.refgrowcdn.com/latest.js
```

### Data Attributes

| Attribute           | Default         | Description                                    |
|---------------------|-----------------|------------------------------------------------|
| `data-project-id`   | (required)      | Your Refgrow project ID                        |
| `data-param`        | `ref`           | URL parameter name for the referral code       |
| `data-cookie-days`  | `90`            | Cookie expiration in days                      |
| `data-cookie-domain`| Current domain  | Cookie domain for cross-subdomain tracking     |

### Example with Custom Options

```html
<script
  src="https://scripts.refgrowcdn.com/latest.js"
  data-project-id="YOUR_PROJECT_ID"
  data-param="via"
  data-cookie-days="30"
  data-cookie-domain=".yoursite.com"
  async defer>
</script>
```

With this configuration, referral links use `?via=CODE` instead of `?ref=CODE`, cookies expire after 30 days, and the cookie is shared across all subdomains of `yoursite.com`.

### What the Tracking Script Does

- Detects when users arrive via referral links (`?ref=CODE`)
- Stores the referral code in a first-party cookie
- Enables manual conversion tracking via the `Refgrow()` function
- Provides helper methods for Stripe Payment Links and Paddle/LemonSqueezy links

### Manual Conversion Tracking

```javascript
// Track a signup (no monetary value)
Refgrow(0, 'signup', 'user@example.com');

// Track a purchase (with monetary value)
Refgrow(49.99, 'purchase', 'user@example.com');
```

Parameters:
1. `value` (number) -- Monetary value (use 0 for non-monetary events)
2. `type` (string) -- Event type ('signup', 'purchase', or custom)
3. `email` (string) -- User's email (used for attribution)

### Reading the Referral Cookie (Client-Side)

```javascript
function getRefgrowRef() {
  const match = document.cookie.match(
    /(?:^|;\s*)ref=([^;]*)/
  );
  return match ? decodeURIComponent(match[1]) : null;
}

const referralCode = getRefgrowRef();
if (referralCode) {
  console.log('Referred by:', referralCode);
}
```

### Server-Side Cookie Reading (Node.js/Express)

```javascript
app.post('/signup', async (req, res) => {
  const referralCode = req.cookies.ref;

  if (referralCode) {
    await fetch('https://refgrow.com/api/store-attribution', {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer rgk_YOUR_API_KEY',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        email: req.body.email,
        referral_code: referralCode
      })
    });
  }
});
```

### Cross-Domain Tracking

**Same root domain** (e.g., `yoursite.com` and `app.yoursite.com`):

```html
data-cookie-domain=".yoursite.com"
```

**Different domains:** Configure your tracking domain in Refgrow project settings. The tracking script will append the referral code as a URL parameter when users navigate between domains.

### Content Security Policy (CSP)

If your site uses CSP headers:

```
Content-Security-Policy:
  script-src 'self' https://scripts.refgrowcdn.com https://refgrow.com;
  connect-src 'self' https://refgrow.com;
```

### Privacy & GDPR

The tracking script sets a first-party cookie scoped to your domain. It does not use third-party cookies, fingerprinting, or cross-site tracking. The cookie contains only the referral code and is not used for advertising. You can load the script conditionally after cookie consent.

---

## Affiliate Dashboard Widget

### Script URL

```
https://scripts.refgrowcdn.com/page.js
```

### Data Attributes

| Attribute            | Required    | Description                                           |
|----------------------|-------------|-------------------------------------------------------|
| `data-project-id`    | Yes         | Your Refgrow project ID                               |
| `data-project-email` | Recommended | Current user's email for auto-login                   |
| `data-lang`          | No          | Language code (e.g., `en`, `de`, `fr`). Auto-detected. |

### With User Authentication

```html
<div id="refgrow"
    data-project-id="YOUR_PROJECT_ID"
    data-project-email="user@example.com"
    data-lang="en">
</div>
<script src="https://scripts.refgrowcdn.com/page.js" async defer></script>
```

### Without User Authentication

```html
<div id="refgrow"
    data-project-id="YOUR_PROJECT_ID"
    data-lang="en">
</div>
<script src="https://scripts.refgrowcdn.com/page.js" async defer></script>
```

Users will need to enter their email and verify it to access the dashboard.

### Programmatic Control

```javascript
// Identify a user after login
Refgrow.identify('user@example.com');

// Switch language
Refgrow.setLanguage('de');

// Listen for events
Refgrow.on('affiliate:signup', (data) => {
  console.log('New affiliate signed up:', data.email);
});
```

### Supported Languages

English (en), German (de), Spanish (es), French (fr), Italian (it), Portuguese (pt), Romanian (ro), Russian (ru), Ukrainian (uk).

### Widget Blocks

The widget is composed of configurable blocks. Enable, disable, and reorder from project settings.

Available blocks:
- `header` -- program title and description
- `share_links` -- referral URL with copy button
- `coupon_code` -- affiliate's assigned coupon code
- `stats` -- click count, referral count, conversion metrics
- `daily_stats` -- daily performance chart
- `earnings` -- total and pending commission amounts
- `payment_methods` -- payout configuration
- `payment_history` -- past payouts with status
- `commission_levels` -- multilevel commission progress (paid plans)
- `multi_tier` -- sub-affiliate earnings (paid plans)
- `promotional_materials` -- banners, text links, social share templates

Block configuration format (stored in `projects.widget_blocks_config`):

```json
[
  { "id": "header", "enabled": true, "order": 1 },
  { "id": "share_links", "enabled": true, "order": 2 },
  { "id": "coupon_code", "enabled": true, "order": 3 },
  { "id": "stats", "enabled": true, "order": 4 },
  { "id": "daily_stats", "enabled": true, "order": 5 },
  { "id": "earnings", "enabled": true, "order": 6 },
  { "id": "payment_methods", "enabled": true, "order": 7 },
  { "id": "payment_history", "enabled": false, "order": 8 },
  { "id": "commission_levels", "enabled": false, "order": 9 },
  { "id": "multi_tier", "enabled": false, "order": 10 },
  { "id": "promotional_materials", "enabled": false, "order": 11 }
]
```

### Widget Appearance

Customizable in project settings:
- Primary Color (buttons and highlights)
- Secondary Color (secondary elements and accents)
- Font Color (text color)
- Title (headline text)
- Description (program explanation)

On paid plans (Starter and above), the "Powered by Refgrow" footer can be removed.

---

## Payment Provider Integration

### Stripe Integration

Webhook URL: `https://refgrow.com/webhook/stripe/{your-project-id}` (auto-configured)

#### Setup

1. Go to project's "Integration" tab
2. Select "Stripe Webhooks" as tracking method
3. Enter your Stripe Secret Key (restricted key recommended)
4. Click "Connect Stripe"
5. Refgrow auto-configures the webhook endpoint in your Stripe account

#### Passing Referral Codes to Stripe

**For Stripe Checkout Sessions:**

```javascript
const refCode = req.cookies.refgrow_ref_code;

const session = await stripe.checkout.sessions.create({
  // ... other session parameters
  metadata: {
    referral_code: refCode || null
  }
});
```

**For Stripe Payment Links (automatic):**

```html
<a href="https://buy.stripe.com/xyz..."
   class="refgrow-stripe-payment-link">
  Buy Now
</a>
```

```javascript
if (window.Refgrow) {
  Refgrow.processStripePaymentLinks();
}
```

**For Stripe Payment Links (programmatic redirect):**

```javascript
if (window.Refgrow) {
  Refgrow.redirectToStripePaymentLink('https://buy.stripe.com/xyz...');
}
```

#### Attribution Priority (Stripe)

Refgrow checks these in order:
1. Coupon / promotion code match (most reliable)
2. `session.metadata.referral_code`
3. `client_reference_id` on checkout session
4. Subscription metadata
5. Email fallback via `referral_attributions` table

#### Supported Stripe Webhook Events

- `checkout.session.completed` -- purchase completed
- `invoice.paid` -- subscription invoice paid
- `customer.subscription.created` -- new subscription
- `customer.subscription.updated` -- plan changes, renewals
- `customer.discount.created` -- coupon applied (renewal tracking)
- `charge.refunded` -- charge refunded

#### Commission Configuration

Commission priority:
1. Affiliate-specific override (highest priority)
2. Product-specific commission
3. Project default commission (fallback)

Commission types: Percentage or Fixed Amount
Commission duration: Lifetime, First Purchase, or Limited Period

For subscriptions:
- Commission on initial payment
- Optional recurring commissions on renewals
- Additional commission on upgrades
- Automatic reversal on refunds/cancellations

---

### LemonSqueezy Integration

Webhook URL: `https://refgrow.com/webhook/lemonsqueezy/YOUR_PROJECT_ID`

#### Setup

1. Go to LemonSqueezy Dashboard > Settings > Webhooks
2. Click "Create Webhook"
3. Set URL to `https://refgrow.com/webhook/lemonsqueezy/YOUR_PROJECT_ID`
4. Enable events: `order_created`, `subscription_created`, `subscription_payment_succeeded`
5. Copy webhook secret and save in Refgrow project Integration tab

#### Passing Referral Codes

**Automatic (recommended):** Add class to checkout links:

```html
<a href="https://your-store.lemonsqueezy.com/checkout/buy/abc123"
   class="refgrow-lemonsqueezy-link">Buy Now</a>
```

The tracking script will automatically append `checkout[custom][referral_code]=CODE`.

**Manual URL parameter:**

```html
<a href="https://your-store.lemonsqueezy.com/checkout/buy/abc123?checkout[custom][referral_code]=ALEX123">Buy Now</a>
```

**Programmatic API:**

```javascript
const checkoutData = {
  custom: {
    referral_code: 'ALEX123'
  }
};
```

**Via discount codes:** Create discount codes in LemonSqueezy, link them to affiliates in Refgrow's Coupons tab.

For dynamically added links, call `Refgrow.processLemonSqueezyLinks()`.

#### Supported LemonSqueezy Webhook Events

- `order_created` -- one-time purchase completed
- `subscription_created` -- new subscription
- `subscription_payment_succeeded` -- subscription payment processed

---

### Paddle Integration

Webhook URL: `https://refgrow.com/webhook/paddle/{your-project-id}`

#### Setup

1. Go to project's "Integration" tab, select "Paddle Webhooks"
2. Copy the webhook URL
3. In Paddle dashboard, create webhook with that URL
4. Enable events: `transaction.completed`, `subscription.created`, `subscription.updated`
5. Copy Paddle webhook signing secret, paste in Refgrow

#### Passing Referral Codes

**For Paddle Checkout:**

```javascript
const refCode = req.cookies.refgrow_ref_code;

const checkout = await paddle.checkouts.create({
  custom_data: {
    referral_code: refCode || null
  }
});
```

**For Paddle Payment Links:**

```html
<a href="https://buy.paddle.com/product/xyz..." class="refgrow-paddle-link">Buy Now</a>
```

```javascript
if (window.Refgrow) {
  Refgrow.processPaddleLinks();
}
```

#### Supported Paddle Webhook Events

- `transaction.completed` -- purchase completed
- `subscription.created` -- new subscription
- `subscription.updated` -- subscription updated

---

## REST API Reference

### API Authentication

Base URL: `https://refgrow.com/api/v1`

All requests require a Bearer token. API keys have the prefix `rgk_` and are generated from project settings under "API Keys". Keys are stored hashed (bcrypt). Never expose in client-side code. All requests must use HTTPS.

```
Authorization: Bearer rgk_YOUR_API_KEY
```

Example headers:

```javascript
const headers = {
  'Authorization': 'Bearer rgk_YOUR_API_KEY',
  'Content-Type': 'application/json'
};
```

---

### Affiliates API

#### List Affiliates

```
GET /api/v1/affiliates
```

Query parameters:

| Parameter | Type    | Required | Description                                    |
|-----------|---------|----------|------------------------------------------------|
| `limit`   | integer | Optional | Number of affiliates to return (default: 20)   |
| `offset`  | integer | Optional | Pagination offset (default: 0)                 |
| `status`  | string  | Optional | Filter by status ('active', 'inactive')        |

Example request:

```bash
curl -X GET "https://refgrow.com/api/v1/affiliates?limit=10&status=active" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```javascript
const response = await fetch(
  'https://refgrow.com/api/v1/affiliates?limit=10&status=active',
  {
    headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
  }
);
const data = await response.json();
```

Example response (200 OK):

```json
{
  "success": true,
  "data": [
    {
      "id": 123,
      "user_email": "affiliate1@example.com",
      "referral_code": "REF123",
      "created_at": "2024-01-15T10:00:00.000Z",
      "status": "active",
      "clicks": 58,
      "signups": 12,
      "purchases": 5,
      "unpaid_earnings": "50.00",
      "total_earnings": "150.00",
      "eligible_earnings": "35.00",
      "held_earnings": "15.00",
      "next_release_date": "2024-02-15T10:00:00.000Z"
    }
  ],
  "pagination": {
    "limit": 10,
    "offset": 0,
    "total": 55,
    "has_more": true
  }
}
```

Hold period fields (when project has hold period configured):

| Field                | Type                  | Description                                    |
|----------------------|-----------------------|------------------------------------------------|
| `eligible_earnings`  | string                | Earnings past hold period, available for payout |
| `held_earnings`      | string                | Earnings still within hold period               |
| `next_release_date`  | string (ISO) or null  | When next batch of held earnings becomes eligible |

Note: `total_earnings` = `eligible_earnings` + `held_earnings` + `paid_earnings`

#### Create Affiliate

```
POST /api/v1/affiliates
```

Request body:

| Parameter      | Type   | Required | Description                                       |
|----------------|--------|----------|---------------------------------------------------|
| `email`        | string | Yes      | Email address. Must be unique per project.         |
| `referral_code`| string | Optional | Custom referral code. Auto-generated if omitted.   |

Example request:

```bash
curl -X POST "https://refgrow.com/api/v1/affiliates" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "new.affiliate@example.com",
    "referral_code": "NEWCODE"
  }'
```

Example response (201 Created):

```json
{
  "success": true,
  "data": {
    "id": 124,
    "user_email": "new.affiliate@example.com",
    "referral_code": "NEWCODE",
    "unpaid_earnings": null,
    "total_earnings": null,
    "created_at": "2024-07-29T12:30:00.000Z",
    "status": "active"
  }
}
```

Error responses: `400` Invalid email or parameters. `409` Email or referral code already exists.

#### Retrieve Affiliate

```
GET /api/v1/affiliates/:email
```

The email must be URL-encoded.

```bash
curl -X GET "https://refgrow.com/api/v1/affiliates/affiliate1%40example.com" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Example response (200 OK):

```json
{
  "success": true,
  "data": {
    "id": 123,
    "user_email": "affiliate1@example.com",
    "referral_code": "REF123",
    "created_at": "2024-01-15T10:00:00.000Z",
    "status": "active",
    "clicks": 58,
    "signups": 12,
    "purchases": 5,
    "unpaid_earnings": "50.00",
    "total_earnings": "150.00"
  }
}
```

Error responses: `400` Invalid email format. `404` Affiliate not found.

#### Update Affiliate

```
PUT /api/v1/affiliates/:email
```

Updatable fields:

| Parameter      | Type   | Description                              |
|----------------|--------|------------------------------------------|
| `email`        | string | New email address                        |
| `referral_code`| string | New unique referral code                 |
| `status`       | string | 'active' or 'inactive'                   |

```bash
curl -X PUT "https://refgrow.com/api/v1/affiliates/affiliate1%40example.com" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status": "inactive"}'
```

Error responses: `400` Invalid parameters. `404` Not found. `409` Conflict.

#### Delete Affiliate

```
DELETE /api/v1/affiliates/:email
```

Permanently deletes an affiliate and all associated data. Irreversible.

```bash
curl -X DELETE "https://refgrow.com/api/v1/affiliates/affiliate1%40example.com" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Returns `204 No Content` on success.

---

### Conversions API

#### List Conversions

```
GET /api/v1/conversions
```

Query parameters:

| Parameter         | Type           | Required | Description                                    |
|-------------------|----------------|----------|------------------------------------------------|
| `limit`           | integer        | Optional | Number to return (default: 50)                 |
| `offset`          | integer        | Optional | Pagination offset (default: 0)                 |
| `type`            | string         | Optional | Filter: `signup` or `purchase`                 |
| `affiliate_id`    | integer        | Optional | Filter by affiliate ID                         |
| `referred_user_id`| integer        | Optional | Filter by referred user ID                     |
| `paid`            | boolean        | Optional | Filter by payout status                        |
| `from`            | string (ISO)   | Optional | Filter after this date                         |
| `to`              | string (ISO)   | Optional | Filter before this date                        |

Example request:

```bash
curl -X GET "https://refgrow.com/api/v1/conversions?type=purchase&affiliate_id=123&paid=true" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Example response (200 OK):

```json
{
  "success": true,
  "data": [
    {
      "id": 1001,
      "type": "purchase",
      "affiliate_id": 123,
      "referred_user_id": 501,
      "value": 12.5,
      "base_value": 250,
      "base_value_currency": "USD",
      "paid": false,
      "created_at": "2024-07-29T13:00:00.000Z",
      "reference": "ORDER-123",
      "coupon_code_used": "SUMMER2024"
    }
  ],
  "pagination": {
    "limit": 50,
    "offset": 0,
    "total": 2,
    "has_more": false
  }
}
```

#### Create Conversion

```
POST /api/v1/conversions
```

Request body:

| Parameter            | Type    | Required | Description                                    |
|----------------------|---------|----------|------------------------------------------------|
| `type`               | string  | Yes      | `signup` or `purchase`                         |
| `affiliate_id`       | integer | Optional | Affiliate ID (for attributed conversions)      |
| `referral_code`      | string  | Optional | Referral code to look up affiliate             |
| `referred_user_id`   | integer | Optional | Referred user ID                               |
| `email`              | string  | Optional | Customer email (for webhook payloads)          |
| `value`              | number  | Optional | Commission value (auto-calculated if omitted)  |
| `base_value`         | number  | Optional | Original transaction value                     |
| `base_value_currency`| string  | Optional | Currency code (e.g., USD, EUR)                 |
| `paid`               | boolean | Optional | Payout status (default: false)                 |
| `reference`          | string  | Optional | Custom reference (e.g., order ID)              |
| `coupon_code_used`   | string  | Optional | Coupon code used                               |

Also triggers `referral_converted` and `referral_updated` webhook events automatically.

Example request:

```bash
curl -X POST "https://refgrow.com/api/v1/conversions" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "purchase",
    "affiliate_id": 123,
    "base_value": 250,
    "base_value_currency": "USD",
    "reference": "ORDER-123"
  }'
```

```javascript
const response = await fetch('https://refgrow.com/api/v1/conversions', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    type: 'purchase',
    affiliate_id: 123,
    base_value: 250,
    base_value_currency: 'USD',
    reference: 'ORDER-123'
  })
});

const result = await response.json();
```

Example response (201 Created):

```json
{
  "success": true,
  "data": {
    "id": 1002,
    "type": "purchase",
    "affiliate_id": 123,
    "referred_user_id": 501,
    "value": 12.5,
    "base_value": 250,
    "base_value_currency": "USD",
    "paid": false,
    "created_at": "2024-07-29T13:05:00.000Z",
    "reference": "ORDER-123",
    "coupon_code_used": null
  }
}
```

Error responses: `400` Invalid parameters. `404` Affiliate/user not found. `409` Duplicate conversion.

#### Retrieve Conversion

```
GET /api/v1/conversions/:id
```

```bash
curl -X GET "https://refgrow.com/api/v1/conversions/1002" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

#### Update Conversion

```
PUT /api/v1/conversions/:id
```

Triggers `referral_updated` webhook event.

Updatable fields:

| Parameter            | Type    | Description                    |
|----------------------|---------|--------------------------------|
| `value`              | number  | Commission value               |
| `base_value`         | number  | Original transaction value     |
| `type`               | string  | `signup` or `purchase`         |
| `paid`               | boolean | Payout status                  |
| `reference`          | string  | Custom reference               |
| `coupon_code_used`   | string  | Coupon code used               |
| `base_value_currency`| string  | Currency code                  |

```bash
curl -X PUT "https://refgrow.com/api/v1/conversions/1002" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"paid": true}'
```

#### Delete Conversion

```
DELETE /api/v1/conversions/:id
```

Permanently deletes a conversion. Irreversible.

```bash
curl -X DELETE "https://refgrow.com/api/v1/conversions/1002" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Returns `204 No Content` on success.

---

### Referrals API

#### List Referrals

```
GET /api/v1/referrals
```

Query parameters:

| Parameter      | Type    | Required | Description                                         |
|----------------|---------|----------|-----------------------------------------------------|
| `limit`        | integer | Optional | Number to return (default: 20)                      |
| `offset`       | integer | Optional | Pagination offset (default: 0)                      |
| `affiliate_id` | integer | Optional | Filter by affiliate ID                              |
| `status`       | string  | Optional | 'pending', 'converted', 'direct', 'direct_signup'   |

```bash
curl -X GET "https://refgrow.com/api/v1/referrals?affiliate_id=123&status=converted" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Example response (200 OK):

```json
{
  "success": true,
  "data": [
    {
      "id": 501,
      "user_email": "customer1@example.com",
      "conversion_status": "converted",
      "conversion_date": "2024-02-10T11:05:00.000Z",
      "created_at": "2024-02-01T09:00:00.000Z",
      "affiliate_id": 123,
      "affiliate_code": "REF123"
    }
  ],
  "pagination": {
    "limit": 20,
    "offset": 0,
    "total": 5,
    "has_more": false
  }
}
```

#### Create Referral

```
POST /api/v1/referrals
```

Request body:

| Parameter      | Type          | Required | Description                                         |
|----------------|---------------|----------|-----------------------------------------------------|
| `email`        | string        | Yes      | Referred user's email. Unique per project.           |
| `affiliate_id` | integer       | Optional | Referring affiliate ID. Omit for direct signup.      |
| `status`       | string        | Optional | 'pending', 'converted', 'direct', 'direct_signup'   |

```bash
curl -X POST "https://refgrow.com/api/v1/referrals" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "manual.customer@example.com",
    "affiliate_id": 123,
    "status": "converted"
  }'
```

Example response (201 Created):

```json
{
  "success": true,
  "data": {
    "id": 502,
    "user_email": "manual.customer@example.com",
    "affiliate_id": 123,
    "conversion_status": "converted",
    "conversion_date": "2024-07-29T13:00:00.000Z",
    "created_at": "2024-07-29T13:00:00.000Z"
  }
}
```

Error responses: `400` Invalid email. `404` Specified affiliate_id not found. `409` Email already exists.

#### Retrieve Referral

```
GET /api/v1/referrals/:email
```

Email must be URL-encoded.

```bash
curl -X GET "https://refgrow.com/api/v1/referrals/customer1%40example.com" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

#### Update Referral

```
PUT /api/v1/referrals/:email
```

Updatable fields:

| Parameter      | Type            | Description                                         |
|----------------|-----------------|-----------------------------------------------------|
| `email`        | string          | New email address                                   |
| `affiliate_id` | integer or null | Change affiliate or set null to disassociate         |
| `status`       | string          | Setting to 'converted'/'direct' updates conversion_date |

```bash
curl -X PUT "https://refgrow.com/api/v1/referrals/manual.customer%40example.com" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"affiliate_id": null, "status": "direct"}'
```

---

### Coupons API

#### List Coupons

```
GET /api/v1/coupons
```

Returns all coupons associated with affiliates. Supports pagination and filtering by status, affiliate_id, or coupon_code search.

#### Create Coupon

```
POST /api/v1/coupons
```

Request body:

```json
{
  "affiliate_id": 42,
  "coupon_code": "JANE20",
  "stripe_coupon_id": "promo_xxx",
  "lemonsqueezy_discount_code": "LS_DISC_123",
  "status": "active"
}
```

| Parameter                    | Type    | Required | Description                              |
|------------------------------|---------|----------|------------------------------------------|
| `affiliate_id`               | integer | Yes      | Affiliate to link coupon to              |
| `coupon_code`                | string  | Yes      | Coupon code (min 3 chars)                |
| `stripe_coupon_id`           | string  | Optional | Stripe coupon ID for auto-attribution    |
| `lemonsqueezy_discount_code` | string  | Optional | LemonSqueezy discount code               |
| `status`                     | string  | Optional | 'active' or 'inactive' (default: active) |

#### Retrieve Coupon

```
GET /api/v1/coupons/:id
```

#### Update Coupon

```
PUT /api/v1/coupons/:id
```

#### Delete Coupon

```
DELETE /api/v1/coupons/:id
```

Permanently deletes a coupon. If linked to Stripe, also deleted from Stripe.

---

### Stripe Customer Referral Info

```
GET /api/v1/projects/:projectId/stripe-customer-referral-info/:stripeCustomerId
```

Get referral information for a Stripe customer within a project.

---

### Error Handling

Error response format:

```json
{
  "success": false,
  "error": "Affiliate not found"
}
```

| Status | Meaning                              |
|--------|--------------------------------------|
| `200`  | Success                              |
| `201`  | Created                              |
| `204`  | Deleted (no content)                 |
| `400`  | Bad request (missing/invalid params) |
| `401`  | Unauthorized (invalid/missing API key)|
| `403`  | Forbidden (no permission)            |
| `404`  | Resource not found                   |
| `409`  | Conflict (duplicate resource)        |
| `429`  | Rate limited                         |
| `500`  | Internal server error                |

### Rate Limits

- 100 requests per minute per API key

Rate limit headers in every response:
- `X-RateLimit-Limit` -- requests allowed per window
- `X-RateLimit-Remaining` -- requests remaining
- `X-RateLimit-Reset` -- Unix timestamp when window resets

---

## Webhook Events

Refgrow sends HTTP POST notifications about events in your affiliate program. All webhooks are signed with HMAC-SHA256.

### Setup

1. Go to Project Settings > "Webhooks" tab
2. Click "Add Webhook"
3. Enter endpoint URL (e.g., `https://yourapp.com/webhooks/refgrow`)
4. Select events to receive
5. Optional: Generate a secret key for signature verification
6. Save

### Supported Events

| Event                 | Description                          | Trigger                              |
|-----------------------|--------------------------------------|--------------------------------------|
| `referral_signed_up`  | New user signed up via referral      | User registers through referral link |
| `referral_converted`  | Referral converted to paying customer| Referred user makes a purchase       |
| `referral_canceled`   | Conversion canceled or refunded      | Payment refunded or canceled         |
| `referral_updated`    | Conversion updated or modified       | Conversion created/updated via API   |

### Request Headers

```
Content-Type: application/json
User-Agent: Refgrow-Webhooks/1.0
X-Refgrow-Event: referral_converted
X-Refgrow-Signature: sha256=abc123...
```

### Payload: referral_signed_up

```json
{
  "event": "referral_signed_up",
  "timestamp": 1703123456,
  "project_id": "123",
  "referrer": {
    "id": "456",
    "email": "affiliate@example.com",
    "payout_preferences": {
      "paypal_email": "affiliate@example.com",
      "wise_details": {
        "accountId": "wise_account_123",
        "email": "affiliate@example.com"
      }
    }
  },
  "referred": {
    "id": "789",
    "email": "customer@example.com"
  },
  "data": {
    "referral_code": "REF123",
    "signup_date": "2024-01-15T10:00:00Z",
    "user_agent": "Mozilla/5.0...",
    "ip_address": "192.168.1.1"
  }
}
```

### Payload: referral_converted

```json
{
  "event": "referral_converted",
  "timestamp": 1703123456,
  "project_id": "123",
  "referrer": {
    "id": "456",
    "email": "affiliate@example.com",
    "payout_preferences": {
      "paypal_email": "affiliate@example.com",
      "wise_details": {
        "accountId": "wise_account_123",
        "email": "affiliate@example.com"
      }
    }
  },
  "referred": {
    "id": "789",
    "email": "customer@example.com"
  },
  "conversion": {
    "id": "conv_123",
    "amount": 99.99,
    "currency": "USD",
    "commission_amount": 19.99,
    "commission_type": "percentage",
    "commission_rate": 20,
    "payment_processor": "stripe",
    "product_id": "prod_abc123",
    "order_id": "order_456",
    "conversion_date": "2024-01-15T10:30:00Z"
  }
}
```

### Payload: referral_canceled

```json
{
  "event": "referral_canceled",
  "timestamp": 1703123456,
  "project_id": "123",
  "referrer": {
    "id": "456",
    "email": "affiliate@example.com",
    "payout_preferences": { ... }
  },
  "referred": {
    "id": "789",
    "email": "customer@example.com"
  },
  "conversion": {
    "id": "conv_123",
    "amount": 99.99,
    "commission_amount": 19.99,
    "refund_amount": 99.99,
    "reason": "Customer requested refund",
    "canceled_date": "2024-01-16T14:20:00Z"
  }
}
```

### Payload: referral_updated

```json
{
  "event": "referral_updated",
  "timestamp": 1703123456,
  "project_id": "123",
  "referrer": {
    "id": "456",
    "email": "affiliate@example.com",
    "payout_preferences": { ... }
  },
  "referred": {
    "id": "789",
    "email": "customer@example.com"
  },
  "conversion": {
    "id": "conv_123",
    "amount": 99.99,
    "amount_usd": 19.99,
    "commission_amount": 19.99,
    "base_value": 99.99,
    "conversion_date": "2024-01-15T10:30:00Z",
    "reference": "order_456"
  }
}
```

### Payout Preferences

Webhook payloads automatically include PayPal and Wise payout preferences in `referrer.payout_preferences` when the affiliate has configured them. This eliminates the need for additional API calls to enrich webhook data.

### Signature Verification (Node.js)

```javascript
const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
    const expectedSignature = 'sha256=' + crypto
        .createHmac('sha256', secret)
        .update(payload, 'utf8')
        .digest('hex');

    return crypto.timingSafeEqual(
        Buffer.from(expectedSignature),
        Buffer.from(signature)
    );
}

// Express middleware
app.use('/webhooks/refgrow', express.raw({type: 'application/json'}), (req, res) => {
    const signature = req.headers['x-refgrow-signature'];
    const secret = process.env.REFGROW_WEBHOOK_SECRET;

    if (!verifySignature(req.body, signature, secret)) {
        return res.status(401).send('Invalid signature');
    }

    const event = JSON.parse(req.body);
    console.log('Received event:', event.event);

    res.status(200).send('OK');
});
```

### Signature Verification (PHP)

```php
function verifySignature($payload, $signature, $secret) {
    $expectedSignature = 'sha256=' . hash_hmac('sha256', $payload, $secret);
    return hash_equals($expectedSignature, $signature);
}

$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_REFGROW_SIGNATURE'] ?? '';
$secret = 'your_webhook_secret';

if (!verifySignature($payload, $signature, $secret)) {
    http_response_code(401);
    exit('Invalid signature');
}
```

### Express.js Webhook Handler

```javascript
const express = require('express');
const app = express();

app.post('/webhooks/refgrow', express.raw({type: 'application/json'}), async (req, res) => {
    try {
        const event = JSON.parse(req.body);

        switch (event.event) {
            case 'referral_signed_up':
                await handleReferralSignup(event);
                break;
            case 'referral_converted':
                await handleReferralConversion(event);
                break;
            case 'referral_updated':
                await handleReferralUpdate(event);
                break;
            case 'referral_canceled':
                await handleReferralCancellation(event);
                break;
            default:
                console.log('Unknown event type:', event.event);
        }

        res.status(200).json({ received: true });
    } catch (error) {
        console.error('Webhook error:', error);
        res.status(400).send('Webhook Error');
    }
});
```

### Webhook Delivery

- Successful delivery: HTTP 200-299, response within 5 seconds
- Failed delivery: HTTP 400+ or timeout; automatic retries (3 attempts)
- Your endpoint must respond with HTTP 200-299 for successful delivery

### Best Practices

- Always verify webhook signatures
- Use HTTPS endpoints
- Respond quickly (within 10 seconds)
- Return HTTP 200 on success
- Handle duplicate events (implement idempotency using event IDs)
- Use queues for heavy processing operations

---

## Widget Customization

### Appearance Settings (configured in project dashboard)

- Primary Color -- buttons and highlights
- Secondary Color -- secondary elements and accents
- Font Color -- text color
- Title -- headline text
- Description -- program explanation

### Branding Removal

On paid plans (Starter and above), the "Powered by Refgrow" footer can be removed.

### Block Configuration

Blocks can be enabled, disabled, and reordered via drag-and-drop in project settings. See the Widget Blocks section above for full list of available blocks and their IDs.

### i18n

The widget loads translations from `/locales.json` and supports 9 languages. Override auto-detection with `data-lang="fr"` on the embed div.

### CSP for Widget

```
script-src 'self' https://scripts.refgrowcdn.com https://refgrow.com;
connect-src 'self' https://refgrow.com;
```

---

## Affiliate Portal

The Affiliate Portal is a standalone, hosted dashboard where affiliates can view stats, referral links, conversions, earnings, and payouts -- without embedding anything into your website. It is an alternative to the embedded widget.

### Enabling the Portal

1. Go to your project's **Portal** page (separate page in the project sidebar)
2. Toggle **Enable Portal** on
3. Choose a slug (e.g., `myapp`). Your portal will be available at `myapp.refgrow.com`
4. Save

### Portal Features

- Dashboard with clicks, signups, conversions, total earnings, unpaid balance, referral link, and coupon code
- Payout history with downloadable invoices
- Settings for preferred payment method (PayPal, Wise, bank transfer, etc.)
- Day-by-day statistics for the last 30 days
- Detailed earnings breakdown

### Custom Domain

Add a CNAME record pointing to `portal.refgrow.com`. Then enter your custom domain on the Portal page. SSL is provisioned automatically.

### Public vs Invite-Only

- **Public signup** -- anyone can visit the portal and create an affiliate account
- **Invite-only** -- only affiliates already added to your project can log in

### Portal vs Widget

Both share the same data. Use the Portal for standalone affiliate programs and external partners. Use the Widget for in-app referral programs and existing users. You can use both simultaneously.

---

## Messages

Send direct messages to your affiliates from the Refgrow dashboard. Messages appear in the affiliate's widget and portal. Use this to communicate program updates, promotions, or personalized notes.

---

## MCP Server

The `@refgrow/mcp` package is a Model Context Protocol server that wraps the Refgrow REST API for use with AI assistants like Claude Desktop, Cursor, and Claude Code.

### Installation

Runs via `npx` -- no global install needed:

```
npx @refgrow/mcp
```

### Prerequisites

- Node.js 18+
- A Refgrow API key (starts with `rgk_`)

### Getting an API Key

1. Log in to Refgrow dashboard
2. Navigate to project Settings tab
3. Scroll to API Keys section
4. Click "Generate API Key"
5. Copy the key (starts with `rgk_`, shown only once)

### Setup for Claude Desktop

Config file:
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`

```json
{
  "mcpServers": {
    "refgrow": {
      "command": "npx",
      "args": ["-y", "@refgrow/mcp"],
      "env": {
        "REFGROW_API_KEY": "rgk_your_api_key_here"
      }
    }
  }
}
```

### Setup for Cursor

Create or edit `.cursor/mcp.json` in your project root:

```json
{
  "mcpServers": {
    "refgrow": {
      "command": "npx",
      "args": ["-y", "@refgrow/mcp"],
      "env": {
        "REFGROW_API_KEY": "rgk_your_api_key_here"
      }
    }
  }
}
```

### Setup for Claude Code

Add to `.mcp.json` in your project root:

```json
{
  "mcpServers": {
    "refgrow": {
      "command": "npx",
      "args": ["-y", "@refgrow/mcp"],
      "env": {
        "REFGROW_API_KEY": "rgk_your_api_key_here"
      }
    }
  }
}
```

### Environment Variables

| Variable          | Required | Description                                        |
|-------------------|----------|----------------------------------------------------|
| `REFGROW_API_KEY` | Yes      | Your Refgrow API key (starts with `rgk_`)          |
| `REFGROW_API_URL` | No       | Custom API base URL (default: `https://refgrow.com/api/v1`) |

### Available MCP Tools (18 total)

**Affiliates:**
- `list_affiliates` -- List all affiliates with stats (clicks, signups, purchases, earnings). Supports filtering by status and pagination.
- `get_affiliate_details` -- Get detailed info about a specific affiliate by email.
- `create_affiliate` -- Create a new affiliate with optional custom referral code and partner slug.
- `update_affiliate` -- Update affiliate email, referral code, status, or partner slug.
- `delete_affiliate` -- Remove an affiliate and associated referral data.

**Referrals:**
- `list_referrals` -- List referred users. Filter by affiliate ID or conversion status (pending, converted, direct, direct_signup).
- `get_referral_details` -- Get details for a specific referred user by email.
- `create_referral` -- Manually create a referred user record, optionally linked to an affiliate.

**Conversions:**
- `list_conversions` -- List conversions with filters for type (signup/purchase), affiliate, date range (from/to ISO dates), paid status. Default limit: 50.
- `get_conversion` -- Get a specific conversion by ID.
- `create_conversion` -- Create a conversion. Commission auto-calculated from project settings if value omitted. Can identify affiliate by ID or referral code.
- `update_conversion` -- Update conversion details or mark as paid.
- `delete_conversion` -- Delete a conversion record.

**Coupons:**
- `list_coupons` -- List coupon codes with affiliate info. Filter by status, affiliate_id, or coupon_code search.
- `get_coupon` -- Get a specific coupon by ID.
- `create_coupon` -- Create a coupon linked to an affiliate, with optional Stripe coupon ID or LemonSqueezy discount code for automatic attribution.
- `update_coupon` -- Update coupon code, linked affiliate, payment provider IDs, or status.
- `delete_coupon` -- Delete a coupon (also removes from Stripe if linked).

---

## Framework Integration Examples

### React / Next.js -- Tracking Script

```typescript
// components/RefgrowTracking.tsx
"use client";

import Script from "next/script";

export function RefgrowTracking({ projectId }: { projectId: string }) {
  return (
    <Script
      src="https://scripts.refgrowcdn.com/latest.js"
      data-project-id={projectId}
      strategy="afterInteractive"
    />
  );
}
```

### React -- Affiliate Widget Component

```javascript
import { useEffect, useRef } from 'react';

function AffiliateWidget({ projectId, userEmail }) {
  const containerRef = useRef(null);

  useEffect(() => {
    const script = document.createElement('script');
    script.src = 'https://scripts.refgrowcdn.com/page.js';
    script.async = true;
    script.defer = true;
    containerRef.current?.appendChild(script);

    return () => {
      script.remove();
    };
  }, [projectId, userEmail]);

  return (
    <div
      id="refgrow"
      ref={containerRef}
      data-project-id={projectId}
      data-project-email={userEmail}
    />
  );
}
```

### Vue / Nuxt -- Tracking Script

```typescript
// nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      script: [
        {
          src: 'https://scripts.refgrowcdn.com/latest.js',
          'data-project-id': 'YOUR_PROJECT_ID',
          defer: true
        }
      ]
    }
  }
})
```

### Plain HTML -- Complete Page

```html
<!DOCTYPE html>
<html>
<head>
    <title>My Affiliate Program</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- Tracking Script for all pages -->
    <script src="https://scripts.refgrowcdn.com/latest.js"
        data-project-id="YOUR_PROJECT_ID"></script>
</head>
<body>
    <header>
        <h1>My Website</h1>
    </header>

    <main>
        <h2>Join Our Affiliate Program</h2>

        <!-- Refgrow Widget -->
        <div id="refgrow"
            data-project-id="YOUR_PROJECT_ID"
            data-lang="en">
        </div>
        <script src="https://scripts.refgrowcdn.com/page.js" async defer></script>
    </main>
</body>
</html>
```

### Server-Side (Node.js + EJS)

```html
<!-- affiliate-page.ejs -->
<!DOCTYPE html>
<html>
<head>
    <title>Affiliate Program - <%= siteName %></title>
</head>
<body>
    <main>
        <h1>Our Affiliate Program</h1>

        <% if (user) { %>
            <!-- Authenticated user -->
            <div id="refgrow"
                data-project-id="<%= process.env.REFGROW_PROGRAM_ID %>"
                data-project-email="<%= user.email %>"
                data-lang="en">
            </div>
        <% } else { %>
            <!-- Non-authenticated user -->
            <div id="refgrow"
                data-project-id="<%= process.env.REFGROW_PROGRAM_ID %>"
                data-lang="en">
            </div>
        <% } %>

        <script src="https://scripts.refgrowcdn.com/page.js" async defer></script>
    </main>

    <script src="https://scripts.refgrowcdn.com/latest.js"
        data-project-id="<%= process.env.REFGROW_PROGRAM_ID %>"></script>
</body>
</html>
```

### Node.js -- Creating a Conversion via API

```javascript
const response = await fetch('https://refgrow.com/api/v1/conversions', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer rgk_YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    customer_email: 'customer@example.com',
    amount: 49.99,
    referral_code: 'REF123'
  })
});

const data = await response.json();
console.log('Conversion created:', data);
```

### Stripe Checkout Session with Referral Code (Node.js)

```javascript
const refCode = req.cookies.refgrow_ref_code;

const session = await stripe.checkout.sessions.create({
  line_items: [{ price: 'price_xxx', quantity: 1 }],
  mode: 'subscription',
  success_url: 'https://yoursite.com/success',
  cancel_url: 'https://yoursite.com/cancel',
  metadata: {
    referral_code: refCode || null
  }
});
```

---

## Troubleshooting

### Referrals Not Being Tracked

1. Verify the tracking script is on all pages with the correct project ID
2. Check browser console for error messages
3. Ensure third-party cookies are not blocked
4. Test with a known referral link format (e.g., `?ref=CODE`)
5. Verify the referral parameter name matches project settings

### Conversions Not Attributing to Affiliates

**For Stripe/LemonSqueezy/Paddle:**
- Ensure webhooks are properly configured
- Verify referral code is passed to the payment provider
- Check webhook logs in your payment provider dashboard

**For Manual Tracking:**
- Ensure a valid email is passed to the `Refgrow()` function
- Verify the cookie exists when making the call
- Check browser console for API errors

### Affiliate Dashboard Issues

1. Verify the page.js script is loading properly
2. Check that the project ID is correct
3. Ensure no JavaScript errors on your page
4. Test on a clean page without other scripts
5. Verify your domain is configured in project settings

### Stripe Webhooks Not Working

1. Verify Stripe API key in project settings
2. Check webhook endpoint URL matches `https://refgrow.com/webhook/stripe/{your-project-id}`
3. Confirm all required events are enabled
4. Check Stripe dashboard for webhook delivery logs

### Webhook Signature Verification Failing

- Ensure the webhook secret matches exactly
- The raw request body must not be parsed by JSON middleware before signature verification
- Use `express.raw({type: 'application/json'})` for the webhook endpoint

### Duplicate Conversions

- Refgrow deduplicates by payment provider event ID
- Check for multiple webhook endpoints pointing to the same project
- Implement idempotency in your webhook handler using event IDs

### CSP Blocking Scripts

Add to your Content Security Policy:

```
script-src 'self' https://scripts.refgrowcdn.com https://refgrow.com;
connect-src 'self' https://refgrow.com;
```

### MCP Server Issues

- "Server not found": Ensure Node.js 18+ is installed, verify `npx` is available
- "Authentication failed" / 401: Verify API key starts with `rgk_`, check it hasn't been revoked
- "Tool not available": Restart your AI client, verify JSON config is valid

---

## Support

- Email: support@refgrow.com
- Docs: https://refgrow.com/docs
- API Reference: https://refgrow.com/docs/api-reference


---

# Full Documentation Index

The sections below are the verbatim content of every page under refgrow.com/docs, concatenated. Each section is also reachable on its own at refgrow.com/docs/<slug>.md.

---



<!-- ===== /docs/introduction ===== -->

# Introduction to Refgrow

> Source: https://refgrow.com/docs/introduction

Your complete solution for affiliate marketing.

## What is Refgrow?

Refgrow is a powerful affiliate marketing platform designed specifically for SaaS businesses. It helps you leverage word-of-mouth marketing by making it easy to create, manage, and track affiliate programs.

With Refgrow, you can turn your customers into advocates, reward them for referrals, and grow your business organically through the power of affiliate marketing.

## Key Features

### Easy Integration

Integrate Refgrow into your website with just a few lines of code. No complicated setup required.

### Automatic Tracking

Track referrals and conversions automatically with our powerful tracking system.

### Customizable Dashboard

Provide your affiliates with a branded dashboard to track their performance and access resources.

### Commission Management

Set up flexible commission structures and manage payments through integrations.

## How It Works

### Step 1

Create a program and set up your commission structure

### Step 2

Integrate the tracking code and affiliate dashboard

### Step 3

Manage and grow your affiliate network

Refgrow makes it easy to start and grow your affiliate program. By following our simple onboarding process, you can set up a fully functional affiliate program in minutes. Once integrated, you can track referrals, manage commissions, and provide affiliates with the tools they need to promote your business.

## Who Is Refgrow For?

### SaaS Businesses

Ideal for software-as-a-service companies looking to grow through referral marketing.

### Digital Product Creators

Perfect for course creators, content producers, and digital product sellers.

### E-commerce Stores

Great for online retailers looking to expand their reach through affiliates.

### Membership Sites

Excellent for subscription and membership businesses seeking organic growth.

## Getting Started with Refgrow

Ready to start your affiliate program? Follow our [Quick Start Guide](/docs/quickstart) to set up your first program in minutes, or explore our detailed [Installation Guide](/docs/installation) for more advanced integration options.

### Quick Start Guide

Get up and running with Refgrow in just a few minutes. Learn the basics and create your first affiliate program.

[Start Here →](/docs/quickstart)

### Installation Guide

Detailed instructions for installing and configuring Refgrow in your application.

[Learn More →](/docs/installation)

---



<!-- ===== /docs/quickstart ===== -->

# Quickstart

> Source: https://refgrow.com/docs/quickstart

Set up a Refgrow affiliate program on your website in minutes to grow your business with affiliates. Here is how to get started.

## 1\. Install tracking script

Add the tracking script to the `<head>` section of your website:

```
<script
  src="https://scripts.refgrowcdn.com/latest.js"
  data-project-id="YOUR_PROJECT_ID"
  async defer>
</script>
```

**Important:** Replace `YOUR_PROJECT_ID` with your actual project ID from the Refgrow dashboard.

## 2\. Add affiliate dashboard

Embed the affiliate dashboard into your website so affiliates can track their performance and earnings. Alternatively, you can use the hosted [Affiliate Portal](/docs/affiliate-portal) instead of embedding a widget.

### Option 1: With user email (Referral Program)

Use this when you know the user's email address (e.g., they are already logged in):

```
<div id="refgrow"
  data-project-id="YOUR_PROJECT_ID"
  data-project-email="user@example.com">
</div>
<script src="https://scripts.refgrowcdn.com/page.js" async defer></script>
```

### Option 2: Without user email (Affiliate Program)

Use this when users need to enter their email to access the dashboard:

```
<div id="refgrow"
  data-project-id="YOUR_PROJECT_ID">
</div>
<script src="https://scripts.refgrowcdn.com/page.js" async defer></script>
```

**Note:** The dashboard will automatically handle user authentication and show personalized affiliate data.

## 3\. Track user registrations (optional)

If your business has a registration step before purchase, add this tracking call after successful user signups:

```
Refgrow(0, 'signup', 'user@example.com');
```

**When to use:** Call this function on your registration success page or after successful user signup to track when referred users create accounts. Replace `user@example.com` with the actual user's email address.

## 4\. Connect payment provider

Choose your payment provider to automatically track purchases and calculate commissions:

### Stripe

Most popular payment processor with webhook-based tracking.

-   One-time payments
-   Subscriptions
-   Automatic tracking

[View Guide →](/docs/stripe)

### LemonSqueezy

Perfect for digital products, services and SaaS businesses.

-   Digital products
-   Subscriptions
-   Built-in tracking

### Paddle

Global payment processor with subscription management.

-   Global payments
-   Subscription handling
-   Tax compliance

### Polar

Subscription platform for creators and developers.

-   Creator subscriptions
-   GitHub integration
-   Developer-friendly

**Don't see your payment provider?** [Use manual tracking](/docs/tracking) to integrate with any payment system.

## Next steps

### Explore the API

Programmatically manage your affiliate program.

[View API →](/docs/api-reference)

### Set up payouts

Configure automatic payouts for your affiliates.

## Need help?

If you need help, please contact us at [support@refgrow.com](mailto:support@refgrow.com).

---



<!-- ===== /docs/installation ===== -->

# Installation Guide

> Source: https://refgrow.com/docs/installation

Set up Refgrow in minutes with these simple steps.

## Overview

Setting up Refgrow involves two essential components:

1.  **Tracking Script** — Placed on your website to detect referrals and track conversions
2.  **Affiliate Dashboard** — Where your affiliates manage their links and see their earnings

**Quick Setup:** Both components can be implemented with just a few lines of code.

## Step 1: Add the Tracking Script

The tracking script handles referral detection, cookie management, and conversion tracking. Add it to **all pages** of your website:

```
<script
  src="https://scripts.refgrowcdn.com/latest.js"
  data-project-id="YOUR_PROJECT_ID">
</script>
```

**Important:** Replace `YOUR_PROJECT_ID` with your actual project ID from your Refgrow dashboard.

### What the Tracking Script Does

-   Detects when users arrive via referral links (`?ref=CODE`)
-   Stores the referral code in a cookie with your configured lifetime
-   Enables manual conversion tracking via the `Refgrow()` function
-   Provides helper methods for Stripe Payment Links

### Placement

For optimal performance, place the script in the `<head>` section of your HTML, before other scripts that might access the `Refgrow()` function.

**Content Security Policy (CSP):** If your website uses CSP headers, you will need to add `https://scripts.refgrowcdn.com` to your `script-src` directive. See the [Tracking guide](/docs/tracking) for detailed CSP configuration instructions.

## Step 2: Choose Your Conversion Tracking Method

**Multiple Methods:** You can use one or multiple tracking methods simultaneously.

### Stripe Webhooks (Recommended)

Automatically track payments processed through Stripe:

1.  Go to your project's "Integration" tab
2.  Select "Stripe Webhooks" as your tracking method
3.  Enter your Stripe Secret Key (a restricted key is recommended)
4.  Click "Connect Stripe"

Refgrow will automatically set up the required webhook in your Stripe account.

**For Direct Purchase Flow:** If users can purchase without registering, make sure to pass the referral code to Stripe. [See the Stripe guide](/docs/stripe) for details.

### LemonSqueezy Webhooks

Track purchases made through LemonSqueezy:

1.  Go to your project's "Integration" tab
2.  Select "LemonSqueezy Webhooks" as your tracking method
3.  Enter your LemonSqueezy API Key
4.  In your LemonSqueezy dashboard, create a webhook pointing to: `https://refgrow.com/webhook/lemonsqueezy/YOUR_PROJECT_ID`
5.  Select the events: `order_created` and `subscription_created`

### Manual Tracking

Track conversions by calling the `Refgrow()` function in your code:

```
// Track a signup (no monetary value)
Refgrow(0, 'signup', 'user@example.com');

// Track a purchase (with monetary value)
Refgrow(49.99, 'purchase', 'user@example.com');
```

**Parameters:**

1.  `value` — Monetary value (use 0 for non-monetary events)
2.  `type` — Event type ('signup', 'purchase', or custom)
3.  `email` — User's email (crucial for attribution)

Place this code on thank you pages, after successful registrations, or whenever a conversion occurs.

## Step 3: Add the Affiliate Dashboard

The affiliate dashboard is where users can sign up as affiliates, get their referral links, and track their earnings. You can either embed a widget into your website or use the hosted [Affiliate Portal](/docs/affiliate-portal).

### Option 1: For Websites with User Authentication

If users are already logged into your site, pass their email to pre-authenticate them:

```
<div id="refgrow"
    data-project-id="YOUR_PROJECT_ID"
    data-project-email="user@example.com"
    data-lang="en"> <!-- Optional: Specify language code -->
</div>
<script src="https://scripts.refgrowcdn.com/page.js" async defer></script>
```

**Notes:**

-   Replace `YOUR_PROJECT_ID` with your actual project ID
-   Replace `user@example.com` with your server-side code that outputs the current user's email
-   The `data-lang` attribute is optional. If omitted, the language set in your project settings (or English by default) will be used. Supported codes include: en, ro, ua, de, es, fr, it, pt.
-   The user will be automatically logged in to the affiliate dashboard

### Option 2: Without User Authentication

For standalone affiliate pages or sites without authentication:

```
<div id="refgrow"
    data-project-id="YOUR_PROJECT_ID"
    data-lang="en"> <!-- Optional: Specify language code -->
</div>
<script src="https://scripts.refgrowcdn.com/page.js" async defer></script>
```

Users will need to enter their email and verify it to access their affiliate dashboard.

### Customizing the Dashboard

You can customize the appearance and content of the dashboard in your Refgrow project's "Widget" tab, including:

-   Colors and fonts to match your brand
-   Custom titles and descriptions
-   Which stats to display
-   Payout information

**Content Security Policy (CSP):** For the affiliate dashboard widget, add `https://refgrow.com` or `https://*.refgrow.com` to your `script-src` and `connect-src` directives.

## Step 4: Configure Commission Settings

Set up your commission structure in your Refgrow project settings:

1.  Go to your project's "Settings" tab
2.  Configure your default commission rate (percentage or fixed amount)
3.  Set the commission duration (lifetime, first purchase, or limited period)

### Advanced Commission Options

Refgrow offers advanced commission options:

-   **Product-specific commissions** — Set different rates for specific products
-   **Affiliate-specific overrides** — Create custom rates for individual affiliates

## Testing Your Installation

### Complete Test Flow

1.  Sign up as a test affiliate
2.  Generate your referral link
3.  Open the link in a new private/incognito browser window
4.  Verify the cookie is set (check your browser's developer tools)
5.  Make a test purchase or trigger a conversion
6.  Verify the conversion appears in your Refgrow dashboard

### Debugging Tools

The tracking script logs helpful information to the browser console. Open your browser's developer tools (F12) to see:

-   Referral code detection
-   Cookie setting confirmation
-   Conversion tracking events

## Troubleshooting

### Referrals Not Being Tracked

1.  Verify the tracking script is on all pages with the correct project ID
2.  Check your browser console for any error messages
3.  Ensure third-party cookies are not blocked by the browser
4.  Test with a known referral link format (e.g., `?ref=CODE`)
5.  Verify the referral parameter name matches your project settings

### Conversions Not Attributing to Affiliates

**For Stripe/LemonSqueezy:**

-   Ensure webhooks are properly configured
-   Verify you are passing the referral code to the payment provider
-   Check webhook logs in your payment provider dashboard

**For Manual Tracking:**

-   Ensure you are providing a valid email address to the `Refgrow()` function
-   Verify the cookie exists when making the call
-   Check your browser console for any API errors

### Affiliate Dashboard Issues

1.  Verify the page.js script is loading properly
2.  Check that the project ID is correct
3.  Ensure there are no JavaScript errors on your page
4.  Test the dashboard on a clean page without other scripts
5.  Verify that your domain is properly configured in your project settings

## Framework-Specific Guides

### React / Next.js

```
// components/RefgrowTracking.tsx
"use client";

import Script from "next/script";

export function RefgrowTracking({ projectId }: { projectId: string }) {
  return (
    <Script
      src="https://scripts.refgrowcdn.com/latest.js"
      data-project-id={projectId}
      strategy="afterInteractive"
    />
  );
}
```

### Vue / Nuxt

```
// nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      script: [
        {
          src: 'https://scripts.refgrowcdn.com/latest.js',
          'data-project-id': 'YOUR_PROJECT_ID',
          defer: true
        }
      ]
    }
  }
})
```

## Next Steps

-   [Stripe Integration](/docs/stripe) — learn advanced options for integrating with Stripe
-   [Tracking Script](/docs/tracking) — advanced tracking options and configuration
-   [Widget Customization](/docs/widget) — personalize the affiliate dashboard to match your brand
-   [API Reference](/docs/api-reference) — manage affiliates and conversions programmatically

---



<!-- ===== /docs/llm-quickstart ===== -->

# AI-Powered Integration

> Source: https://refgrow.com/docs/llm-quickstart

Use AI coding assistants to integrate Refgrow in minutes. Works with Claude Code, Cursor, GitHub Copilot, and more.

## Quick Context (Recommended)

AI coding assistants work best when they have context about the API they're integrating. Refgrow publishes a machine-readable documentation file at [refgrow.com/llms.txt](https://refgrow.com/llms.txt) that any AI tool can read. This is the fastest way to get started — just paste a prompt that includes the URL.

Use this prompt with your AI tool:

```
Integrate Refgrow affiliate tracking into my app.
Here's the full documentation: https://refgrow.com/llms.txt
My project ID is: YOUR_PROJECT_ID
```

The AI will fetch the documentation, understand Refgrow's API, and generate the correct integration code for your stack — whether that's Next.js, Rails, Django, Laravel, or anything else.

**Tip:** Replace `YOUR_PROJECT_ID` with your actual project ID from the Refgrow dashboard. You can also add details about your tech stack to get more tailored output.

## MCP Server (For Claude Code & Cursor)

The [Model Context Protocol (MCP)](https://modelcontextprotocol.io) gives your AI assistant direct access to Refgrow's API. Instead of just generating code, the AI can actually create affiliates, list conversions, manage coupons, and more — all through natural language.

### Claude Code

Add the Refgrow MCP server with a single command:

```
claude mcp add refgrow -- npx -y @refgrow/mcp
```

Then set your API key as an environment variable:

```
export REFGROW_API_KEY=rgk_your_api_key_here
```

### Cursor

Create or edit `.cursor/mcp.json` in your project root:

```
{
  "mcpServers": {
    "refgrow": {
      "command": "npx",
      "args": ["-y", "@refgrow/mcp"],
      "env": {
        "REFGROW_API_KEY": "rgk_your_api_key_here"
      }
    }
  }
}
```

Restart Cursor after saving. The Refgrow tools will appear in the AI assistant's available tools.

### Claude Desktop

Add the following to your `claude_desktop_config.json`:

-   **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
-   **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`

```
{
  "mcpServers": {
    "refgrow": {
      "command": "npx",
      "args": ["-y", "@refgrow/mcp"],
      "env": {
        "REFGROW_API_KEY": "rgk_your_api_key_here"
      }
    }
  }
}
```

After saving, restart Claude Desktop. You should see the Refgrow tools available in the tools menu.

**Important:** Your API key starts with `rgk_`. Generate one from your project's **Settings → API Keys** section in the Refgrow dashboard. See the [MCP Server docs](/docs/mcp-server) for full setup details.

## Available MCP Tools

The MCP server exposes 18 tools organized in 4 categories. Your AI assistant can call any of these based on your natural-language requests.

### Affiliates

Tool

Description

`list_affiliates`

List all affiliates with stats (clicks, signups, purchases, earnings)

`get_affiliate_details`

Get details for a specific affiliate by email

`create_affiliate`

Create a new affiliate with optional custom referral code

`update_affiliate`

Update affiliate email, referral code, status, or partner slug

`delete_affiliate`

Remove an affiliate from the project

### Referrals

Tool

Description

`list_referrals`

List referred users, filterable by affiliate or status

`get_referral_details`

Get details for a specific referred user by email

`create_referral`

Manually create a referred user record

### Conversions

Tool

Description

`list_conversions`

List conversions with filters for type, affiliate, date range, paid status

`get_conversion`

Get a specific conversion by ID

`create_conversion`

Create a conversion (signup/purchase) with auto-commission calculation

`update_conversion`

Update conversion details or mark as paid

`delete_conversion`

Delete a conversion record

### Coupons

Tool

Description

`list_coupons`

List coupon codes with affiliate info

`get_coupon`

Get a specific coupon by ID

`create_coupon`

Create a coupon linked to an affiliate (with optional Stripe/LemonSqueezy IDs)

`update_coupon`

Update coupon details

`delete_coupon`

Delete a coupon (also removes from Stripe if linked)

## Example Prompts

Here are some prompts you can give your AI assistant to integrate and manage Refgrow. These work with any AI tool — Claude Code, Cursor, GitHub Copilot, Windsurf, and others.

Tracking setup

"Add Refgrow tracking script to my Next.js app. My project ID is abc123."

Stripe webhook integration

"Set up a Stripe webhook for affiliate conversion tracking with Refgrow."

Create an affiliate (MCP)

"Create an affiliate with email partner@example.com and 30% commission."

View conversions (MCP)

"Show me all conversions from last week."

Embed widget

"Add the Refgrow embedded widget to my dashboard page so affiliates can see their stats."

LemonSqueezy integration

"Integrate Refgrow with my LemonSqueezy checkout to track affiliate conversions."

## Direct Context Injection

Some AI tools don't support fetching URLs automatically. In that case, you can download the full documentation and paste it directly into your prompt as context.

1.  Download the docs file: [refgrow.com/llms.txt](https://refgrow.com/llms.txt)
2.  Open the file in a text editor and copy its contents
3.  Paste it into your AI tool's prompt along with your integration request

Or use `curl` from the terminal:

```
curl -s https://refgrow.com/llms.txt | pbcopy
```

**Tip:** On Linux, replace `pbcopy` with `xclip -selection clipboard`. On Windows, use `clip`.

You can also point AI tools that support file attachments directly at the downloaded `llms.txt` file. This works especially well with ChatGPT, Gemini, and other chat-based interfaces.

## Next Steps

-   [MCP Server](/docs/mcp-server) — full MCP setup guide with troubleshooting
-   [Quickstart](/docs/quickstart) — set up your first affiliate program
-   [API Reference](/docs/api-reference) — full documentation of all API endpoints
-   [Tracking Script](/docs/tracking) — understand how referral tracking works

## Need help?

If you have questions about AI-powered integration, contact us at [support@refgrow.com](mailto:support@refgrow.com).

---



<!-- ===== /docs/programs ===== -->

# Programs

> Source: https://refgrow.com/docs/programs

Learn how to manage affiliate programs with Refgrow.

## What is a Program?

In Refgrow, a program represents a single affiliate program. Each program has its own:

-   Unique tracking domain
-   Commission structure
-   Payment settings
-   Affiliate dashboard
-   Analytics and reporting

## Creating a Program

To create a new program:

1.  Navigate to your Refgrow dashboard
2.  Click "Add New Program"
3.  Enter your program name
4.  Follow the onboarding steps to configure your program

**Note:** The number of programs you can create depends on your subscription plan:

-   Free/Starter: 1 program
-   Pro: Multiple programs (limit depends on your plan)

## Program Onboarding

### Step 1: Configure Basic Settings

In the first step of onboarding, you will configure:

-   Conversion tracking method
-   Tracking domain
-   Cookie lifetime (default is 30 days)
-   Commission type (percentage)
-   Commission value
-   Commission duration (lifetime or period)

### Step 2: Customize Appearance

In the second step, you can customize the look and feel of your affiliate dashboard:

-   Primary and secondary colors
-   Font color
-   Affiliate title and description
-   Toggle visibility of title, description, and daily stats
-   Option to hide Refgrow branding

### Step 3: Integration Setup

The final step involves setting up integrations for your affiliate program.

## Program Settings

### General Settings

Setting

Description

Program Name

The name of your affiliate program

Tracking Domain

The domain where your affiliate program operates

Commission Value

Percentage commission for affiliates

Cookie Lifetime

How long referral attribution lasts (default: 30 days)

### Tracking Settings

Choose from multiple conversion tracking methods:

-   JavaScript — Manual tracking using the Refgrow function
-   Stripe integration — Automatic tracking of Stripe payments
-   LemonSqueezy — Integration with LemonSqueezy payments

### Appearance Settings

Customize how your affiliate dashboard looks:

-   Primary and secondary colors
-   Custom title and description
-   Show/hide various elements
-   White-label option (hide Refgrow branding)

## Program Dashboard

Each program has its own dashboard showing:

### Performance Metrics

-   Total clicks
-   Conversion rate
-   Revenue generated
-   Active affiliates

### Affiliate Management

-   Affiliate list
-   Commission tracking
-   Payment history
-   Performance reports

## Program Analytics

Track your affiliate program's performance with detailed analytics:

### Daily Statistics

-   Daily clicks
-   Daily signups
-   Daily conversions
-   Daily revenue

### Conversion Reports

-   Signup conversions
-   Purchase tracking
-   Conversion attribution
-   Revenue tracking

### Financial Reports

-   Commission reports
-   Payout history
-   Unpaid earnings
-   ROI analysis

## Managing Payouts

Refgrow offers both manual and automatic payout options:

### Manual Payouts

-   Review unpaid earnings
-   Process payments through preferred platform
-   Mark payments as completed
-   Track payment history

### Automatic Payouts

-   Available for Pro and Business plans
-   Integration with PayPal and Wise
-   Bulk payout processing
-   Automatic status updates

## Next Steps

### Set Up Tracking

Learn how to implement conversion tracking for your program.

[View Guide →](/docs/tracking)

### Configure Payments

Set up payment methods and commission structures.

[Learn More →](/docs/stripe)

### Integration

Add the affiliate widget to your website.

[View Guide →](/docs/widget)

---



<!-- ===== /docs/affiliates ===== -->

# Affiliates

> Source: https://refgrow.com/docs/affiliates

Managing and engaging with your affiliate partners.

## Overview

Affiliates are partners who promote your products or services in exchange for commissions on successful referrals. Refgrow provides tools to manage your affiliates, track their performance, and ensure they have the resources they need to succeed.

## Affiliate Dashboard

Each affiliate gets access to a personalized dashboard where they can:

-   View their referral statistics
-   Get their unique referral links
-   Track earnings and commissions
-   Access promotional materials
-   Update their payment information

### Dashboard Customization

You can customize the appearance and content of the affiliate dashboard from your program settings. Options include:

-   Changing colors to match your brand
-   Customizing the program title and description
-   Toggling display of daily statistics
-   Showing or hiding certain dashboard elements

For details on customization, see the [Customization guide](/docs/customization).

## Managing Affiliates

### Viewing Affiliates

To view and manage your affiliates:

1.  Log in to your Refgrow dashboard
2.  Select the program you want to manage
3.  Navigate to the "Affiliates" tab

Here you will see a list of all your affiliates with key metrics including:

-   Email address
-   Referral code
-   Number of clicks
-   Signups and purchases generated
-   Total earnings
-   Unpaid balance

### Inviting Affiliates

There are several ways to add affiliates to your program:

#### Manual Invitations

1.  From the Affiliates page, click "Invite Affiliates"
2.  Enter one or more email addresses (separated by commas)
3.  Add an optional personalized message
4.  Click "Send Invites"

Invitees will receive an email with instructions to join your program.

#### Sharing Your Signup Link

You can also share a direct signup link:

1.  From the Affiliates page, click "Copy Signup Link"
2.  Share this link via email, social media, or your website

Anyone who visits this link can sign up to become an affiliate for your program.

#### Automatic Registration

You can allow customers to become affiliates automatically:

1.  Go to your program settings
2.  Enable "Allow customer self-registration"
3.  Optionally, set requirements (e.g., must have made a purchase)

### Removing Affiliates

To remove an affiliate from your program:

1.  Go to the Affiliates tab
2.  Find the affiliate you want to remove
3.  Click the delete (trash) icon in the Actions column
4.  Confirm the deletion

**Note:** Removing an affiliate is permanent and cannot be undone. Any pending unpaid commissions should be handled before removal.

## Affiliate Performance

### Tracking Metrics

Refgrow tracks several key metrics for each affiliate:

-   **Clicks:** The number of times someone clicked their referral link
-   **Signups:** Number of new users who signed up through their link
-   **Purchases:** Number of completed purchases attributed to them
-   **Earnings:** Total amount earned through commissions
-   **Conversion Rate:** Percentage of clicks that convert to purchases

### Analyzing Performance

To analyze affiliate performance in more detail:

1.  Navigate to the "Analytics" tab in your program dashboard
2.  Filter by date range or specific affiliates
3.  View charts and graphs showing performance trends
4.  Export data for further analysis if needed

This data can help you identify your top-performing affiliates and optimize your program.

## Communication and Resources

### Communicating with Affiliates

Effective communication is key to a successful affiliate program. You can:

-   Send email announcements to all affiliates
-   Provide updates about new products or promotions
-   Share tips for better conversion rates
-   Communicate changes to commission structures or policies

### Providing Resources

Help your affiliates succeed by providing marketing resources:

1.  Go to the "Resources" tab in your program settings
2.  Upload marketing materials such as:
    -   Banner images
    -   Product images
    -   Email templates
    -   Social media copy
3.  Add descriptions for each resource
4.  Publish to make them available in the affiliate dashboard

These resources will appear in the "Marketing Materials" section of your affiliates' dashboards.

## Best Practices

-   **Clear Guidelines:** Provide clear guidelines on how affiliates can and cannot promote your products
-   **Competitive Commissions:** Offer competitive commission rates to attract and retain high-quality affiliates
-   **Regular Communication:** Keep affiliates informed about new products, promotions, and changes
-   **Quality Resources:** Provide high-quality marketing materials to help affiliates promote effectively
-   **Prompt Payments:** Process affiliate payments promptly according to your schedule
-   **Recognition:** Recognize and reward top-performing affiliates

## Next Steps

-   Learn about [Commission Structures](/docs/commissions)
-   Set up your [Payout System](/docs/payouts)
-   Customize your [Affiliate Dashboard](/docs/customization)

---



<!-- ===== /docs/commissions ===== -->

# Commission Structures

> Source: https://refgrow.com/docs/commissions

Setting up effective affiliate rewards.

## Overview

Commission structures determine how your affiliates are rewarded for their referrals. Setting up the right commission structure is essential for creating an attractive affiliate program while maintaining profitability.

Refgrow offers flexible commission options that allow you to create a structure that works for your business model.

## Commission Types

### Percentage-Based Commissions

With percentage-based commissions, affiliates earn a fixed percentage of each sale they generate. This is the most common commission type and works well for most businesses.

```
Purchase Amount: $100
Commission Rate: 20%
Affiliate Earnings: $20
```

### Fixed-Amount Commissions

With fixed-amount commissions, affiliates earn a predetermined amount for each sale, regardless of the purchase amount. This works well for subscription-based products or services with consistent pricing.

```
Purchase: Any plan
Fixed Commission: $15
Affiliate Earnings: $15
```

## Commission Duration

### One-Time Commissions

With one-time commissions, affiliates earn only on the initial purchase. This is the simplest commission structure and works well for products with a one-time purchase model.

### Lifetime Commissions

With lifetime commissions, affiliates earn on all purchases made by customers they refer, for as long as those customers remain active. This is great for subscription-based businesses and encourages affiliates to refer high-quality, long-term customers.

```
Monthly Subscription: $50
Commission Rate: 20%
Monthly Affiliate Earnings: $10 (ongoing)
```

### Fixed-Period Commissions

With fixed-period commissions, affiliates earn on purchases made by their referrals for a specific duration (e.g., 3 months, 6 months, or 1 year).

```
Monthly Subscription: $50
Commission Rate: 15%
Monthly Affiliate Earnings: $7.50
Duration: 6 months
Total Earnings: $45
```

## Setting Up Commissions

### Basic Commission Setup

To set up your basic commission structure:

1.  Log in to your Refgrow dashboard
2.  Select the program you want to configure
3.  Go to the "Settings" tab
4.  Navigate to the "Commissions" section
5.  Choose your commission type (percentage or fixed)
6.  Enter the commission value
7.  Select the commission duration (lifetime or fixed period)
8.  If choosing a fixed period, specify the duration in months
9.  Save your changes

### Advanced Commission Settings

For more complex commission structures, Refgrow offers several advanced options:

#### Minimum Payout Threshold

Set a minimum amount that affiliates must earn before they can request payment. This helps reduce processing costs for small payouts.

```
Example: $50 minimum payout threshold
An affiliate must earn at least $50 before they can receive a payment.
```

#### Payout Frequency

Determine how often affiliate payments are processed. Common options include:

-   Weekly
-   Bi-weekly
-   Monthly
-   Quarterly

The payout frequency you choose should balance affiliate satisfaction with administrative convenience.

## Commission Calculation

Refgrow automatically calculates commissions based on your configured settings. Here is how it works:

### For Percentage-Based Commissions

```
Commission Amount = Purchase Amount x Commission Rate

Example:
Purchase Amount: $100
Commission Rate: 20%
Commission Amount: $100 x 0.20 = $20
```

### For Fixed-Amount Commissions

```
Commission Amount = Fixed Commission Value

Example:
Fixed Commission: $15
Commission Amount: $15
```

### For Subscription Products

For subscription products, commissions are calculated for each billing cycle based on your commission structure:

```
For Percentage-Based:
Monthly Commission = Monthly Subscription Fee x Commission Rate

For Fixed-Amount:
Monthly Commission = Fixed Commission Value
```

The duration for which these commissions are paid depends on your commission duration setting (fixed period or lifetime).

## Individual Affiliate Settings

Beyond your global commission settings, Refgrow allows you to customize commission structures for individual affiliates. This enables you to create different reward structures for different types of partnerships.

### Affiliate-Specific Commission Overrides

You can set custom commission rates and durations for individual affiliates:

1.  Go to your project's "Affiliates" tab
2.  Find the affiliate you want to customize
3.  Click the "Manage Override" button (percentage icon)
4.  Configure custom settings:
    -   **Commission Type:** Choose percentage or fixed amount
    -   **Commission Value:** Set the specific rate or amount
    -   **Commission Duration:** Choose how long they earn commissions
5.  Save your changes

**Commission Duration Options:**

-   **Use Default:** Use your project's default duration settings
-   **Lifetime:** Affiliate earns commission forever from referred customers
-   **Fixed Period:** Affiliate earns for a specific number of months from the first purchase

**Priority:** Affiliate-specific overrides take the highest priority, followed by product-specific commissions, with your default project settings as the fallback.

### Use Cases for Individual Settings

#### Strategic Partners

Offer higher commission rates and lifetime duration to key strategic partners who bring high-value customers.

```
Default: 20% for 6 months
Strategic Partner: 35% lifetime
```

#### Content Creators

Provide fixed period commissions for content creators who focus on promotional campaigns.

```
Default: 25% for 3 months
Creator: 40% for 1 month
```

#### New Affiliates

Offer fixed period higher rates to incentivize new affiliates to get started.

```
Default: 25% lifetime
New Affiliate: 45% for 1 month
```

#### Enterprise Partners

Create custom fixed-amount commissions for enterprise partners based on negotiated terms.

```
Default: 20% of sale
Enterprise: $500 per customer
```

## Best Practices

### Determining the Right Commission Rate

When setting your commission rate, consider these factors:

-   **Profit Margins:** Ensure your commission rates allow you to maintain healthy profit margins
-   **Industry Standards:** Research what competitors offer to ensure your rates are competitive
-   **Customer Lifetime Value:** Consider the long-term value of each customer, not just their initial purchase
-   **Acquisition Costs:** Compare affiliate commissions to your other customer acquisition costs

### Recommended Commission Structures

#### For SaaS Products

-   Percentage-based: 20-40% of the first month, or 15-30% recurring
-   Commission duration: Lifetime or 3-12 months
-   Payout frequency: Monthly

#### For Digital Products

-   Percentage-based: 30-50% of purchase price
-   Commission duration: Lifetime or fixed period
-   Payout frequency: Monthly or bi-weekly

#### For E-commerce

-   Percentage-based: 5-15% of purchase amount
-   Commission duration: Lifetime or fixed period
-   Payout frequency: Monthly

#### For Membership Sites

-   Percentage-based: 20-40% of membership fee
-   Commission duration: 6-12 months or lifetime
-   Payout frequency: Monthly

## Next Steps

-   Learn how to [manage payouts](/docs/payouts) to your affiliates
-   Explore [tracking options](/docs/tracking) for recording referrals and conversions
-   Set up [Stripe integration](/docs/stripe) for automated commission tracking

---



<!-- ===== /docs/payouts ===== -->

# Affiliate Payouts

> Source: https://refgrow.com/docs/payouts

Managing payments to your affiliates.

## Overview

Efficiently managing affiliate payouts is critical for maintaining a successful affiliate program. Affiliates are more likely to actively promote your products when they know they will be paid accurately and on time.

Refgrow offers multiple options for processing payouts to your affiliates, from manual payments to fully automated processing. Affiliates can request payouts directly from the widget or portal, and you choose whether to approve each request manually or let Refgrow send the money automatically via PayPal/Wise.

## How the Payout Flow Works

The full payout cycle happens in three steps:

1.  **Affiliate adds a payment method.** In the embedded widget or affiliate portal, they open _Settings → Payment Method_ and enter their PayPal email, Wise email, bank details, or other payout details.
2.  **Affiliate clicks "Request Payout".** Once their eligible earnings reach your minimum payout amount (and the hold period has passed), a green _💸 Request Payout_ button appears next to their unpaid balance. The button shows the exact eligible amount.
3.  **The request is processed** according to your selected mode — manual approval or fully automatic (see below). The affiliate's balance, conversions, and payment history are updated automatically once the payout is sent.

**What affiliates see:** the Request Payout button only appears when the affiliate has a payment method on file AND their eligible earnings meet your minimum. Earnings still inside the hold period are shown separately as "on hold" so there is no confusion.

## Manual vs Automatic Payouts

Refgrow supports two payout modes. You can switch between them any time from **Dashboard → Payouts** using the toggle at the top of the page. Manual is the default — nothing leaves your account without your approval.

### Manual approval (default)

When an affiliate requests a payout, a notification lands on your Payouts page and in Telegram. You review the request, then process it with one click using the bulk payout tools (PayPal, Wise, or Mark-as-Paid for manual transfers).

**Best for:** programs that want a human check before any money moves, teams handling taxes manually, or owners who batch payouts weekly/monthly.

### Fully automatic

When an affiliate clicks Request Payout, Refgrow instantly processes the payment through your configured provider. PayPal is used first if configured, otherwise Wise. The money is sent, balance is updated, and the affiliate gets an email — all without you touching the dashboard.

**Best for:** high-trust programs, established affiliate networks, and programs where you want zero-friction payouts as a competitive advantage.

### Enabling Automatic Payouts

1.  Configure PayPal or Wise in **Settings → Payouts** (see below)
2.  Go to **Dashboard → Payouts**
3.  Click the _Automatic payouts_ toggle at the top of the page. The toggle is disabled (manual mode) by default
4.  Confirm your provider is configured. If no provider is found, Refgrow will fall back to manual review and show a warning

**Safety net:** every payout request is tracked in an internal state machine (`pending → processing → sent → recorded`) with a unique constraint that prevents an affiliate from having two in-flight payouts at once. If PayPal/Wise rejects a request, the reserved balance is automatically refunded, the affiliate sees a safe error, and you get a Telegram alert. Auto- payout will only enable when we can successfully verify your PayPal/Wise credentials.

## Payout Settings

### Setting Payout Frequency

Determine how often you will process affiliate payments:

1.  Go to your program settings
2.  Navigate to the "Payouts" tab
3.  Select your preferred payout frequency:
    -   **Weekly:** Process payments every week
    -   **Bi-weekly:** Process payments every two weeks
    -   **Monthly:** Process payments once per month (most common)
    -   **Quarterly:** Process payments every three months
4.  Save your settings

The frequency you choose will be communicated to your affiliates in their dashboard.

### Minimum Payout Amount

Set a minimum threshold that affiliates must reach before receiving a payout:

1.  In the "Payouts" tab of your program settings
2.  Enter your minimum payout amount (e.g., $50, $100)
3.  Save your settings

Affiliates will only be eligible for payment when their unpaid earnings meet or exceed this threshold. This helps reduce the administrative costs of processing many small payments.

### Hold Period Settings

Configure a hold period to protect against refunds and chargebacks before processing payouts:

1.  In the "Payouts" tab of your program settings
2.  Enter your desired hold period in days (0-365)
3.  Save your settings

**How Hold Periods Work:**

-   **0 days:** Earnings are immediately eligible for payout after conversion
-   **30+ days:** Earnings must wait the specified number of days from the conversion date before becoming eligible
-   **Protection:** Helps protect against refunds, chargebacks, and subscription cancellations
-   **Transparency:** Affiliates can see both their total earnings and payout-eligible earnings separately

**Best Practice:** Common hold periods are 30 days for digital products, 60-90 days for physical products, or 0 days for established programs with low refund rates.

#### Hold Period Display

When a hold period is configured:

-   Affiliates see separate "Total Earnings" and "Available for Payout" amounts
-   Earnings still in the hold period are clearly marked with release dates
-   Payout requests only process eligible earnings
-   Admin dashboard shows held vs. eligible earnings for all affiliates

## Payment Methods

### Adding Payment Methods

Configure the payment methods you offer to affiliates:

1.  Go to your program settings
2.  Navigate to the "Payouts" tab
3.  In the "Available Payment Methods" section, add methods like:
    -   PayPal
    -   Wise (formerly TransferWise)
    -   Bank Transfer
    -   Payoneer
    -   Crypto
4.  Save your settings

Affiliates will be able to choose their preferred payment method from your list of options.

### Payment Integration Setup

For automated bulk payouts, set up payment integrations:

#### PayPal Integration

1.  In the "Payouts" tab, find the "Payment Integration Settings" section
2.  Enter your PayPal Client ID and Client Secret
3.  Save your settings

#### Wise Integration

1.  Get your Wise API Token from the [Wise Developer Portal](https://wise.com/developer-portal)
2.  In the "Payouts" tab, find the "Payment Integration Settings" section
3.  Enter your Wise API Token in the provided field
4.  Click the "Test Connection" button to verify your token and automatically detect your Profile ID
5.  Save your settings once the connection test is successful

**Note:** Your Wise Profile ID will be automatically detected when you test the connection. You do not need to find it manually.

## Processing Payouts

### Accessing the Payments Page

To manage payouts to your affiliates:

1.  Log in to your Refgrow dashboard
2.  Select the program you want to manage
3.  Navigate to the "Payouts" tab

Here you will see a list of all your affiliates with their payment details and earnings.

### Manual Payouts

In manual mode (the default), affiliates trigger payouts via the Request Payout button, and you approve each one from the dashboard. You can also start payouts yourself without waiting for a request — both paths end up on the same Payouts page:

1.  On the Payouts page, find the affiliate you want to pay
2.  Review their unpaid earnings and payment details
3.  Pick a method at the top of the page:
    -   **PayPal** or **Wise** — Refgrow sends the payment through the integration automatically
    -   **Manual (Mark as Paid)** — you send the money yourself (bank transfer, crypto, etc.) and mark it paid inside Refgrow so the affiliate balance is updated
4.  Click _Pay_ next to the affiliate, or select multiple rows and use _Pay Selected_ / _Pay All Eligible_
5.  Confirm the amount and method in the modal
6.  The system records the payment, updates the affiliate's payment history, sends them an email notification, and clears the unpaid balance

**Note:** pending payout requests from affiliates are shown in the Payouts page notification area and also sent to your configured Telegram bot — so you do not miss them even if you do not log in daily.

### Bulk Automated Payouts

For processing multiple payouts at once:

1.  On the Payouts page, select the affiliates you want to pay by checking the boxes next to their names
2.  Choose the payment method (PayPal or Wise) from the dropdown menu
3.  Click the "Process Bulk Payout" button
4.  Review the summary showing total affiliates and amount
5.  Confirm the action

Refgrow will automatically process the payments through the selected integration and update the payment status for each affiliate.

#### How Wise Payouts Work

When using Wise for bulk payouts, the system works intelligently to send money to your affiliates:

-   **Wise Account Holders:** If an affiliate has a Wise account with the email they used to register, money is sent directly to their Wise balance
-   **Bank Account Fallback:** If an affiliate does not have a Wise account, the system will attempt to send money to their bank account based on their provided details
-   **Automatic Currency Conversion:** The system automatically handles currency conversion if needed (e.g., USD to EUR)
-   **Smart Routing:** Wise automatically determines the best way to deliver the payment based on the recipient's location and available options

**Note:** Automated bulk payouts are available for users on Pro and Business plans.

**Sandbox vs Production:** Make sure your system is configured for the correct Wise environment. Sandbox is used for testing, while Production is used for real payments.

## Payment History

Refgrow maintains a complete history of all payments made to affiliates:

-   Each affiliate's record shows their total paid earnings
-   The date of their last payment is displayed
-   You can view a detailed payment history for each affiliate

This payment history helps with record-keeping and can be useful for tax reporting purposes.

## Affiliate Payment Information

### How Affiliates Enter Payment Details

Affiliates can enter and update their payment information through the embedded widget or the hosted affiliate portal (whichever you offer in your program):

1.  They open the widget or portal and sign in
2.  Navigate to the "Settings" or "Payment" section
3.  Select their preferred payment method from your available options
4.  Enter the required details for that payment method:
    -   **PayPal:** Their PayPal email address
    -   **Wise:** Just their email address (if they have a Wise account) or their bank details
    -   **Bank Transfer:** Bank account information (account number, routing number, etc.)
    -   **Other methods:** Relevant account details as required
5.  Save their settings

### Requesting a Payout

After saving a payment method and earning enough to hit your minimum payout amount, affiliates see a _💸 Request Payout_button in both the widget and the portal. The button is visible on the Payouts / Payment Method view and shows the exact eligible amount, for example: `💸 Request Payout ($127.50)`.

-   **Eligible amount:** equals unpaid earnings minus anything still inside the hold period. The button is disabled if eligible earnings are below your minimum
-   **Held earnings:** shown separately with a small "on hold (Nd)" label so affiliates know when they will unlock
-   **No payment method:** the button is replaced with a prompt to configure one in Settings
-   **After clicking:** the affiliate sees an immediate confirmation. If you use manual mode, the request waits for your approval. If you use automatic mode, the payment is sent instantly and the success message includes the provider used

**Tip for Wise payments:** If your affiliate has a Wise account, they only need to provide the email address associated with their Wise account. The system will automatically send money to their Wise balance.

## Best Practices

### Payout Schedule Consistency

Maintain a consistent payout schedule to build trust with your affiliates. If you say you will pay monthly, ensure payments are processed at the same time each month.

### Payment Method Variety

Offer multiple payment methods to accommodate global affiliates. Consider Wise for international payments, as it often has better exchange rates and lower fees than traditional methods.

### Communication

Clearly communicate your payout policies, including frequency, minimum thresholds, and any requirements for receiving payment.

### Record Keeping

Maintain accurate records of all affiliate payments for accounting and tax purposes, and consider providing affiliates with annual earnings statements.

### Testing Before Going Live

Always test your payment integrations in sandbox mode before processing real payments. This helps you identify any issues and ensures a smooth experience for your affiliates.

## Self-Billing Invoices

Refgrow automatically generates self-billing invoices for affiliate payouts, helping you stay compliant with EU VAT regulations and simplify accounting for both you and your affiliates.

### Setting Up Invoice Details

To configure invoices for your program:

1.  Go to **Settings → Invoices** in your project dashboard
2.  Enter your company details:
    -   **Company name** — appears on all generated invoices
    -   **Company address** — full postal address
    -   **Country** — used for EU VAT calculations
    -   **VAT number** — your EU VAT registration number (optional)
    -   **Additional info** — any extra text to display on invoices (bank details, payment terms, etc.)
3.  Save your settings

### Requiring Affiliate Tax Data

You can optionally require affiliates to provide their tax information (VAT ID, tax number, or company details) before they can request payouts:

1.  In the Invoices settings tab, enable **"Require affiliate tax data"**
2.  Optionally add a custom description explaining what information you need
3.  Affiliates will see a "Tax Information" section in their widget settings

### EU VAT Validation

When an affiliate enters a VAT ID, Refgrow validates it in real-time against the EU VIES (VAT Information Exchange System) database. This ensures that only valid, active VAT numbers are accepted.

-   Valid EU VAT IDs are marked with a green checkmark
-   Invalid IDs show an error message
-   Non-EU affiliates can still enter their local tax/company number without VIES validation

### Invoice Download for Affiliates

Affiliates can download PDF invoices directly from their embedded widget dashboard:

-   Each paid payout in the payment history shows a download icon
-   Clicking the icon generates and downloads a PDF invoice
-   The invoice includes your company details, the affiliate's information, payout amount, date, and VAT details
-   Invoices are generated on the fly — no manual creation needed

**Note:** Self-billing invoices are available on all plans (Starter, Pro, Business, and Enterprise). Make sure to fill in your company details in Settings → Invoices for invoices to include the correct information.

## Troubleshooting

### Affiliate Missing Payment Details

If an affiliate is eligible for payment but has not provided payment details:

1.  Contact them directly to request their payment information
2.  Send them instructions on how to update their payment details
3.  Consider setting up automatic reminders for affiliates with missing payment information

### Bulk Payout Failures

If a bulk payout fails, check these common issues:

1.  Verify your payment integration credentials are correct and up to date
2.  Ensure you have sufficient funds in your integrated payment account
3.  Check that affiliates' payment details are valid
4.  Review any specific error messages provided by the payment processor

### Wise Integration Issues

Common Wise integration problems and solutions:

#### Connection Test Fails

-   **Invalid Token:** Verify your API token is correct and has not expired
-   **Wrong Environment:** Make sure you are using the right token for your environment (sandbox vs production)
-   **Permission Issues:** Ensure your API token has the required permissions for transfers

#### Profile ID Not Detected

-   Try regenerating your API token in the Wise Developer Portal
-   Ensure your Wise account is fully verified and active
-   Contact Wise support if you continue having issues

#### Payout Transfers Fail

-   **Insufficient Balance:** Ensure your Wise account has enough funds
-   **Recipient Issues:** Verify the affiliate's email or bank details are correct
-   **Manual Approval Required:** Some transfers may require manual approval in your Wise account
-   **Currency Not Supported:** Check if the target currency is supported by Wise

**Environment Switching:** To switch from sandbox to production, contact support. The environment is controlled server-side for security.

---



<!-- ===== /docs/coupons ===== -->

# Coupon Tracking

> Source: https://refgrow.com/docs/coupons

Attribute sales to affiliates using unique coupon codes.

## Overview

Refgrow allows you to track affiliate sales not only through referral links but also via unique coupon codes. This provides an alternative or supplementary method for affiliates to drive sales and get credit for them. Coupon tracking works with Stripe, LemonSqueezy (via webhooks), and manual conversion tracking.

## How Coupon Tracking Works

1.  **Create Coupons in Refgrow:**
    
    Navigate to your Project Dashboard → Coupons. Here you can create coupon codes and assign them to specific affiliates. For each coupon in Refgrow, you can optionally provide:
    
    -   **Stripe Coupon ID:** The Coupon ID from your Stripe Dashboard (Dashboard → Products → Coupons → click coupon → Details). Can be custom text like `SAVE20`, `summer-discount`, or auto-generated like `coup_XXXXXXXX`.
    -   **LemonSqueezy Discount Code:** If this coupon in Refgrow corresponds to a specific Discount Code you have created in your LemonSqueezy store. This is used by Refgrow to match webhook events from LemonSqueezy.
    
    The main "Your Coupon Code" in Refgrow is the code your customers will typically use, and it is also used for manual tracking.
    
2.  **Affiliate Shares Coupon:**
    
    Your affiliate shares their assigned coupon code (e.g., "AFFILIATE20") with their audience.
    
3.  **Customer Makes a Purchase:**
    
    A customer uses this coupon code during the checkout process on your website (integrated with Stripe or LemonSqueezy).
    
4.  **Conversion Attribution:**
    -   **Via Webhooks (Stripe/LemonSqueezy):**
        
        When a purchase is completed, Stripe or LemonSqueezy sends a webhook event to Refgrow. This event contains information about the discount or coupon used.
        
        Refgrow uses an improved matching system that attempts to find the affiliate in this priority order:
        
        -   **For Stripe:**
            1.  Matches by what the customer actually typed during checkout
            2.  Matches by Stripe Coupon ID (if configured)
            3.  Matches by Stripe Promotion Code ID (if configured)
        -   **For LemonSqueezy:** Matches by the "LemonSqueezy Discount Code" text you entered.
        
        If a match is found and the coupon is active and assigned to an affiliate, Refgrow attributes the sale to that affiliate and calculates the commission.
        
    -   **Via Manual Tracking JS Call:**
        
        You can also track conversions made with a coupon manually by calling the `Refgrow()` JavaScript function. Pass the coupon code as the fourth argument:
        

```
// Example: Track a $50 purchase made with coupon 'AFFILIATE20'
Refgrow(50, 'purchase', 'customer@example.com', 'AFFILIATE20');
```

Refgrow will then look up 'AFFILIATE20' in your project's coupons and attribute the sale accordingly.

**Simplified Setup:** In most cases, you only need to set the "Your Coupon Code" to match what customers type. The system will automatically find them by the customer-entered code. Use Stripe Coupon ID or Promotion Code ID only if you need precise control over matching.

## Setting Up Coupons

1.  Go to your **Project Dashboard**.
2.  Navigate to the **Coupons** tab from the sidebar.
3.  Click on **"Add Coupon"**.
4.  Fill in the details:
    -   **Assign to Affiliate:** Select the affiliate this coupon belongs to.
    -   **Your Coupon Code:** The primary code customers will use (e.g., "AFFILIATE20"). This must be unique per project. **In most cases, this is all you need to set!**
    -   **Stripe Coupon ID (Optional):** The Coupon ID from your Stripe Dashboard → Products → Coupons → click coupon → Details. Can be custom text like `SAVE20` or auto-generated like `coup_XXXXXXXX`. Use only if you need precise Stripe integration.
    -   **LemonSqueezy Discount Code (Optional):** Enter the exact discount code text from your LemonSqueezy store if this code corresponds to a LemonSqueezy discount. This is vital for webhook tracking with LemonSqueezy.
    -   **Status:** Set to Active or Inactive.
5.  Click **"Add Coupon"**.

You can edit or delete coupons from the same page.

### Auto-Generate Coupon Settings

When enabled, every new affiliate will automatically get their own unique coupon code. You can configure additional restrictions:

-   **Eligible for first-time order only:** Restricts the coupon to customers who have not made a purchase before.
-   **Limit to a specific customer:** Restricts the coupon to a specific email address.
-   **Add an expiration date:** Sets when the coupon will expire.
-   **Require minimum order value:** Sets a minimum order amount required to use the coupon.
-   **Limit the number of times this code can be redeemed:** Sets maximum number of times the coupon can be used.

### Generation Mode (Stripe)

The auto-coupon block has two modes that change how Refgrow talks to your Stripe account.

-   **Refgrow creates a fresh Stripe Coupon per affiliate (default):**For each new affiliate, Refgrow calls Stripe and creates a new Coupon using the discount config you set in the form (percentage or fixed amount, duration, max redemptions, etc.), then a Promotion Code on top of that Coupon. One Coupon and one Promotion Code per affiliate. Use this when you do not already maintain a discount in Stripe and want Refgrow to manage the full lifecycle.
-   **Use my existing Stripe Coupon as a template:**You create a single Coupon yourself in Stripe (set the discount, currency, products it applies to, duration), copy its ID, and paste it into the "Stripe Coupon ID" field on the Coupons page. Refgrow then only mints Promotion Codes against that one Coupon, one per affiliate. The discount terms live entirely in your Stripe dashboard. Use this when you already manage discount logic in Stripe and just want Refgrow to generate per-affiliate codes against it.

When you save a template ID, Refgrow calls `stripe.coupons.retrieve` to confirm the Coupon exists on your Stripe account and rejects the save if it does not. The Promotion Codes it generates carry metadata identifying the affiliate and the project, so you can audit them from the Stripe dashboard.

To re-issue an existing affiliate's code (for example after you switch modes or change the template), use the "Generate for all affiliates" button on the Coupons page, or call `POST /api/projects/:id/coupons/regenerate` with`{ "affiliate_id": ... }` or `{ "affiliate_email": "..." }` for a single one. The underlying Stripe Coupon and Promotion Code are intentionally left alive so already-distributed links keep working; prune them in your Stripe dashboard if you want them gone.

**Note:** If a conversion is made using both a referral link (cookie present) AND a coupon code, the coupon code attribution will typically take precedence if the webhook identifies the coupon successfully.

## Understanding Stripe Objects

Stripe has different types of discount-related objects that can be confusing. Here is what each one means:

Object Type

What It Is

Example ID

Where to Find

**Coupon ID**

The actual discount configuration in Stripe

`SAVE20`, `summer-discount`, `coup_abc123`

Dashboard → Products → Coupons → click coupon → Details

**Customer Entered Code**

What customers actually type during checkout

`SAVE20PERCENT`, `HZEFAY`

This is what appears in the discount field during checkout

**Note:** In most cases, you only need to set the "Your Coupon Code" field to match what customers type during checkout. The system will automatically find the affiliate when a customer uses that exact code.

## Use Cases

-   **Influencer Marketing:** Provide unique coupon codes to influencers instead of or in addition to referral links.
-   **Podcast/Offline Advertising:** Share memorable coupon codes in audio or print media.
-   **Partner Promotions:** Offer special discount codes to specific partners.
-   **Simplified Sharing:** Some affiliates and customers find coupon codes easier to share and remember than long URLs.

## Troubleshooting

-   **Coupon not tracking via Stripe Webhook:**
    1.  First, ensure your "Your Coupon Code" in Refgrow matches what customers type during checkout.
    2.  If you are using specific Stripe IDs, verify they match exactly in your Stripe Dashboard.
    3.  Use the built-in diagnostic tools in Refgrow (Coupons → Diagnostics dropdown) to validate your setup.
    4.  Check server logs for `[COUPON DEBUG]` messages to see exactly what Refgrow received from Stripe.
-   **Coupon not tracking via LemonSqueezy Webhook:** Ensure the "LemonSqueezy Discount Code" in Refgrow exactly matches the discount code text used in the LemonSqueezy transaction and passed in the webhook. Check your LemonSqueezy webhook logs and Refgrow server logs.
-   **Manual coupon tracking not working:** Double-check that you are passing the correct coupon code (the one defined as "Your Coupon Code" in Refgrow) to the `Refgrow()` JavaScript function.
-   **Still having issues?** Use the new diagnostic tools available in your Coupons dashboard to validate configuration and find potential problems automatically.

---



<!-- ===== /docs/widget ===== -->

# Affiliate Widget

> Source: https://refgrow.com/docs/widget

Learn how to integrate the Refgrow affiliate dashboard into your website.

## Overview

The Refgrow affiliate widget provides a complete dashboard for your affiliates to track their referrals, access promotional materials, and manage their account. This guide will help you integrate the widget into your website.

## Integration Options

### Option 1: With User Authentication

If your website has user authentication, use this code and dynamically set the user's email:

```
<div id="refgrow"
    data-project-id="YOUR_PROGRAM_ID"
    data-project-email="user@example.com"
    data-lang="en">
</div>
<script src="https://scripts.refgrowcdn.com/page.js" async defer></script>
```

**Parameters:**

-   **data-project-id:** Your unique program ID (replace YOUR\_PROGRAM\_ID with your actual program ID).
-   **data-project-email:** The email of the currently logged-in user (replace dynamically when rendering your page).
-   **data-lang:** (Optional) Specify the language for the widget. If omitted, the project's default language or English will be used.

### Option 2: Without User Authentication

If you do not have user authentication or want to use the referral page's built-in authentication, use this code:

```
<div id="refgrow"
    data-project-id="YOUR_PROGRAM_ID"
    data-lang="en">
</div>
<script src="https://scripts.refgrowcdn.com/page.js" async defer></script>
```

**Parameters:**

-   **data-project-id:** Your unique program ID.
-   **data-lang:** (Optional) Specify the language for the widget.

This option will use the referral page's built-in authentication system. Users will need to enter their email and verify it.

## Data Attributes

Attribute

Required

Description

`data-project-id`

Yes

Your Refgrow project ID

`data-project-email`

Recommended

Current user's email for affiliate identification

`data-lang`

No

Language code (e.g., `en`, `de`, `fr`). Auto-detected by default.

## Widget Appearance

You can customize the appearance of your affiliate dashboard in your program settings:

-   **Primary Color:** Sets the main color for buttons and highlights
-   **Secondary Color:** Used for secondary elements and accents
-   **Font Color:** Controls the text color throughout the dashboard
-   **Title:** Customize the headline text for your affiliate program
-   **Description:** Add a custom description explaining your program

These settings can be configured during the onboarding process or updated any time from your program settings.

### Removing Branding

On paid plans (Starter and above), you can remove the "Powered by Refgrow" footer from the widget.

## Widget Blocks

The widget is composed of configurable blocks. You can enable, disable, and reorder blocks from your Refgrow project settings under **Widget Design**. Features include drag-and-drop block reordering with visual handles, individual hide/show toggles for all widget sections, and real-time preview with instant updates.

### Available Blocks

-   **Header** — program title and description
-   **Share Links** — referral URL with a copy button
-   **Coupon Code** — affiliate's assigned coupon code
-   **Statistics** — click count, referral count, and conversion metrics
-   **Daily Stats** — daily performance chart
-   **Earnings** — total and pending commission amounts
-   **Payment Methods** — payout configuration
-   **Payment History** — past payouts with status
-   **Commission Levels** — multilevel commission progress (paid plans)
-   **Multi-Tier Commissions** — sub-affiliate earnings (paid plans)
-   **Promotional Materials** — banners, text links, and social share templates

### Block Configuration

Block configuration is stored in `projects.widget_blocks_config` as a JSON array. Each block has:

```
[
  { "id": "header", "enabled": true, "order": 1 },
  { "id": "share_links", "enabled": true, "order": 2 },
  { "id": "coupon_code", "enabled": true, "order": 3 },
  { "id": "stats", "enabled": true, "order": 4 },
  { "id": "daily_stats", "enabled": true, "order": 5 },
  { "id": "earnings", "enabled": true, "order": 6 },
  { "id": "payment_methods", "enabled": true, "order": 7 },
  { "id": "payment_history", "enabled": false, "order": 8 },
  { "id": "commission_levels", "enabled": false, "order": 9 },
  { "id": "multi_tier", "enabled": false, "order": 10 },
  { "id": "promotional_materials", "enabled": false, "order": 11 }
]
```

## Integration Examples

### Basic HTML Page

```
<!DOCTYPE html>
<html>
<head>
    <title>My Affiliate Program</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
    <header>
        <h1>My Website</h1>
        <nav>
            <a href="/">Home</a>
            <a href="/affiliate">Affiliate Program</a>
        </nav>
    </header>

    <main>
        <h2>Join Our Affiliate Program</h2>

        <!-- Refgrow Widget -->
        <div id="refgrow"
            data-project-id="YOUR_PROGRAM_ID"
            data-lang="en">
        </div>
        <script src="https://scripts.refgrowcdn.com/page.js" async defer></script>
    </main>

    <footer>
        <p>&copy; 2025 My Company</p>
    </footer>

    <!-- Tracking Script for all pages -->
    <script src="https://scripts.refgrowcdn.com/latest.js"
        data-project-id="YOUR_PROGRAM_ID"></script>
</body>
</html>
```

### Server-Side Dynamic Example (Node.js + EJS)

```
<!-- affiliate-page.ejs -->
<!DOCTYPE html>
<html>
<head>
    <title>Affiliate Program - <%= siteName %></title>
</head>
<body>
    <main>
        <h1>Our Affiliate Program</h1>

        <% if (user) { %>
            <!-- Authenticated user -->
            <div id="refgrow"
                data-project-id="<%= process.env.REFGROW_PROGRAM_ID %>"
                data-project-email="<%= user.email %>"
                data-lang="en">
            </div>
        <% } else { %>
            <!-- Non-authenticated user -->
            <div id="refgrow"
                data-project-id="<%= process.env.REFGROW_PROGRAM_ID %>"
                data-lang="en">
            </div>
        <% } %>

        <script src="https://scripts.refgrowcdn.com/page.js" async defer></script>
    </main>

    <script src="https://scripts.refgrowcdn.com/latest.js"
        data-project-id="<%= process.env.REFGROW_PROGRAM_ID %>"></script>
</body>
</html>
```

## Internationalization (i18n)

The widget supports 9 languages out of the box. It loads translations from `/locales.json` and auto-detects the user's language from their browser settings.

Supported languages include:

-   English, Spanish, French, German, Portuguese, Italian
-   Dutch, Swedish, Norwegian, Danish, Finnish
-   Polish, Czech, Romanian, Hungarian
-   Russian, Ukrainian, Turkish
-   Japanese, Korean, Chinese (Simplified)
-   Arabic, Hebrew

Override the auto-detected language with `data-lang="fr"` on the embed div.

## Programmatic Control

The widget exposes a global `Refgrow` object for programmatic control:

```
// Identify a user after login
Refgrow.identify('user@example.com');

// Switch language
Refgrow.setLanguage('de');

// Listen for events
Refgrow.on('affiliate:signup', (data) => {
  console.log('New affiliate signed up:', data.email);
});
```

## Single-Page App Integration

For SPAs (React, Vue, Angular), load the widget script once and mount the container:

```
// React example
import { useEffect, useRef } from 'react';

function AffiliateWidget({ projectId, userEmail }) {
  const containerRef = useRef(null);

  useEffect(() => {
    const script = document.createElement('script');
    script.src = 'https://scripts.refgrowcdn.com/page.js';
    script.async = true;
    script.defer = true;
    containerRef.current?.appendChild(script);

    return () => {
      script.remove();
    };
  }, [projectId, userEmail]);

  return (
    <div
      id="refgrow"
      ref={containerRef}
      data-project-id={projectId}
      data-project-email={userEmail}
    />
  );
}
```

## Important Notes

-   Place the widget code where you want the affiliate program to appear on your website.
-   For Option 1 (with auth), ensure you dynamically set the user's email when rendering your page.
-   For Option 2 (without auth), users will need to authenticate through the referral page interface.
-   The affiliate program will automatically adapt to your website's styling.
-   You can customize the appearance in your program settings.
-   Make sure the tracking script is included on all pages where you want to track referral clicks.

## Troubleshooting

### Widget not displaying

1.  Verify your program ID is correct
2.  Check if the page.js script is properly loaded
3.  Look for console errors in browser developer tools
4.  Ensure your domain is allowed in program settings

### Authentication issues

1.  If using your own authentication, verify that the data-project-email attribute is set correctly
2.  For built-in authentication, ensure users can access the login form
3.  Check for any cross-origin issues if embedding on a different domain

### Content Security Policy (CSP)

For the affiliate dashboard widget, add `https://refgrow.com` or `https://*.refgrow.com` to your `script-src` and `connect-src` directives. Also add `https://scripts.refgrowcdn.com` to `script-src`.

## Next Steps

-   [Set Up Tracking](/docs/tracking) — learn how to track conversions and attribute sales to affiliates
-   [Configure Payments](/docs/stripe) — set up payment methods and commission structures
-   [API Reference](/docs/api-reference) — build custom integrations

---



<!-- ===== /docs/tracking ===== -->

# Tracking Setup

> Source: https://refgrow.com/docs/tracking

Learn how to track referrals and conversions with Refgrow.

## How Tracking Works

Refgrow uses a combination of URL parameters and cookies to track referrals and attribute conversions accurately. Here is how it works:

### 1\. Referral Link

Affiliate shares their unique referral link with the `ref` parameter.

### 2\. Click Tracking

When someone clicks the link, Refgrow records the click and sets a tracking cookie.

### 3\. Conversion

When the user converts (signs up, makes a purchase), the conversion is tracked.

### 4\. Attribution

The conversion is attributed to the affiliate based on the tracking cookie.

## Setting Up Basic Tracking

### 1\. Add Tracking Script

First, add the Refgrow tracking script to your website:

```
<!-- Add this to the <head> section of your pages -->
<script
  src="https://scripts.refgrowcdn.com/latest.js"
  data-project-id="YOUR_PROJECT_ID"
  async defer>
</script>
```

### 2\. Track Conversions

There are several ways to track conversions with Refgrow:

#### Manual Tracking

```
// Track a signup
Refgrow(0, 'signup', 'user@example.com');

// Track a purchase
Refgrow(99.99, 'purchase', 'user@example.com');

// Track a purchase with the payment's own id and currency
Refgrow(24000, 'purchase', 'user@example.com', {
  reference: 'txn_8f21c0',
  currency: 'XOF'
});
```

**Parameters:**

-   **value:** The monetary value of the conversion (use 0 for non-monetary conversions like signups)
-   **type:** The type of conversion ('signup' or 'purchase')
-   **email:** The email of the user who completed the conversion
-   **options:** Optional fourth argument, described below

#### Options

Worth setting on purchases, particularly when the call runs on an order confirmation page.

-   **reference:** Your own id for the payment, for example the transaction id from your payment provider. Refgrow records a conversion with a given reference once, so a customer refreshing the confirmation page cannot pay the affiliate twice for one sale.
-   **currency:** Three letter code for what the customer actually paid, for example EUR or XOF. Defaults to your project currency. Refgrow never converts between currencies: balances and payouts stay in the currency the commission was earned in.
-   **couponCode:** The discount code used at checkout, when you attribute by coupon rather than by referral link.

**Note:** This call runs in the visitor's browser, so it is missed if they close the tab before the page loads. If the conversion is a payment and you have API access, record it from your backend with [POST /api/v1/conversions](/docs/api-reference) instead, which does not depend on the customer staying on the page.

## Configuration Options

Customize tracking behavior with data attributes on the script tag:

Attribute

Default

Description

`data-project-id`

—

Required. Your Refgrow project ID.

`data-param`

`ref`

URL parameter name for the referral code.

`data-cookie-days`

`90`

Cookie expiration in days.

`data-cookie-domain`

Current domain

Cookie domain for cross-subdomain tracking.

### Example with Custom Options

```
<script
  src="https://scripts.refgrowcdn.com/latest.js"
  data-project-id="YOUR_PROJECT_ID"
  data-param="via"
  data-cookie-days="30"
  data-cookie-domain=".yoursite.com"
  async defer>
</script>
```

With this configuration, referral links would use `?via=CODE` instead of `?ref=CODE`, cookies expire after 30 days, and the cookie is shared across all subdomains of `yoursite.com`.

## Integration with Payment Processors

### Stripe Integration

To integrate with Stripe:

1.  Go to your project settings
2.  Click "Create Stripe API Key" button or enter your existing key
3.  The system will automatically configure webhooks and start tracking your Stripe payments

**Note:** See the [Stripe integration guide](/docs/stripe) for detailed setup instructions including attribution methods and Payment Links support.

### LemonSqueezy Webhook Setup

1.  Go to your LemonSqueezy Dashboard → Settings → Webhooks
2.  Click "Add webhook"
3.  Set the webhook URL to: `https://refgrow.com/webhook/lemonsqueezy/YOUR_PROJECT_ID`
4.  Replace YOUR\_PROJECT\_ID with your actual project ID
5.  Select the following events:
    -   `order_created`
    -   `subscription_created`
    -   `subscription_updated`
6.  Click "Create webhook" to save

Ensure you have set your LemonSqueezy API Key in your project settings.

## Cookie Lifetime Configuration

You can configure how long the referral tracking cookie lasts in your project settings:

1.  Go to your project settings
2.  Find the "Cookie Lifetime" setting
3.  Set the number of days you want the tracking cookie to last
4.  Save your settings

The default cookie lifetime is 30 days. This means that if a user clicks an affiliate link and makes a purchase within 30 days, the affiliate will receive credit for the conversion.

## Cross-Domain Tracking

If your marketing site (e.g., `yoursite.com`) and your app (e.g., `app.yoursite.com` or `dashboard.yourproduct.io`) are on different domains, you need cross-domain tracking.

### Same root domain

If both sites share the same root domain, set the cookie domain to the root:

```
data-cookie-domain=".yoursite.com"
```

### Different domains

For completely different domains, configure your tracking domain in Refgrow project settings. The tracking script will append the referral code as a URL parameter when users navigate between domains.

## Setting Up Your Tracking Domain

For optimal tracking, you can configure a custom tracking domain:

1.  Go to your project settings
2.  Find the "Tracking Domain" setting
3.  Enter your domain (e.g., yourdomain.com)
4.  Save your settings

Using your own domain for tracking can improve conversion rates and build trust with your customers.

## Reading the Referral Cookie

To pass the referral code to your payment processor or backend:

```
// JavaScript (client-side)
function getRefgrowRef() {
  const match = document.cookie.match(
    /(?:^|;\s*)ref=([^;]*)/
  );
  return match ? decodeURIComponent(match[1]) : null;
}

const referralCode = getRefgrowRef();
if (referralCode) {
  // Pass to your checkout or signup flow
  console.log('Referred by:', referralCode);
}
```

## Server-Side Tracking

You can also read the referral cookie on the server side. For example, in Node.js/Express:

```
app.post('/signup', async (req, res) => {
  const referralCode = req.cookies.ref;

  if (referralCode) {
    // Record attribution via Refgrow API
    await fetch('https://refgrow.com/api/store-attribution', {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer rgk_YOUR_API_KEY',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        email: req.body.email,
        referral_code: referralCode
      })
    });
  }
});
```

## Content Security Policy

If your site uses a Content Security Policy (CSP), add Refgrow to your allowed sources:

```
Content-Security-Policy:
  script-src 'self' https://scripts.refgrowcdn.com https://refgrow.com;
  connect-src 'self' https://refgrow.com;
```

## Best Practices

### Security

-   Ensure your tracking script is loaded over HTTPS
-   Validate conversion data on your server
-   Review tracking logs regularly
-   Keep your API keys secure

### Performance

-   Place the tracking script in the `<head>` section
-   Track the most valuable conversion points
-   Test your tracking setup thoroughly
-   Monitor tracking for any issues

## Privacy & GDPR

The tracking script sets a first-party cookie scoped to your domain. It does not use third-party cookies, fingerprinting, or cross-site tracking. The cookie contains only the referral code and is not used for advertising.

If you need to delay cookie creation until consent is given, you can load the script conditionally after the user accepts cookies.

## Important Notes

-   The tracking script must be included on all pages where you want to track referral clicks and conversions.
-   For manual tracking, ensure that you call the Refgrow function after the tracking script has loaded and when you are certain the conversion has occurred.
-   Handle any errors that may occur during the tracking process to ensure a smooth user experience.
-   You can change the conversion tracking method in your project settings at any time.

## Next Steps

-   [Stripe Integration](/docs/stripe) — set up automatic commission tracking with Stripe
-   [Widget Customization](/docs/widget) — embed the affiliate dashboard
-   [API Reference](/docs/api-reference) — learn about programmatic conversion tracking

---



<!-- ===== /docs/customization ===== -->

# Dashboard Customization

> Source: https://refgrow.com/docs/customization

Personalizing the affiliate dashboard experience.

## Overview

Refgrow allows you to customize the appearance and functionality of your affiliate dashboard to match your brand identity and meet your specific requirements. This guide covers all the customization options available in Refgrow.

## Branding Options

### Logo and Favicon

Upload your company logo and favicon to create a branded experience:

1.  Go to your program settings
2.  Navigate to the "Widget" tab
3.  In the "Logo & Favicon" section:
    -   Upload your logo (recommended size: 200px x 50px)
    -   Upload your favicon (must be .ico format, 16px x 16px)
4.  Save your changes

Your logo will appear in the affiliate dashboard header, and your favicon will be displayed in the browser tab.

### Color Scheme

Customize the dashboard's color scheme to match your brand:

1.  In the "Widget" tab of your program settings
2.  Go to the "Colors" section
3.  Customize the following colors:
    -   **Primary Color:** Used for main buttons, links, and accents
    -   **Secondary Color:** Used for secondary elements and highlights
    -   **Background Color:** The main background color of the dashboard
    -   **Text Color:** The color of body text
    -   **Heading Color:** The color of headings and titles
4.  Use the color picker or enter hex color codes
5.  Preview your changes in real-time
6.  Save when satisfied

### Typography

Select fonts that align with your brand identity:

1.  In the "Widget" tab
2.  Go to the "Typography" section
3.  Choose from the available font families for:
    -   **Heading Font:** Used for titles and headings
    -   **Body Font:** Used for paragraphs and general text
4.  Adjust font sizes if needed
5.  Save your changes

Refgrow uses web-safe fonts and Google Fonts to ensure your dashboard looks consistent across all devices.

## Layout Customization

### Dashboard Sections

Choose which sections to display in the affiliate dashboard:

1.  Go to the "Layout" section in the "Widget" tab
2.  Enable or disable dashboard sections:
    -   **Overview:** Summary of performance metrics
    -   **Earnings:** Detailed commission information
    -   **Referrals:** List of referral activities
    -   **Marketing Materials:** Promotional resources
    -   **Payouts:** Payment history and requests
    -   **Settings:** Affiliate account settings
3.  Drag and drop to reorder sections
4.  Save your layout configuration

### Custom CSS

For advanced customization, add custom CSS to further style your dashboard:

1.  In the "Widget" tab, locate the "Advanced Customization" section
2.  Enter your custom CSS in the provided editor
3.  Preview changes in real-time
4.  Save when satisfied

Example custom CSS:

```
.dashboard-header {
  box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}

.stat-card {
  border-radius: 10px;
  transition: transform 0.2s;
}

.stat-card:hover {
  transform: translateY(-5px);
}
```

**Note:** Custom CSS is available for users on Pro and Business plans.

## Content Customization

### Welcome Message

Create a personalized welcome message for your affiliates:

1.  Go to the "Content" section in the "Widget" tab
2.  Edit the "Welcome Message" field
3.  Use the rich text editor to format your message
4.  Insert variables like `{{affiliate.name}}` to personalize the message
5.  Save your changes

This message will be displayed at the top of the affiliate dashboard.

### Custom Pages

Create custom pages for additional information or resources:

1.  In the "Content" section, click "Add Custom Page"
2.  Enter a title for your page
3.  Create your content using the rich text editor
4.  Choose where to display the page link (sidebar, footer, or both)
5.  Set the page order
6.  Save the page

Custom pages are perfect for affiliate guidelines, FAQs, or promotional tips.

### Email Templates

Customize the emails sent to affiliates:

1.  Go to the "Emails" section in your program settings
2.  Select the email template you want to customize:
    -   Welcome Email
    -   Password Reset
    -   Commission Notification
    -   Payout Confirmation
3.  Edit the subject line and email content
4.  Use variables to personalize emails
5.  Save your changes

All emails include your logo and follow your brand's color scheme.

## Marketing Materials

### Banner Ads

Upload banner ads for your affiliates to use:

1.  Go to the "Marketing" tab in your program settings
2.  In the "Banner Ads" section, click "Add New Banner"
3.  Upload your banner image (recommended sizes: 728x90, 300x250, 160x600)
4.  Add a description for the banner
5.  Set the banner status (active or inactive)
6.  Save the banner

Affiliates can copy the HTML code for these banners directly from their dashboard.

### Text Links

Create pre-written text links for affiliates:

1.  In the "Marketing" tab, go to the "Text Links" section
2.  Click "Add New Text Link"
3.  Enter the link text
4.  Specify the destination URL
5.  Add a description
6.  Save the text link

The system will automatically append the affiliate's referral code to these links.

### Downloadable Resources

Provide additional marketing materials:

1.  In the "Marketing" tab, go to the "Resources" section
2.  Click "Add New Resource"
3.  Upload your file (PDF, ZIP, etc.)
4.  Add a title and description
5.  Set a category for the resource
6.  Save the resource

These resources will be available for affiliates to download from their dashboard.

## Domain Customization

### Custom Domain

Use your own domain for the affiliate dashboard:

1.  Go to the "Settings" tab in your program settings
2.  Navigate to the "Domain" section
3.  Enter your custom domain (e.g., affiliates.yourcompany.com)
4.  Follow the DNS configuration instructions
5.  Verify your domain
6.  Save your settings

**Note:** Custom domains are available for users on Pro and Business plans.

### White Labeling

Remove Refgrow branding from the affiliate dashboard:

1.  In the "Settings" tab, find the "White Label" section
2.  Toggle the "Enable White Label" option
3.  Save your settings

This will remove all mentions of Refgrow from the affiliate dashboard, emails, and other user-facing elements.

**Note:** White labeling is available for users on Business plans.

## Mobile Responsiveness

All Refgrow dashboards are fully responsive, ensuring a great experience for affiliates on mobile devices. Your customizations will automatically adapt to different screen sizes, with some layout adjustments to optimize for mobile viewing.

You can preview how your dashboard looks on different devices:

1.  In the "Widget" tab, click the "Preview" button
2.  Use the device selector to switch between desktop, tablet, and mobile views
3.  Make any necessary adjustments to your design

## Best Practices

### Maintain Brand Consistency

Ensure your affiliate dashboard design aligns with your main website and other brand touchpoints for a seamless experience.

### Prioritize Readability

Choose color combinations that provide sufficient contrast for text readability, and avoid overly complex designs that can distract from important information.

### Test Thoroughly

Preview your customizations on multiple devices and browsers to ensure they look good everywhere, especially if you've added custom CSS.

### Update Regularly

Refresh your marketing materials periodically to keep affiliates engaged and provide them with current promotional content.

## Next Steps

-   Learn how to [manage your programs](/docs/programs)
-   Explore [affiliate management](/docs/affiliates) features
-   Set up [webhooks](/docs/webhooks) for real-time notifications

---



<!-- ===== /docs/emails ===== -->

# Email Notifications

> Source: https://refgrow.com/docs/emails

Automate email notifications to your affiliates based on program events.

## Overview

Refgrow's Email Notifications system allows you to automatically send personalized emails to your affiliates when important events occur in your affiliate program. You can configure when emails are sent, customize message templates with dynamic variables, and track delivery history.

**Automatic:** Once configured, emails are sent automatically when events occur in your affiliate program. No additional setup or code required!

## Getting Started

### 1\. Access Email Notifications

Navigate to your project dashboard and click on **"Emails"** in the sidebar menu. This will take you to the Email Notifications management page.

### 2\. Create Your First Template

1.  Click the **"New Template"** button in the Templates tab
2.  Enter a template name (e.g., "Commission Notification")
3.  Write your email subject line (you can use variables like `{{commission_amount}}`)
4.  Compose your email body using HTML or plain text
5.  Use available variables to personalize the content
6.  Click **"Create Template"** to save

### 3\. Configure Event Settings

1.  Go to the **"Events"** tab
2.  For each event type, toggle the switch to enable notifications
3.  Select a template from the dropdown
4.  Optionally set a delay (in minutes) before sending the email
5.  Save your settings

### 4\. Test Your Setup

1.  Go back to the **"Templates"** tab
2.  Click the **"Test"** button on any template
3.  Enter your email address
4.  Click **"Send Test"** to receive a test email with sample data

## Supported Events

The Email Notifications system supports three main event types:

Event Type

Description

When It Triggers

`conversion`

Commission earned notification

When a referred user makes a purchase and the affiliate earns a commission

`payout`

Payout processed notification

When a payout is successfully processed for an affiliate

`referral_signup`

New referral signup notification

When a new user signs up through an affiliate's referral link

## Template Variables

You can use dynamic variables in both the subject line and body of your email templates. These variables will be automatically replaced with actual data when the email is sent.

### Available Variables

Variable

Description

Available For Events

`{{project_name}}`

Name of your affiliate program/project

All events

`{{commission_amount}}`

Commission amount earned by the affiliate

conversion

`{{customer_email}}`

Email address of the customer who made the purchase

conversion

`{{purchase_amount}}`

Total amount of the purchase

conversion

`{{conversion_date}}`

Date when the conversion occurred

conversion

`{{payout_amount}}`

Amount of the payout

payout

`{{payment_method}}`

Payment method used (PayPal, Wise, etc.)

payout

`{{payout_date}}`

Date when the payout was processed

payout

`{{referral_email}}`

Email address of the new referral

referral\_signup

`{{signup_date}}`

Date when the referral signed up

referral\_signup

### Example Template

Here's an example of a conversion notification template:

**Subject:** You earned {{commission\_amount}} from {{project\_name}}!

```
Hi there!

Great news! You just earned a commission from {{project_name}}.

Details:
- Commission: {{commission_amount}}
- Customer: {{customer_email}}
- Purchase Amount: {{purchase_amount}}
- Date: {{conversion_date}}

Thank you for being part of our affiliate program!

Best regards,
{{project_name}} Team
```

## Scheduled Emails

You can configure a delay (in minutes) for email notifications. This is useful when you want to:

-   Send emails after a grace period (e.g., wait 24 hours after conversion to ensure no refunds)
-   Batch notifications together
-   Send reminders at specific times

To set a delay, go to the **"Events"** tab and enter the number of minutes in the delay field for the event you want to delay. Emails will be sent automatically after the specified delay period.

## Email History & Logs

The **"History"** tab provides a complete log of all email notifications sent through the system. You can view:

-   **Sent emails:** Successfully delivered emails
-   **Failed emails:** Emails that failed to send (with error details)
-   **Pending emails:** Emails scheduled for future delivery
-   **Scheduled emails:** Emails waiting for their scheduled time

Each log entry includes the recipient email, event type, template used, send status, and timestamp. Failed emails include error messages to help you troubleshoot issues.

## How It Works

Email notifications are sent automatically when events occur in your affiliate program. Once you've configured your templates and enabled events, the system handles everything for you.

### When Emails Are Sent

Emails are automatically sent when:

-   **Conversion:** A referred user makes a purchase and your affiliate earns a commission
-   **Payout:** You process a payout for an affiliate
-   **Referral Signup:** A new user signs up through an affiliate's referral link

**Important:** For emails to be sent, make sure:

-   The event type is enabled in the Events tab
-   A template is selected for the event
-   The affiliate has a valid email address in their profile

## Best Practices

-   **Test before going live:** Always use the "Test" feature to preview emails before enabling notifications for real events.
-   **Use clear subject lines:** Make sure your subject lines clearly indicate what the email is about and include important information like commission amounts.
-   **Personalize content:** Use variables to make emails feel personal and relevant to each affiliate.
-   **Monitor delivery:** Regularly check the History tab to ensure emails are being delivered successfully and troubleshoot any failures.
-   **Set appropriate delays:** Consider adding delays for conversion notifications to account for potential refunds or cancellations.
-   **Keep templates updated:** Review and update your email templates periodically to ensure they remain relevant and accurate.

## Troubleshooting

### Emails Not Sending

-   Check that the event is enabled in the **"Events"** tab (toggle switch should be ON)
-   Ensure a template is selected for the event in the dropdown menu
-   Verify the affiliate has a valid email address in their profile
-   Check the **"History"** tab for error messages - failed emails will show what went wrong
-   Make sure you've saved your event settings after making changes

### Variables Not Replacing

-   Make sure variable names are spelled correctly (case-sensitive)
-   Use double curly braces: `{{variable_name}}`
-   Verify that the variable is available for the event type you're using (see the Variables table above)
-   Check that there are no extra spaces inside the braces: `{{variable}}` not `{{ variable }}`

### Scheduled Emails Not Sending

-   Verify the delay time has passed (check the scheduled time in the History tab)
-   Make sure the event is enabled and a template is selected
-   Check the History tab - scheduled emails will show as "scheduled" until they're sent

### Test Emails Not Arriving

-   Check your spam/junk folder
-   Verify the email address you entered is correct
-   Wait a few minutes - emails may take a moment to arrive
-   Check the History tab to see if the test email was sent successfully

---



<!-- ===== /docs/custom-email-domain ===== -->

# Custom Email Sending Domain

> Source: https://refgrow.com/docs/custom-email-domain

Send affiliate-facing emails from your own domain instead of refgrow.com.

## What this covers

Once you connect a custom sending domain, the following emails go from `noreply@your-domain.com` instead of `welcome@auth.refgrow.com`:

-   Affiliate portal sign-up and login codes
-   Affiliate invitation emails
-   Payout notification emails (manual, PayPal, Wise)
-   In-app messages between you and affiliates ([Messages](/docs/messages))
-   Email automation events configured in [Email Notifications](/docs/emails)

## Plan requirement

Custom email sending is part of white-label and is available on the **Business** and **Enterprise** plans.

## How it works

You enter the domain you want emails to come from, and Refgrow handles the email infrastructure on its end. You only need to add a few DNS records (SPF, DKIM, MX) at your domain registrar so receiving mail providers (Gmail, Outlook, etc.) trust the messages.

You do not need to sign up for any third-party email service or paste API keys. Refgrow takes care of the sending infrastructure for you.

## Setup

1.  Open **Settings → General → Custom Email Sending** in your Refgrow dashboard.
2.  Enter the domain you want emails to send from. Use a subdomain (e.g. `mail.yourdomain.com`) so this does not affect your main domain's mail flow.
3.  Click **Add domain**. Refgrow shows a list of DNS records that need to exist on your domain.
4.  Log in to your DNS provider (Cloudflare, Route53, GoDaddy, etc.) and create each record exactly as shown. Click the copy icon next to the Name and Value cells in the dashboard to copy them verbatim.
5.  Wait a few minutes for DNS to propagate, then click **Re-check** in the Refgrow dashboard. Once Resend (the underlying provider Refgrow uses) marks the domain as verified, the status switches to **verified** and future emails go from your domain automatically.

## Recommended DNS provider configuration

Most registrars accept the records as-is, with no special handling. A few notes:

-   For the **TXT** records, paste the value as a single line. Some registrars wrap long TXT values automatically; that is fine.
-   For the **MX** record, set the priority to `10` as shown.
-   Use `Auto` or the registrar's default TTL. 300 seconds is also fine.
-   On Cloudflare, leave the "proxy" toggle _off_ (grey cloud) for these records. Mail records must hit your DNS directly, not through Cloudflare's HTTP proxy.

## Verifying the setup

After clicking Re-check, the status field tells you what Resend sees:

-   **not\_started / pending** — DNS records are not yet visible. Wait a few minutes and Re-check again.
-   **verified** — Records are correct and Refgrow will now send emails from your domain.
-   **failure / temporary\_failure** — Resend tried to verify and could not match the records. Double-check that each record name and value is exact, including dots and equals signs. Common issues: pasted into the wrong record type, copied with a leading or trailing space, or the registrar wrapped a TXT value across multiple lines incorrectly.

## Changing or removing the domain

If you change your mind, click **Remove** on the configured domain. Refgrow will detach the domain from its sending infrastructure and revert future emails to `welcome@auth.refgrow.com`. You can then add a different domain or leave it disabled.

If you simply want to switch domains, enter the new domain in the input and click Add. Refgrow automatically removes the previous one before adding the new one, so you do not get charged for two slots on our end.

## Troubleshooting

### Verification stays pending after 30+ minutes

DNS propagation usually takes 5-10 minutes but can take longer. Use a tool like [dnschecker.org](https://dnschecker.org) to verify each record is resolving from multiple regions before re-checking.

### Emails are still coming from refgrow.com after verification

Make sure the status badge in Settings shows **verified**(not just "pending"). Future emails switch over automatically the moment Resend confirms the domain.

### Some emails come from my domain and some from refgrow.com

Until verification is confirmed, Refgrow keeps using its default sender to avoid bounced emails landing in spam. After verification, all affiliate-facing emails should send from your domain. If you continue to see mixed senders, contact support.

## FAQ

### Do I need a Business plan even if my domain is already with Resend?

Yes. The feature is gated to Business and Enterprise regardless of your existing setup elsewhere.

### Can I use my main domain (e.g. yourdomain.com) instead of a subdomain?

Technically yes, but it is not recommended. If your main domain already sends or receives mail (e.g. from Google Workspace), the new SPF and MX records can conflict with your existing setup. Using a subdomain like `mail.yourdomain.com` isolates Refgrow email traffic from your main domain.

### Will receiving mail still work on this domain?

The MX record we add points incoming bounce messages to Resend so we can detect deliverability problems. If you use the same subdomain for inbound mail, the new MX record will replace your existing one. That is why we recommend a subdomain dedicated to Refgrow.

### What happens if I downgrade from Business to a lower plan?

The custom domain stays attached but emails revert to `welcome@auth.refgrow.com` as soon as your billing plan no longer includes white-label. Re-upgrading restores the custom sender immediately.

## Related

-   [Affiliate Portal & White-Label](/docs/affiliate-portal) — overview of all white-label features.
-   [Email Notifications](/docs/emails) — automate event-based emails to affiliates.
-   [In-App Messages](/docs/messages) — communicate with affiliates inside the platform.

---



<!-- ===== /docs/affiliate-portal ===== -->

# Affiliate Portal

> Source: https://refgrow.com/docs/affiliate-portal

Give your affiliates a hosted dashboard at `{slug}.refgrow.com`

## What is the Affiliate Portal?

The Affiliate Portal is a standalone, hosted dashboard where your affiliates can view their stats, referral links, conversions, earnings, and payouts — without embedding anything into your website.

It is an alternative to the [embedded widget](/docs/widget). Instead of integrating a widget into your app, you simply share a portal URL like `yourslug.refgrow.com` and your affiliates log in with a one-time email code.

## Enabling the Portal

To enable the affiliate portal for your project:

1.  Go to your project's **Portal** page (separate page in the sidebar).
2.  Toggle **Enable Portal** on.
3.  Choose a **slug** (e.g. `myapp`). Your portal will be available at `myapp.refgrow.com`.
4.  Click **Save**.

## Portal Features

The portal provides affiliates with everything they need to track and manage their referral activity:

### Dashboard

Overview of clicks, signups, conversions, total earnings, and unpaid balance. Includes the referral link, coupon code, and recent conversions table.

### Payouts

Full payout history with dates, amounts, and statuses. Downloadable invoices for completed payouts.

### Settings

Affiliates can set their preferred payment method (PayPal, Wise, bank transfer, etc.) and provide payout details.

### Statistics

Day-by-day breakdown of clicks, signups, conversions, and earnings for the last 30 days.

### Earnings

Detailed earnings view showing total, available, held, and paid amounts. Per-conversion breakdown with sale amounts and commission.

## Custom Domain

By default your portal is hosted at `{slug}.refgrow.com`. You can also use your own domain (e.g. `affiliates.yourcompany.com`):

1.  Add a **CNAME** record in your DNS pointing to `portal.refgrow.com`.
2.  In your project's **Portal** page, enter your custom domain.
3.  Refgrow will verify the DNS record. Once verified, SSL is provisioned automatically and your portal is live on your domain.

**DNS Example:** `affiliates.yourcompany.com CNAME portal.refgrow.com`

## Public vs Invite-Only

You can control who can sign up for your affiliate portal:

-   **Public signup** — anyone who visits the portal can enter their email and create an affiliate account. Ideal for open affiliate programs.
-   **Invite-only** — only affiliates you have already added to your project can log in. New visitors see a login form but cannot create accounts. Use this for curated programs.

Toggle this setting on your project's **Portal** page under **Public Signup**.

## Portal vs Widget

Both the portal and the [embedded widget](/docs/widget) let affiliates manage their referral activity. Here is when to use each:

Affiliate Portal

Embedded Widget

Hosting

Hosted by Refgrow at slug.refgrow.com

Embedded in your website

Setup

Enable in settings, share the link

Add script tag to your site

Authentication

Email + one-time code

Your app session or email entry

Best for

Standalone affiliate programs, external partners

In-app referral programs, existing users

Branding

Project name + logo in header

Fully customizable with your brand colors

Code changes

None required

Script tag + optional data attributes

**Tip:** You can use both at the same time. The portal and widget share the same data, so affiliates can switch between them seamlessly.

## Sharing the Portal

Once your portal is enabled, share the URL with your affiliates:

-   Direct link: `https://{slug}.refgrow.com`
-   Include it in your affiliate welcome email.
-   Add a "Partner Dashboard" link in your website footer or navigation.
-   If you use a custom domain, share that URL instead (e.g. `https://affiliates.yourcompany.com`).

Affiliates visit the link, enter their email, receive a one-time code, and they are in.

## Need help?

If you need help setting up the affiliate portal, contact us at [support@refgrow.com](mailto:support@refgrow.com).

---



<!-- ===== /docs/messages ===== -->

# Messages

> Source: https://refgrow.com/docs/messages

Communicate with your affiliates directly from your dashboard.

## Overview

Messages provides built-in communication between program owners and their affiliates. Instead of relying on external email threads or chat tools, you can send and receive messages right inside Refgrow. Affiliates see your messages in their portal or embedded widget, and can reply directly.

## How It Works

1.  You compose a message from the **Messages** page in your dashboard.
2.  The affiliate receives the message in their portal or widget under the **Messages** tab.
3.  The affiliate can read and reply. Their reply appears in your dashboard conversation thread.
4.  Both sides receive email notifications for new messages so nothing gets missed.

## Getting Started

Messages are available on all plans. To make sure your affiliates can see the Messages tab:

1.  Go to **Settings > Portal** and confirm that the Messages block is enabled.
2.  Alternatively, visit the **Messages** page in your dashboard — if messaging is not yet enabled you can toggle it on from there.

**Tip:** If you use the embedded widget, make sure the "Messages" block is included in your widget configuration so affiliates can access conversations without leaving your app.

## Sending Messages

1.  Navigate to **Messages** in your dashboard sidebar.
2.  Click **New Message** and select an affiliate from the dropdown, or open an existing conversation.
3.  Type your message and press **Send**.

You can send messages to any active affiliate in your program. Each conversation is a chronological thread, so you always have full context.

## For Affiliates

Affiliates access messages through the **Messages** tab in the affiliate portal or the embedded widget. From there they can:

-   Read messages from the program owner
-   Reply directly within the conversation thread
-   See a badge indicator when unread messages are waiting

No additional setup is required on the affiliate side — if Messages is enabled, the tab appears automatically.

## Email Notifications

When a new message is sent, the recipient receives an email notification containing a preview of the message and a link to view the full conversation. This applies in both directions:

-   **Affiliate receives email** when the program owner sends a message.
-   **Program owner receives email** when an affiliate replies.

## Use Cases

Here are some common ways to use Messages to strengthen your affiliate program:

-   **Welcome messages:** Send a personal welcome when a new affiliate joins your program.
-   **Activation reminders:** Nudge affiliates who have signed up but haven't started promoting yet.
-   **Performance tips:** Share conversion tips or high-performing strategies with individual affiliates.
-   **Payout notifications:** Let affiliates know when a payout has been processed or if payment details need updating.
-   **Campaign updates:** Announce new promotions, seasonal offers, or changes to commission structures.

## Frequently Asked Questions

### Can I message all affiliates at once?

Messages are currently one-to-one conversations. For bulk announcements, consider using the email notification feature or reaching out to affiliates individually.

### Do affiliates need an account to receive messages?

Yes. Messages are tied to affiliate accounts. The affiliate must be registered in your program to receive and reply to messages.

### Will I be notified when an affiliate replies?

Yes. You will receive an email notification whenever an affiliate sends a reply. You can also check the Messages page in your dashboard for unread conversations.

### Can I delete a conversation?

Individual messages cannot be deleted at this time. This ensures both sides have a complete record of the conversation.

## Next Steps

-   Learn about [Managing Affiliates](/docs/affiliates)
-   Customize your [Affiliate Portal](/docs/affiliate-portal)
-   Set up [Email Notifications](/docs/emails)

---



<!-- ===== /docs/multi-tier ===== -->

# Multi-Tier Commission System

> Source: https://refgrow.com/docs/multi-tier

Set up a two-tier affiliate program where affiliates can recruit sub-affiliates and earn commissions from their referrals' sales.

## How It Works

### Two-Tier Structure

-   **Tier 1 (Parent):** Original affiliates who recruit others
-   **Tier 2 (Child):** Affiliates recruited by Tier 1 affiliates

### Commission Flow

When a Tier 2 affiliate makes a sale:

1.  **Tier 2 affiliate** earns their standard commission
2.  **Tier 1 parent** earns an additional Tier 2 commission
3.  Both commissions are calculated and paid separately

## Setup Guide

**Note:** Multi-Tier commissions are available on Pro and Business plans.

### Step 1: Enable Multi-Tier System

1.  Go to **Project Settings** → **Commissions** tab
2.  Find the **Multi-Tier Commission System** section
3.  Toggle **"Enable Multi-Tier Commission System"**

### Step 2: Configure Tier 2 Settings

### Commission Type

Choose between:

-   **Percentage (%):** Fixed percentage of sale
-   **Fixed amount ($):** Fixed dollar amount per sale

### Commission Value

Set the rate Tier 1 affiliates earn from Tier 2 sales.

Typical range: 5-15% of sale value

### Duration

-   **Lifetime:** Tier 1 earns from all future Tier 2 sales
-   **Period:** Tier 1 earns for a specific number of months

### Step 3: Example Configuration

```
Standard Commission: 30% lifetime
Tier 2 Commission: 10% lifetime

Result when Tier 2 affiliate sells $100:
- Tier 2 affiliate earns: $30 (standard commission)
- Tier 1 parent earns: $10 (additional tier 2 commission)
```

## Setting Up Affiliate Hierarchies

**Admin-Managed System:** The Multi-Tier system uses admin-managed parent-child relationships rather than automatic recruitment links.

### Process for Adding Tier 2 Affiliates

1.  Go to your **Project Dashboard** → **Affiliates** section
2.  Create a new affiliate OR select an existing affiliate
3.  Use the "Set Parent Affiliate" option to link them to a Tier 1 affiliate
4.  The system automatically calculates Tier 2 commissions for future sales

### Recruitment Options

### Manual Process

Have interested affiliates contact you directly for review and approval.

### Application Form

Create your own signup form and manually add qualified affiliates to the system.

### API Integration

Build your own recruitment system using Refgrow's API for automated processing.

## Tracking & Analytics

### Admin Dashboard

-   **Affiliates page:** See parent-child relationships
-   **Multi-tier statistics:** Track Tier 2 performance
-   **Commission breakdown:** Separate Tier 1 and Tier 2 earnings

### Affiliate Widget

Affiliates can see:

-   Their standard referral link
-   **If Tier 2:** Information about their parent affiliate
-   **If Tier 1 with children:** Tier 2 commission earnings
-   Multi-tier commission breakdown and statistics

## Best Practices

### Set Attractive Tier 2 Rates

-   Make it worthwhile for top affiliates to recruit
-   Typical range: 5-15% of sale value
-   Consider your margins when setting rates

### Streamline Recruitment

-   Create a clear application process for potential affiliates
-   Develop criteria for selecting quality Tier 2 partners
-   Consider building a custom recruitment form with API integration

### Monitor Performance

-   Track which Tier 1 affiliates are best recruiters
-   Analyze Tier 2 conversion rates
-   Adjust commission rates based on performance

### Maintain Balance

-   Ensure Tier 2 rates don't exceed your profit margins
-   Test different rate structures to find optimal balance
-   Consider different rates for different products

## Common Questions

### Can Tier 2 affiliates recruit their own sub-affiliates?

No, this is a two-tier system. Tier 2 affiliates cannot create Tier 3 levels.

### What happens if a Tier 1 affiliate is removed?

Their Tier 2 affiliates remain active but become independent (no longer generate Tier 2 commissions for the removed parent).

### Can I change Tier 2 commission rates after setup?

Yes, but changes only apply to new conversions, not existing ones.

### How are Tier 2 commissions paid out?

Tier 2 commissions are added to the Tier 1 affiliate's earnings and paid through their chosen payment method.

## Quick Start Checklist

1.  **Enable the system** in your project settings
2.  **Set your Tier 2 commission rates** and duration
3.  **Create your affiliate hierarchy** by assigning parent-child relationships
4.  **Develop your recruitment process** for finding quality Tier 2 affiliates
5.  **Monitor and optimize** based on performance data

**Pro Tip:** The Multi-Tier system provides a powerful way to create affiliate hierarchies and reward your top-performing affiliates for building teams beneath them, all managed through your admin dashboard.

---



<!-- ===== /docs/multilevel ===== -->

# Multilevel Commission System

> Source: https://refgrow.com/docs/multilevel

Create progressive commission levels that motivate and reward affiliate performance with flexible condition settings and automatic upgrades.

## How It Works

### Progressive Level Structure

-   **Multiple Levels:** Create unlimited commission levels (Bronze, Silver, Gold, etc.)
-   **Flexible Conditions:** Set amount thresholds, referral counts, time-based, or custom criteria
-   **Automatic Upgrades:** Affiliates advance when they meet level requirements

### Commission Benefits

As affiliates progress through levels:

1.  **Higher commission rates** reward better performance
2.  **Flexible durations** (one-time, period, or lifetime)
3.  **Manual overrides** for special cases or VIP treatment

## Setup Guide

**Note:** Multilevel commissions are available on Pro and Business plans.

### Step 1: Enable Multilevel System

1.  Go to **Project Settings** → **Commissions** tab
2.  Find the **Multilevel Commission System** section
3.  Toggle **"Enable Multilevel Commission System"**

### Step 2: Create Commission Levels

### Level Configuration

Set up each level with:

-   **Level Name:** Display name (Bronze, Silver, Gold)
-   **Level Order:** Progression sequence (1, 2, 3...)

### Commission Settings

Configure rewards:

-   **Commission Rate:** Percentage or fixed amount
-   **Duration:** One-time, period, or lifetime

### Condition Settings

Set advancement criteria:

-   **Condition Type:** Amount threshold, referral count, time-based, or custom
-   **Condition Value:** Target amount or number
-   **Condition Period:** Total, monthly, quarterly, or yearly
-   **Auto Upgrade:** Automatic progression when criteria met

### Step 3: Example Configuration

```
Level 1 - Starter: 5% lifetime
  Condition: Amount threshold, $0+ (total)

Level 2 - Bronze: 7% for 6 months
  Condition: Amount threshold, $100+ (total)

Level 3 - Silver: 10% lifetime
  Condition: Amount threshold, $500+ (total)

Level 4 - Gold: 15% lifetime
  Condition: Referral count, 10+ referrals (total)

Result when Gold affiliate sells $100:
- Gold affiliate earns: $15 (15% commission)
- Automatic upgrade when affiliate reaches next threshold
```

## Advanced Condition Types

### Amount Threshold

**Use case:** Reward high-value affiliates

-   Set earnings targets ($100, $500, $1000+)
-   Choose period: total, monthly, quarterly, yearly
-   Ideal for revenue-focused progression

### Referral Count

**Use case:** Encourage affiliate recruitment

-   Set referral targets (5, 10, 25+ referrals)
-   Track over different time periods
-   Perfect for growth-focused programs

### Time-Based

**Use case:** Reward affiliate loyalty and longevity

-   Set activity duration requirements (30, 90, 365+ days)
-   Combine with other criteria for comprehensive evaluation
-   Encourage long-term partnerships

### Custom Conditions

**Use case:** Flexible criteria for unique business needs

-   Define custom metrics and targets
-   Combine multiple criteria types
-   Adapt to specific industry requirements

## Managing Affiliate Levels

**Beta Feature:** The Multilevel system is currently in beta and supports both automatic upgrades based on performance criteria and manual level assignments for special cases.

### Process for Setting Affiliate Levels

1.  Go to your **Project Dashboard** → **Affiliates** section
2.  Create a new affiliate OR select an existing affiliate
3.  Use the "Multilevel Commission Settings" option to assign them to a specific level
4.  The system automatically applies the selected level's commission rate for future sales

### Level Management Options

### Automatic Upgrades

System automatically checks performance and upgrades affiliates when they meet criteria for the next level.

### Manual Assignment

Manually assign any affiliate to any level for VIP treatment, partnerships, or testing purposes.

### Automatic Processing

The system automatically processes level upgrades when affiliates meet new criteria during conversion events.

## Tracking & Analytics

### Admin Dashboard

-   **Affiliates page:** See current commission levels for each affiliate
-   **Level statistics:** Track level distribution and progression
-   **Performance metrics:** Monitor earnings by level and upgrade frequency

### Affiliate Widget

Affiliates can see:

-   Their current commission level and rate
-   **Progress tracking:** How close they are to the next level
-   **Level overview:** All available levels and requirements
-   Achievement history and milestone progress

## Best Practices

### Design Progressive Levels

-   Start with modest rates to encourage initial engagement
-   Create meaningful jumps between levels (3-5% increases)
-   Set realistic but challenging upgrade thresholds

### Monitor Performance

-   Track which levels are most motivating for affiliates
-   Analyze upgrade frequency and time-to-level progression
-   Adjust level criteria based on actual performance data

### Clear Communication

-   Explain level benefits clearly in affiliate materials
-   Show progress indicators in the affiliate dashboard
-   Send congratulatory emails when affiliates reach new levels

### Maintain Balance

-   Ensure higher level rates don't exceed profit margins
-   Test different level structures before full rollout
-   Consider different criteria for different product categories

## Common Questions

### Can affiliates skip commission levels?

No, affiliates must progress through levels sequentially. However, you can manually assign any affiliate to any level regardless of their performance.

### What happens if I change a level's commission rate?

Changes only apply to new conversions. Existing transactions retain their original commission rates.

### Can Multilevel work with Multi-Tier commissions?

Yes, both systems can work together. Multilevel affects individual affiliate commission rates, while Multi-Tier handles parent-child commission sharing.

### How are commission levels paid out?

Commission levels determine the rate applied to conversions. Payouts are processed through the affiliate's chosen payment method according to your payout schedule.

## Quick Start Checklist

1.  **Enable the system** in your project settings (Commission tab)
2.  **Create your commission levels** with appropriate rates and condition settings
3.  **Set condition types** (amount threshold, referral count, time-based, or custom)
4.  **Configure auto-upgrade settings** to automate progression or manage manually
5.  **Assign affiliate levels** through the affiliate management interface
6.  **Monitor and optimize** based on affiliate behavior and business performance

**Pro Tip:** The Multilevel Commission system creates powerful incentives for affiliate performance while giving you complete control over progression criteria and commission structures. As a beta feature, we're continuously improving based on user feedback.

## Next Steps

### Explore the API

Use the API to programmatically manage commission levels and automate level assignments.

[View API Docs](/docs/api-reference)

### Multi-Tier System

Learn how to combine Multilevel with Multi-Tier for even more sophisticated commission structures.

[Multi-Tier Guide](/docs/multi-tier)

---



<!-- ===== /docs/referral-exchange ===== -->

# Referral Exchange

> Source: https://refgrow.com/docs/referral-exchange

Grow your affiliate network by exchanging affiliates with other programs on Refgrow.

## Overview

The Referral Exchange is a marketplace where Refgrow projects can share affiliates with each other. When one of your affiliates joins another program through the exchange, you earn a credit. You can then spend that credit to receive an affiliate from another program.

## How It Works

### 1\. Enable Exchange for Your Project

Go to the **Referral Exchange** page in your dashboard and toggle the exchange on. Fill in your listing details:

-   **Name** — Your project or product name
-   **Headline** — A short tagline (e.g. "Earn 30% recurring commission promoting the best project management tool")
-   **Description** — Describe what you offer and why affiliates should join
-   **Category** — Select the category that best fits your product

You can use the **"Fill with AI"** button to automatically generate your listing details based on your project information.

### 2\. Credit System

The exchange runs on a simple credit system:

#### Earn Credits (+1)

When one of your affiliates gets sent to another program and converts, you earn 1 credit.

#### Spend Credits (-1)

When you receive an affiliate from another program, it costs 1 credit.

### 3\. Buying Credits

If you need more credits, you can purchase them directly:

-   Credits cost **$0.50 each**
-   Minimum purchase: **10 credits ($5.00)**
-   Payment is processed through Stripe
-   Credits never expire

### 4\. Receiving Affiliates

Once your listing is active, other programs can send affiliates to you. When you receive an affiliate:

1.  They appear in the **"Received"** tab of your exchange history
2.  The affiliate is automatically added to your project
3.  1 credit is deducted from your balance
4.  The affiliate can start promoting your product immediately

### 5\. Sending Affiliates

You can also send your affiliates to participate in other programs:

1.  Browse available programs in the exchange directory
2.  Select a program that fits your affiliate's interests
3.  The affiliate receives an invitation to join that program
4.  When they convert, you earn 1 credit

## Exchange History

The exchange page shows two tabs:

-   **Received Affiliates** — Affiliates that other programs sent to you, with status (Pending / Converted) and credit charged.
-   **Sent Affiliates** — Your affiliates that joined other programs, with status and credits earned.

## Tips for Success

-   **Write a compelling listing** — A good headline and description attract more affiliates. Mention your commission rate.
-   **Choose the right category** — This helps affiliates find programs relevant to their audience.
-   **Start by sending** — Earn credits first by sending affiliates to other programs, then use those credits to receive affiliates.
-   **Keep credits topped up** — If your balance hits 0, you can't receive new affiliates until you earn or buy more credits.

## Next Steps

[

### AI Recruiter →

Find affiliates using AI-powered web search across social platforms.

](/docs/ai-recruiter)[

### Managing Affiliates →

Learn how to manage and track your affiliate partners.

](/docs/affiliates)

---



<!-- ===== /docs/ai-recruiter ===== -->

# AI Recruiter

> Source: https://refgrow.com/docs/ai-recruiter

Find and recruit affiliates using AI-powered web search across Twitter/X, Reddit, and YouTube.

## Overview

The AI Recruiter searches the web for real content creators and influencers who match your niche, then generates personalized outreach messages you can use to invite them to your affiliate program.

AI Recruiter is available on paid plans only. Free plan users need to upgrade to access this feature.

## How It Works

1.  **Choose a platform** — Select where to search: Twitter/X, Reddit, or YouTube.
2.  **Enter your search query** — Describe the type of affiliates you're looking for (e.g. "SaaS reviewers", "productivity tool bloggers", "indie hackers").
3.  **Specify a niche** — Optionally narrow down the niche (e.g. "project management", "developer tools").
4.  **AI searches the web** — The system uses AI with real-time web search to find actual profiles matching your criteria.
5.  **Review prospects** — Each prospect includes their profile link, bio, follower count, a relevance score, and a personalized outreach message.
6.  **Reach out** — Click **"Copy Message"** to copy the AI-generated outreach to your clipboard, then paste it into a DM on Twitter, Reddit, or YouTube. After reaching out, click **"Mark as Invited"** to track the status.
7.  **Track progress** — Prospects move through statuses: Found → Invited → Contacted → Converted. Use the Prospects tab to filter and manage them.

## Supported Platforms

### Twitter / X

Find active accounts that tweet about your niche. Great for reaching thought leaders and micro-influencers.

### Reddit

Discover users who actively discuss topics related to your product in relevant subreddits.

### YouTube

Find content creators who review or discuss tools and products in your category.

## Search Tips

-   **Be specific** — "SaaS marketing tools reviewers" works better than just "marketing".
-   **Use niche keywords** — Include terms your ideal affiliates would use (e.g. "no-code", "developer tools", "startup growth").
-   **Try different platforms** — Some niches are more active on Twitter, others on Reddit or YouTube.
-   **Review relevance scores** — Higher scores mean the prospect is a better match for your niche. Focus on those first.

## Reaching Out

After finding prospects, expand any prospect card to see the AI-generated outreach message. You'll see two action buttons at the bottom:

#### Copy Message

Copies the outreach subject and message to your clipboard. Paste it into a Twitter DM, Reddit message, or YouTube comment to reach out personally.

#### Mark as Invited

After you've sent the message, click this to update the prospect's status to "Invited" so you can track your outreach progress.

You can also use the **Templates** tab to create reusable outreach templates with variables like {{name}}, {{platform}}, and {{commission}}.

## Prospect Pipeline

Track each prospect through their journey in the **Prospects** tab:

Found→Invited→Contacted→Converted

-   **Found** — Prospect discovered by AI search
-   **Invited** — You've reached out to the prospect via DM or message
-   **Contacted** — Prospect responded or you had a conversation
-   **Converted** — Prospect joined your affiliate program

Use filters and bulk actions to manage large numbers of prospects efficiently.

## Outreach Messages

For each prospect, the AI generates a personalized outreach message that references their specific content and audience. The message includes a subject line, personalization points, and a clear call-to-action.

## Monthly Limits

The number of AI searches per month depends on your plan:

Plan

Searches / month

Prospects per search

Starter

5

10

Pro

25

15

Business

50

15

Enterprise

200

15

## Next Steps

[

### Managing Affiliates →

Learn how to manage your affiliate partners after recruiting them.

](/docs/affiliates)[

### Commission Setup →

Configure commission rates to attract the best affiliates.

](/docs/commissions)

---



<!-- ===== /docs/hold-periods ===== -->

# Hold Period Settings

> Source: https://refgrow.com/docs/hold-periods

Protect against refunds and chargebacks with configurable hold periods.

## Overview

Hold periods allow you to delay when affiliate earnings become eligible for payout. This protects your business against refunds, chargebacks, and subscription cancellations by ensuring commissions are only paid out after a safe waiting period.

When a hold period is configured, affiliate earnings are divided into two categories:

-   **Total Earnings:** All commissions earned, regardless of hold period
-   **Eligible Earnings:** Commissions that have passed the hold period and are available for payout

## Configuring Hold Periods

### Setting Up Hold Periods

To configure a hold period for your affiliate program:

1.  Log in to your Refgrow dashboard
2.  Select your project
3.  Navigate to **Project Settings**
4.  Click on the **Payouts** tab
5.  Find the "Hold Period Settings" section
6.  Enter your desired hold period in days (0-365)
7.  Click **Save Settings**

**Note:** Hold period changes apply to all future conversions. Existing earnings maintain their original hold period rules.

### Hold Period Options

Hold Period

Description

Best For

0 days

Earnings are immediately eligible for payout

Established programs with low refund rates, digital products with no refund policy

7-14 days

Short hold period for quick payouts

Digital services, software subscriptions with short trial periods

30 days

Standard hold period for most businesses

SaaS products, digital downloads, most online services

60-90 days

Extended hold period for higher-risk products

Physical products, high-value services, products with extended return policies

## How Hold Periods Work

### Earnings Calculation

When a conversion occurs, the system:

1.  Records the conversion and calculates the commission
2.  Adds the commission to the affiliate's **Total Earnings**
3.  Checks if the conversion date is older than the hold period
4.  If yes, adds the commission to **Eligible Earnings**
5.  If no, the commission remains in the hold period

#### Example Scenario

Example Scenario

**Project Settings:** 30-day hold period

**Today's Date:** March 15, 2024

##### Affiliate Earnings:

-   Conversion on February 10, 2024: $25 → Eligible for payout (35 days old)
-   Conversion on February 20, 2024: $15 → Eligible for payout (24 days old)
-   Conversion on March 1, 2024: $30 → Still in hold period (14 days old)
-   Conversion on March 10, 2024: $20 → Still in hold period (5 days old)

##### Dashboard Display:

-   **Total Earnings:** $90
-   **Eligible for Payout:** $40
-   **In Hold Period:** $50
-   **Next Release Date:** March 31, 2024 (when the March 1st conversion becomes eligible)

### Automatic Release

Earnings are automatically released from the hold period:

-   The system checks daily for earnings that have passed their hold period
-   Eligible earnings are immediately available for payout requests
-   Affiliates see updated balances in their dashboard
-   No manual intervention is required

## Affiliate Experience

### Dashboard Display

When hold periods are configured, affiliates see:

-   **Total Earnings:** All commissions earned to date
-   **Available for Payout:** Earnings eligible for withdrawal
-   **Pending Release:** Earnings still in hold period with release dates
-   **Hold Period Policy:** Information about your hold period settings

**Transparency:** Clear communication about hold periods builds trust with affiliates and sets proper expectations.

### Payout Requests

When affiliates request payouts:

-   Only eligible earnings are included in payout calculations
-   Held earnings are clearly excluded from payout requests
-   Affiliates can see when their next earnings will become available
-   Minimum payout thresholds apply only to eligible earnings

## Admin Management

### Viewing Held Earnings

In your admin dashboard, you can:

-   View total vs. eligible earnings for each affiliate
-   See upcoming earnings release dates
-   Filter affiliates by earnings status
-   Export earnings reports with hold period breakdowns

### Processing Payouts

When processing payouts:

-   Bulk payout tools automatically use only eligible earnings
-   Manual payout forms show eligible amounts
-   Held earnings are protected from accidental payout
-   Payout reports clearly distinguish between held and paid earnings

## Best Practices

### Choose Appropriate Periods

Set hold periods based on your refund policy and chargeback risk. Consider your industry standards and customer behavior patterns.

### Communicate Clearly

Inform affiliates about hold periods upfront. Include this information in your affiliate terms and program documentation.

### Monitor Performance

Track refund rates and adjust hold periods as needed. Shorter periods can improve affiliate satisfaction if refund risk is low.

### Consider Exceptions

For trusted, high-performing affiliates, consider manual payouts or shorter hold periods to maintain good relationships.

## Troubleshooting

### Earnings Not Becoming Eligible

If earnings aren't being released from hold period:

1.  Check that the conversion date is older than your hold period
2.  Verify the hold period is configured correctly in project settings
3.  Ensure the system's daily processing is running (contact support if needed)
4.  Check for any system-wide issues or maintenance windows

### Affiliate Confusion About Hold Periods

To reduce affiliate confusion:

1.  Add clear explanations to your affiliate onboarding materials
2.  Include hold period information in email notifications
3.  Provide examples of how hold periods work
4.  Consider creating FAQ documentation for affiliates

### Changing Hold Periods

When modifying hold periods:

1.  Changes only apply to new conversions going forward
2.  Existing held earnings maintain their original release dates
3.  Communicate changes to affiliates in advance
4.  Consider the impact on affiliate cash flow and satisfaction

## API Integration

When using the Refgrow API, hold period information is included in affiliate and earnings responses:

-   `eligible_earnings`: Earnings available for payout
-   `held_earnings`: Earnings still in hold period
-   `next_release_date`: When next earnings become eligible

See the [API Reference](/docs/api-reference) for complete documentation on hold period fields.

---



<!-- ===== /docs/identity-verification ===== -->

# Identity Verification (HMAC)

> Source: https://refgrow.com/docs/identity-verification

Secure the pre-authenticated widget by verifying affiliate identity with a server-side HMAC-SHA256 signature.

## Why Use Identity Verification?

When you embed the Refgrow widget with `data-project-email` pre-set, the email is visible in the page source. A tech-savvy user could change this attribute via browser DevTools and access another affiliate's dashboard (earnings, referral code, payment method).

Identity Verification prevents this by requiring a **server-generated HMAC hash** alongside the email. The hash is computed using your project secret, which only your server knows. If the hash doesn't match, the widget refuses to load affiliate data.

## How It Works

1.  Your server computes `HMAC-SHA256(email, project_secret)`
2.  You pass the hash as `data-user-hash` in the widget embed
3.  Refgrow's API verifies the hash before returning any affiliate data
4.  If verification fails, the API returns `403 Forbidden`

## Setup

### Step 1: Enable in Settings

Go to your project [Settings](/settings) → General → **Identity Verification (HMAC)** and toggle it on.

**Important:** Make sure your widget embed code includes `data-user-hash` before enabling this setting. Otherwise, all affiliate widgets will stop loading data until the hash is added.

### Step 2: Generate the Hash on Your Server

Use your **HMAC Secret Key** (shown in Settings → General → Identity Verification when enabled) and the affiliate's email to compute the hash. Always lowercase the email before hashing. Store the secret key as an environment variable on your server — never expose it in frontend code.

#### Node.js

```
const crypto = require('crypto');

const userHash = crypto
  .createHmac('sha256', process.env.REFGROW_HMAC_SECRET)
  .update(userEmail.toLowerCase())
  .digest('hex');
```

#### Python

```
import hmac
import hashlib

user_hash = hmac.new(
    HMAC_SECRET.encode(),
    user_email.lower().encode(),
    hashlib.sha256
).hexdigest()
```

#### PHP

```
$userHash = hash_hmac(
    'sha256',
    strtolower($userEmail),
    $hmacSecret
);
```

#### Ruby

```
require 'openssl'

user_hash = OpenSSL::HMAC.hexdigest(
  'sha256',
  hmac_secret,
  user_email.downcase
)
```

#### Go

```
import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "strings"
)

func userHash(email, secret string) string {
    mac := hmac.New(sha256.New, []byte(secret))
    mac.Write([]byte(strings.ToLower(email)))
    return hex.EncodeToString(mac.Sum(nil))
}
```

### Step 3: Add the Hash to Your Widget

#### Standard & Compact Widget

Pass the generated hash as the `data-user-hash` attribute:

```
<div id="refgrow"
  data-project-id="YOUR_PROJECT_ID"
  data-project-email="user@example.com"
  data-user-hash="a1b2c3d4e5f6...">
</div>
<script src="https://scripts.refgrowcdn.com/latest.js" async defer></script>
```

#### Modal Widget

Pass the hash as the 5th parameter to `openModal`. The 4th parameter (legacy) should be `null`:

```
RefgrowCompact.openModal(
  'YOUR_PROJECT_ID',
  'user@example.com',
  'en',        // language
  null,        // legacy param, pass null
  'a1b2c3...'  // HMAC hash
)
```

## How Verification Works

When the widget loads, it sends the email and hash to the Refgrow API. The API computes the expected hash using the stored HMAC secret key and compares it:

-   **Hash matches:** Affiliate data is returned normally
-   **Hash doesn't match:** API returns `403` — "Invalid identity verification hash"
-   **No hash provided (when required):** API returns `403` — "Identity verification required"

## Backward Compatibility

Identity verification is **opt-in**. When disabled (default), the widget works exactly as before — no hash is needed. This means you can:

1.  First update your embed code to include `data-user-hash`
2.  Deploy the change to production
3.  Then enable the setting in Refgrow

This ensures zero downtime during the transition.

## Security Notes

-   **Never expose your Project Secret** in client-side code. The hash must be computed on your server.
-   The hash is specific to each email address. Changing the email without updating the hash will fail verification.
-   If you rotate your Project Secret, all existing hashes become invalid. Update your server code with the new secret and redeploy before rotating.

## Troubleshooting

### Widget shows "Identity verification required"

Your project has identity verification enabled but the widget embed is missing the `data-user-hash` attribute. Add the hash to your embed code.

### Widget shows "Invalid identity verification hash"

-   Check that you're using the correct Project Secret
-   Make sure you lowercase the email before hashing: `email.toLowerCase()`
-   Verify the hash is the full hex string (64 characters for SHA-256)
-   Ensure the email in `data-project-email` matches exactly what you hashed

---



<!-- ===== /docs/stripe ===== -->

# Stripe Integration

> Source: https://refgrow.com/docs/stripe

Automatically track purchases and calculate commissions with Stripe.

## Overview

Refgrow integrates with Stripe to automatically track payments and calculate commissions for your affiliates.

-   Automatic tracking of one-time payments and subscriptions
-   Support for product-specific commission rates
-   Support for affiliate-specific commission overrides
-   Secure webhook implementation for real-time tracking
-   Works with both Stripe Checkout Sessions and Payment Links

## Setting Up Stripe Integration

**Note:** You will need a Stripe account to track payments. If you do not have one, [sign up here](https://dashboard.stripe.com/register).

### Step 1: Connect Your Stripe Account

1.  Go to your project's "Integration" tab
2.  Select "Stripe Webhooks" as your tracking method
3.  Enter your Stripe Secret Key (a restricted key is recommended)
4.  Click "Connect Stripe"

**Auto-configuration:** Refgrow will automatically set up the required webhook endpoint in your Stripe account.

### Step 2: Choose Your User Flow

Select the appropriate user conversion flow for your business:

-   **Click → Signup → Purchase:** Users create an account before making a purchase
-   **Click → Purchase:** Users can purchase directly without signing up first
-   **Both:** Your platform supports both flows

## Passing Referral Codes to Stripe

**Important:** If you have a direct purchase flow (Click → Purchase), passing the referral code to Stripe is essential for correct attribution.

### For Stripe Checkout Sessions

When creating a checkout session on your server, pass the referral code in the metadata:

```
// Example (Node.js Server-Side)
const refCode = req.cookies.refgrow_ref_code; // Get code from cookie

const session = await stripe.checkout.sessions.create({
  // ... other session parameters
  metadata: {
    referral_code: refCode || null // Pass the code here
  }
});
```

### For Stripe Payment Links

For payment links, there are two options:

#### Option 1: Automatic Processing with JavaScript

Add a special class to your payment links:

```
<a href="https://buy.stripe.com/xyz..."
   class="refgrow-stripe-payment-link">
  Buy Now
</a>
```

Call the helper function after the page loads:

```
// Call this once after the page loads
if (window.Refgrow) {
  Refgrow.processStripePaymentLinks();
}
```

#### Option 2: Programmatic Redirects

Redirect users with this helper function:

```
// Use this when you want to redirect a user to a payment link
if (window.Refgrow) {
  Refgrow.redirectToStripePaymentLink('https://buy.stripe.com/xyz...');
  // Don't use window.location.href = url; directly
}
```

## Attribution Methods

Refgrow uses multiple methods to attribute a Stripe customer to an affiliate, checked in this priority order:

### 1\. Coupon / Promotion Code Match

If the customer used a coupon code that matches an affiliate's coupon in Refgrow, the conversion is attributed to that affiliate. This is the most reliable method.

### 2\. Checkout Session Metadata

Pass the referral code in the Stripe Checkout Session metadata:

```
const session = await stripe.checkout.sessions.create({
  // ... other options
  metadata: {
    referral_code: "AFFILIATE_CODE"
  }
});
```

### 3\. Client Reference ID

Set the `client_reference_id` to the referral code when creating a Checkout Session:

```
const session = await stripe.checkout.sessions.create({
  client_reference_id: "AFFILIATE_CODE",
  // ... other options
});
```

### 4\. Subscription Metadata

The referral code can also be passed in the subscription metadata.

### 5\. Email Fallback

If none of the above methods match, Refgrow checks the `referral_attributions` table to see if the customer's email was previously attributed to an affiliate via the tracking script.

## Commission Configuration

### Default Commission Settings

Configure your default commission structure in your project settings:

-   Commission Type: Percentage or Fixed Amount
-   Commission Value: The percentage or fixed amount
-   Commission Duration: Lifetime, First Purchase, or Limited Period

### Product-Specific Commissions

Override commission rates for specific products:

1.  Go to your project's "Integration" tab
2.  Scroll to "Product-Specific Commissions"
3.  Click "Add Product Commission"
4.  Select a Stripe product and set its unique commission rate

**Note:** Product-specific rates take priority over your default commission settings.

### Affiliate-Specific Overrides

Set custom commission rates for individual affiliates:

1.  Go to your "Affiliates" tab
2.  Find the affiliate you want to customize
3.  Click "Manage Override"
4.  Set a custom commission type and value

**Priority:** Affiliate-specific overrides take highest priority, followed by product-specific commissions, with default settings as the fallback.

## How It Works

### 1\. Referral Click

User clicks an affiliate link and the `refgrow_ref_code` cookie is set.

### 2\. Stripe Payment

The referral code is passed to Stripe, and the user completes payment.

### 3\. Webhook Processing

Refgrow receives the webhook, attributes the sale, and calculates the commission.

## Subscription Commissions

For subscription products, Refgrow tracks commissions on:

-   **Initial payment** — commission on the first charge
-   **Recurring payments** — optional recurring commissions on each renewal (configurable per-project)
-   **Upgrades** — additional commission on the upgrade difference

Commission is automatically reversed on refunds and subscription cancellations.

## Supported Webhook Events

Refgrow automatically listens for these webhook events:

-   `checkout.session.completed` — When a purchase is completed
-   `invoice.paid` — When a subscription invoice is paid
-   `customer.subscription.created` — When a new subscription is created
-   `customer.subscription.updated` — When a subscription is updated (plan changes, renewals)
-   `customer.discount.created` — When a coupon is applied (for renewal tracking)
-   `charge.refunded` — When a charge is refunded

## Testing

1.  Use Stripe's test mode and test API keys during development
2.  Create a test affiliate in your Refgrow project
3.  Make a test purchase with the affiliate's referral code or coupon
4.  Verify the conversion appears in Refgrow with the correct commission
5.  Use the [Stripe CLI or webhook testing](https://dashboard.stripe.com/test/webhooks) to replay events

## Troubleshooting

### Webhooks Not Working

1.  Verify your Stripe API key is correctly set in your project settings
2.  Check that the webhook endpoint was created (URL should match `https://refgrow.com/webhook/stripe/{your-project-id}`)
3.  Confirm all required events are enabled for the webhook
4.  Check your Stripe dashboard for webhook delivery logs

### Commissions Not Attributing

**For "Click → Purchase" flow:**

-   Ensure the referral code is being passed to Stripe via metadata or client\_reference\_id
-   Check that your tracking script is installed on all pages
-   Verify the cookie is being set (check browser developer tools)

**For "Click → Signup → Purchase" flow:**

-   Verify the customer email in Stripe matches the email used during signup
-   Check that the referral attribution was created for the user
-   Consider passing the referral code to Stripe as a more reliable method

### Webhook Signature Verification Failing

-   Ensure the webhook secret matches exactly. The raw request body must not be parsed by JSON middleware before signature verification.

### Duplicate Conversions

-   Refgrow deduplicates by Stripe event ID. If you see duplicates, check for multiple webhook endpoints pointing to the same project.

## Next Steps

-   [Tracking Script](/docs/tracking) — learn more about Refgrow's client-side tracking
-   [API Reference](/docs/api-reference) — manage affiliates and conversions programmatically
-   [Widget Customization](/docs/widget) — customize the affiliate dashboard

---



<!-- ===== /docs/lemonsqueezy ===== -->

# LemonSqueezy Integration

> Source: https://refgrow.com/docs/lemonsqueezy

Automatically track purchases and calculate commissions with LemonSqueezy.

## Overview

Refgrow integrates with LemonSqueezy to automatically track payments and calculate commissions for your affiliates.

-   Automatic tracking of one-time payments and subscriptions
-   Support for product-specific commission rates
-   Support for affiliate-specific commission overrides
-   Secure webhook implementation for real-time tracking
-   Works with LemonSqueezy checkout pages and hosted checkout
-   Support for discount codes and coupon tracking

## Setting Up LemonSqueezy Integration

**Note:** You will need a LemonSqueezy account to track payments. If you do not have one, [sign up here](https://lemonsqueezy.com).

### Step 1: Add the Refgrow Tracking Script

Insert this snippet into the `<head>` of your site (any page where users land before purchasing):

```
<script src="https://scripts.refgrowcdn.com/page.js" data-project-id="YOUR_PROJECT_ID" async></script>
```

**Important:** Replace `YOUR_PROJECT_ID` with your actual project ID from the Refgrow dashboard.

### Step 2: Create a Webhook in LemonSqueezy

1.  Go to **LemonSqueezy → Settings → Webhooks**
2.  Click **Create Webhook**
3.  Configure the following settings:

#### Webhook Configuration

-   **URL:** `https://refgrow.com/webhook/lemonsqueezy/YOUR_PROJECT_ID`
-   **Events:** Enable at least:
    -   `order_created`
    -   `subscription_created`
    -   `subscription_payment_succeeded`
-   **Secret:** Copy the webhook secret and save it in your project's integration settings

### Step 3: Configure Webhook Secret

1.  Go to your project's "Integration" tab in Refgrow
2.  Select "LemonSqueezy Webhooks" as your tracking method
3.  Paste the webhook secret from LemonSqueezy
4.  Click "Save Integration Settings"

## Passing Referral Codes

**Tip:** There are multiple ways to pass referral codes to LemonSqueezy for proper attribution.

### Method 1: Automatic Custom Data (Recommended)

For checkout links that users visit after clicking a referral link, Refgrow automatically modifies the URLs. Simply add the class `refgrow-lemonsqueezy-link` to your links:

```
<a href="https://your-store.lemonsqueezy.com/checkout/buy/abc123" class="refgrow-lemonsqueezy-link">Buy Now</a>
```

Refgrow's tracking script will automatically:

-   Check if a referral code exists in cookies
-   Add `checkout[custom][referral_code]=CODE` to the link
-   Ensure proper attribution in LemonSqueezy webhooks

### Method 1b: Direct Custom Data in URL

You can also manually add the custom data parameter to LemonSqueezy checkout links:

```
<a href="https://your-store.lemonsqueezy.com/checkout/buy/abc123?checkout[custom][referral_code]=ALEX123">Buy Now</a>
```

**Note:** If you are adding LemonSqueezy links dynamically after page load, call `Refgrow.processLemonSqueezyLinks()` to process them automatically.

### Method 2: Manual Custom Data

If you are creating checkout sessions programmatically, you can pass the referral code in custom data:

```
// Example API call to LemonSqueezy
const checkoutData = {
  // ... other checkout parameters
  custom: {
    referral_code: 'ALEX123'
  }
};
```

### Method 3: Discount Codes

You can also track affiliates using unique discount codes:

1.  Create discount codes in LemonSqueezy for each affiliate
2.  In Refgrow, go to your project's "Coupons" tab
3.  Link each LemonSqueezy discount code to an affiliate
4.  When customers use the discount code, commissions are automatically attributed

## Commission Configuration

### Default Commission Settings

Configure your default commission structure in your project settings:

-   Commission Type: Percentage or Fixed Amount
-   Commission Value: The percentage or fixed amount
-   Commission Duration: Lifetime, First Purchase, or Limited Period

### Product-Specific Commissions

Override commission rates for specific products:

1.  Go to your project's "Integration" tab
2.  Scroll to "Product-Specific Commissions"
3.  Click "Add Product Commission"
4.  Enter the LemonSqueezy variant ID and set its unique commission rate

**Note:** Product-specific rates take priority over your default commission settings.

### Affiliate-Specific Overrides

Set custom commission rates for individual affiliates:

1.  Go to your "Affiliates" tab
2.  Find the affiliate you want to customize
3.  Click "Manage Override"
4.  Set a custom commission type and value

**Priority:** Affiliate-specific overrides take highest priority, followed by product-specific commissions, with default settings as the fallback.

## How It Works

### 1\. Referral Click

User clicks an affiliate link and the referral code is stored in a cookie.

### 2\. LemonSqueezy Payment

The referral code is passed to LemonSqueezy via custom data, and the user completes payment.

### 3\. Webhook Processing

Refgrow receives the webhook, attributes the sale, and calculates the commission.

## Supported Webhook Events

Refgrow automatically listens for these webhook events:

-   `order_created` - When a one-time purchase is completed
-   `subscription_created` - When a new subscription is created
-   `subscription_payment_succeeded` - When a subscription payment is processed

## Testing Your Integration

**Quick Test:** Use a test purchase to verify everything is working correctly.

### Test Steps

1.  Create a test affiliate in your Refgrow dashboard
2.  Generate a referral link for the test affiliate
3.  Click the referral link (this sets the tracking cookie)
4.  Complete a test purchase on LemonSqueezy
5.  Check your Refgrow dashboard to confirm:
    -   The conversion was recorded
    -   The correct commission was calculated
    -   The affiliate's earnings were updated

## Troubleshooting

### Webhooks Not Working

1.  Verify your webhook secret is correctly set in your project settings
2.  Check that the webhook endpoint was created with the correct URL: `https://refgrow.com/webhook/lemonsqueezy/{your-project-id}`
3.  Confirm all required events are enabled for the webhook
4.  Check your LemonSqueezy dashboard for webhook delivery logs
5.  Ensure the webhook signature verification is working

### Commissions Not Attributing

-   Ensure the Refgrow tracking script is installed on all pages
-   Verify the referral code is being passed correctly (check custom data in LemonSqueezy)
-   Check that the cookie is being set (check browser developer tools)
-   Confirm the affiliate's referral code matches exactly
-   Verify the customer email in LemonSqueezy matches the email used during signup (if applicable)
-   Check webhook logs for any processing errors

### Duplicate Conversions

Refgrow automatically prevents duplicate conversions by tracking:

-   LemonSqueezy Order ID
-   Product/Variant ID
-   Transaction timestamp

If you see duplicates, check your webhook configuration to ensure events are not being sent multiple times.

## Advanced Features

### Manual Conversion Tracking

For custom checkout flows, you can manually track conversions:

```
// Track a manual conversion
if (window.Refgrow) {
  Refgrow.track(purchaseAmount, 'purchase', 'customer@example.com');
}
```

### Multi-Currency Support

Refgrow automatically handles different currencies from LemonSqueezy:

-   Commissions are calculated in the original transaction currency
-   Dashboard displays amounts in your project's configured currency
-   Conversion rates are handled automatically

## Next Steps

### Using the Tracking Script

Learn more about Refgrow's client-side tracking.

[View Guide →](/docs/tracking)

### Commissions

Understand how commission calculations work.

[View Guide →](/docs/commissions)

### Managing Affiliates

Learn how to manage your affiliate program.

[View Guide →](/docs/affiliates)

---



<!-- ===== /docs/paddle ===== -->

# Paddle Integration

> Source: https://refgrow.com/docs/paddle

Automatically track purchases and calculate commissions with Paddle.

## Overview

Refgrow integrates with Paddle to automatically track payments and calculate commissions for your affiliates.

-   Automatic tracking of one-time payments and subscriptions
-   Support for product-specific commission rates
-   Support for affiliate-specific commission overrides
-   Secure webhook implementation for real-time tracking
-   Works with Paddle Checkout and payment links

## Setting Up Paddle Integration

**Note:** You will need a Paddle account to track payments. If you do not have one, [sign up here](https://paddle.com/signup).

### Step 1: Configure Webhook

1.  Go to your project's "Integration" tab
2.  Select "Paddle Webhooks" as your tracking method
3.  Copy the provided webhook URL
4.  In your Paddle dashboard, create a new webhook with the copied URL
5.  Enable these events: `transaction.completed`, `subscription.created`, `subscription.updated`
6.  Copy the webhook signing secret from Paddle
7.  Paste the signing secret in Refgrow and click "Save Secret"

### Step 2: Choose Your User Flow

Select the appropriate user conversion flow for your business:

-   **Click → Signup → Purchase:** Users create an account before making a purchase
-   **Click → Purchase:** Users can purchase directly without signing up first
-   **Both:** Your platform supports both flows

## Passing Referral Codes to Paddle

**Important:** If you have a direct purchase flow (Click → Purchase), passing the referral code to Paddle is essential for correct attribution.

### For Paddle Checkout

When creating a checkout on your server, pass the referral code in the custom data:

```
// Example (Node.js Server-Side)
const refCode = req.cookies.refgrow_ref_code; // Get code from cookie

const checkout = await paddle.checkouts.create({
  // ... other checkout parameters
  custom_data: {
    referral_code: refCode || null // Pass the code here
  }
});
```

### For Paddle Payment Links

For payment links, use the automatic processing with JavaScript:

#### Automatic Processing with JavaScript

1\. Add a special class to your payment links:

```
<a href="https://buy.paddle.com/product/xyz..." class="refgrow-paddle-link">Buy Now</a>
```

2\. Call the helper function after the page loads:

```
// Call this once after the page loads
if (window.Refgrow) {
  Refgrow.processPaddleLinks();
  // Or use a custom selector: Refgrow.processPaddleLinks('.your-paddle-class');
}
```

**Note:** Refgrow will automatically append the referral code via custom data to the Paddle link if a referral cookie exists.

## Commission Configuration

### Default Commission Settings

Configure your default commission structure in your project settings:

-   Commission Type: Percentage or Fixed Amount
-   Commission Value: The percentage or fixed amount
-   Commission Duration: Lifetime, First Purchase, or Limited Period

### Product-Specific Commissions

Override commission rates for specific products:

1.  Go to your project's "Integration" tab
2.  Scroll to "Product-Specific Commissions"
3.  Click "Add Product Commission"
4.  Select a Paddle product and set its unique commission rate

**Note:** Product-specific rates take priority over your default commission settings.

### Affiliate-Specific Overrides

Set custom commission rates for individual affiliates:

1.  Go to your "Affiliates" tab
2.  Find the affiliate you want to customize
3.  Click "Manage Override"
4.  Set a custom commission type and value

**Priority:** Affiliate-specific overrides take highest priority, followed by product-specific commissions, with default settings as the fallback.

## How It Works

### 1\. Referral Click

User clicks an affiliate link and the `refgrow_ref_code` cookie is set.

### 2\. Paddle Payment

The referral code is passed to Paddle, and the user completes payment.

### 3\. Webhook Processing

Refgrow receives the webhook, attributes the sale, and calculates the commission.

## Supported Webhook Events

Refgrow automatically listens for these webhook events:

-   `transaction.completed` - When a purchase is completed
-   `subscription.created` - When a new subscription is created
-   `subscription.updated` - When a subscription is updated

## Troubleshooting

### Webhooks Not Working

1.  Verify your webhook signing secret is correctly set in your project settings
2.  Check that the webhook endpoint was created with the correct URL: `https://refgrow.com/webhook/paddle/{your-project-id}`
3.  Confirm all required events are enabled for the webhook
4.  Check your Paddle dashboard for webhook delivery logs
5.  Ensure the webhook is active and not paused

### Commissions Not Being Calculated

1.  Verify that the customer email is included in the Paddle webhook data
2.  Check that referral codes are being passed correctly via custom data
3.  Ensure the affiliate exists in your Refgrow project
4.  Verify that trial orders with $0 amount are not triggering commissions (this is expected behavior)
5.  Check your commission settings and affiliate overrides

### Attribution Issues

1.  Verify that `tracking.js` is loaded on all pages
2.  Check that the referral code cookie is being set correctly
3.  For direct purchase flows, ensure you are using `Refgrow.processPaddleLinks()`
4.  Verify that custom data is being passed to Paddle correctly
5.  Check that the customer's email matches between the referral and the purchase

## Next Steps

Once your Paddle integration is set up:

-   [Set up payout methods](/docs/payouts) for your affiliates

---



<!-- ===== /docs/polar ===== -->

# Polar Integration

> Source: https://refgrow.com/docs/polar

Automatically track subscriptions and calculate commissions with Polar.

## Overview

Refgrow integrates with Polar to automatically track subscriptions and calculate commissions for your affiliates.

-   Automatic tracking of subscription creation and renewals
-   Support for product-specific commission rates
-   Support for affiliate-specific commission overrides
-   Secure webhook implementation for real-time tracking
-   Works with Polar's subscription management system

## Setting Up Polar Integration

**Note:** You will need a Polar account to track subscriptions. If you do not have one, [sign up here](https://polar.sh/signup).

### Step 1: Configure Webhook

1.  Go to your project's "Integration" tab
2.  Select "Polar Webhook" as your tracking method
3.  Copy the provided webhook URL
4.  In your Polar dashboard, go to Settings → Webhooks
5.  Create a new webhook with the copied URL
6.  Enable these events: `subscription.created`, `subscription.updated`, `subscription.canceled`, `subscription.renewed`
7.  Copy the webhook signing secret from Polar
8.  Paste the signing secret in Refgrow and click "Save Secret"

### Step 2: Choose Your User Flow

Select the appropriate user conversion flow for your business:

-   **Click → Signup → Subscribe:** Users create an account before subscribing
-   **Click → Subscribe:** Users can subscribe directly without signing up first
-   **Both:** Your platform supports both flows

## Passing Referral Codes to Polar

**Important:** If you have a direct subscription flow (Click → Subscribe), passing the referral code to Polar is essential for correct attribution.

### For Polar Subscriptions

When creating a subscription on your server, pass the referral code in the metadata:

```
// Example (Node.js Server-Side)
const refCode = req.cookies.refgrow_ref_code; // Get code from cookie

const subscription = await polar.subscriptions.create({
  // ... other subscription parameters
  metadata: {
    referral_code: refCode || null // Pass the code here
  }
});
```

### For Polar Checkout

For checkout sessions, include the referral code in the metadata:

```
// Example (Node.js Server-Side)
const refCode = req.cookies.refgrow_ref_code; // Get code from cookie

const checkout = await polar.checkouts.create({
  // ... other checkout parameters
  metadata: {
    referral_code: refCode || null // Pass the code here
  }
});
```

**Note:** Refgrow will automatically process the referral code from the subscription metadata when the webhook is received.

## Commission Configuration

### Default Commission Settings

Configure your default commission structure in your project settings:

-   Commission Type: Percentage or Fixed Amount
-   Commission Value: The percentage or fixed amount
-   Commission Duration: Lifetime, First Purchase, or Limited Period

### Product-Specific Commissions

Override commission rates for specific products:

1.  Go to your project's "Integration" tab
2.  Scroll to "Product-Specific Commissions"
3.  Click "Add Product Commission"
4.  Select a Polar product and set its unique commission rate

**Note:** Product-specific rates take priority over your default commission settings.

### Affiliate-Specific Overrides

Set custom commission rates for individual affiliates:

1.  Go to your "Affiliates" tab
2.  Find the affiliate you want to customize
3.  Click "Manage Override"
4.  Set a custom commission type and value

**Priority:** Affiliate-specific overrides take highest priority, followed by product-specific commissions, with default settings as the fallback.

## How It Works

### 1\. Referral Click

User clicks an affiliate link and the `refgrow_ref_code` cookie is set.

### 2\. Polar Subscription

The referral code is passed to Polar, and the user completes subscription.

### 3\. Webhook Processing

Refgrow receives the webhook, attributes the subscription, and calculates the commission.

## Supported Webhook Events

Refgrow automatically listens for these webhook events:

-   `subscription.created` - When a new subscription is created
-   `subscription.updated` - When a subscription is updated
-   `subscription.canceled` - When a subscription is canceled
-   `subscription.renewed` - When a subscription is renewed

## Troubleshooting

### Webhooks Not Working

1.  Verify your webhook signing secret is correctly set in your project settings
2.  Check that the webhook endpoint was created with the correct URL: `https://refgrow.com/webhook/polar/{your-project-id}`
3.  Confirm all required events are enabled for the webhook
4.  Check your Polar dashboard for webhook delivery logs
5.  Ensure the webhook is active and not paused

### Referral Codes Not Being Tracked

1.  Ensure the referral code is being passed in the subscription metadata
2.  Check that the affiliate with that referral code exists and is active
3.  Verify the referral code format matches exactly (case-sensitive)
4.  Check that the user has not been attributed to another affiliate already
5.  Review the webhook payload to confirm the referral code is present

### Commissions Not Calculating Correctly

1.  Check your default commission settings in project configuration
2.  Verify product-specific commission overrides if applicable
3.  Check affiliate-specific commission overrides
4.  Ensure the subscription amount is greater than zero
5.  Review the webhook payload for correct currency and amount values

### Duplicate Conversions

1.  Check that the same subscription is not being processed multiple times
2.  Verify webhook retry logic is not causing duplicates
3.  Review your subscription creation flow to prevent duplicate webhooks
4.  Check the conversion logs for duplicate subscription IDs

## API Reference

### Webhook Endpoint

```
POST https://refgrow.com/webhook/polar/{project-id}
```

### Required Headers

```
Content-Type: application/json
polar-signature: {hmac-sha256-signature}
```

### Webhook Payload Example

```
{
  "type": "subscription.created",
  "data": {
    "subscription": {
      "id": "sub_123456789",
      "customer": {
        "email": "customer@example.com"
      },
      "price": {
        "amount": 2900,
        "currency": "USD"
      },
      "product": {
        "id": "prod_123456789"
      },
      "metadata": {
        "referral_code": "ABC123"
      }
    }
  }
}
```

## Best Practices

### Security

-   Always verify webhook signatures
-   Use HTTPS for all webhook endpoints
-   Keep your webhook secrets secure
-   Monitor webhook delivery logs

### Reliability

-   Implement webhook retry logic
-   Handle webhook failures gracefully
-   Monitor webhook delivery status
-   Test webhooks in development first

## Need Help?

If you are experiencing issues with your Polar integration:

-   Check the [Troubleshooting Guide](/docs/troubleshooting) for common solutions
-   Review your webhook delivery logs in your Polar dashboard
-   Contact our support team with your project ID and specific error details

---



<!-- ===== /docs/dodo ===== -->

# Dodo Payments Integration

> Source: https://refgrow.com/docs/dodo

Automatically track payments and calculate commissions with Dodo Payments.

## Overview

Refgrow integrates with Dodo Payments to automatically track payments and calculate commissions for your affiliates.

-   Automatic tracking of one-time payments and subscriptions
-   Support for product-specific commission rates
-   Support for affiliate-specific commission overrides
-   Secure webhook implementation for real-time tracking
-   Works with Dodo Payments' subscription management system

## Setting Up Dodo Payments Integration

**Note:** You will need a Dodo Payments account to track payments. If you do not have one, [sign up here](https://dodopayments.com/signup).

### Step 1: Configure Webhook

1.  Go to your project's "Integration" tab
2.  Select "Dodo Payments" as your tracking method
3.  Copy the provided webhook URL
4.  In your Dodo Payments dashboard, go to Settings → Webhooks
5.  Create a new webhook with the copied URL
6.  Enable these events: `payment.completed`, `subscription.created`, `subscription.renewed`, `subscription.updated`, `payment.refunded`, `subscription.canceled`
7.  Copy the webhook signing secret from Dodo Payments
8.  Paste the signing secret in Refgrow and click "Save Secret"

### Step 2: Choose Your User Flow

Select the appropriate user conversion flow for your business:

-   **Click → Signup → Purchase:** Users create an account before purchasing
-   **Click → Purchase:** Users can purchase directly without signing up first
-   **Both:** Your platform supports both flows

## Passing Referral Codes to Dodo Payments

**Important:** If you have a direct purchase flow (Click → Purchase), passing the referral code to Dodo Payments is essential for correct attribution.

### For Dodo Payments

When creating a payment or subscription on your server, pass the referral code in the metadata:

```
// Example (Node.js Server-Side)
const refCode = req.cookies.refgrow_ref_code; // Get code from cookie

const payment = await dodo.payments.create({
  // ... other payment parameters
  metadata: {
    referral_code: refCode || null // Pass the code here
  }
});
```

### For Dodo Payments Checkout

For checkout sessions, include the referral code in the metadata:

```
// Example (Node.js Server-Side)
const refCode = req.cookies.refgrow_ref_code; // Get code from cookie

const checkout = await dodo.checkout.create({
  // ... other checkout parameters
  metadata: {
    referral_code: refCode || null // Pass the code here
  }
});
```

**Note:** Refgrow will automatically process the referral code from the payment metadata when the webhook is received.

## Commission Configuration

### Default Commission Settings

Configure your default commission structure in your project settings:

-   Commission Type: Percentage or Fixed Amount
-   Commission Value: The percentage or fixed amount
-   Commission Duration: Lifetime, First Purchase, or Limited Period

### Product-Specific Commissions

Override commission rates for specific products:

1.  Go to your project's "Integration" tab
2.  Scroll to "Product-Specific Commissions"
3.  Click "Add Product Commission"
4.  Select a Dodo Payments product and set its unique commission rate

**Note:** Product-specific rates take priority over your default commission settings.

### Affiliate-Specific Overrides

Set custom commission rates for individual affiliates:

1.  Go to your "Affiliates" tab
2.  Find the affiliate you want to customize
3.  Click "Manage Override"
4.  Set a custom commission type and value

**Priority:** Affiliate-specific overrides take highest priority, followed by product-specific commissions, with default settings as the fallback.

## How It Works

### 1\. Referral Click

User clicks an affiliate link and the `refgrow_ref_code` cookie is set.

### 2\. Dodo Payments

The referral code is passed to Dodo Payments, and the user completes payment.

### 3\. Webhook Processing

Refgrow receives the webhook, attributes the payment, and calculates the commission.

## Supported Webhook Events

Refgrow automatically listens for these webhook events:

-   `payment.completed` - When a one-time payment is completed
-   `subscription.created` - When a new subscription is created
-   `subscription.renewed` - When a subscription is renewed
-   `subscription.updated` - When a subscription is updated
-   `payment.refunded` - When a payment is refunded
-   `subscription.canceled` - When a subscription is canceled

## Troubleshooting

### Webhooks Not Working

1.  Verify your webhook signing secret is correctly set in your project settings
2.  Check that the webhook endpoint was created with the correct URL: `https://refgrow.com/webhook/dodo/{your-project-id}`
3.  Confirm all required events are enabled for the webhook
4.  Check your Dodo Payments dashboard for webhook delivery logs
5.  Ensure the webhook is active and not paused

### Referral Codes Not Being Tracked

1.  Ensure the referral code is being passed in the payment metadata
2.  Check that the affiliate with that referral code exists and is active
3.  Verify the referral code format matches exactly (case-sensitive)
4.  Check that the user has not been attributed to another affiliate already
5.  Review the webhook payload to confirm the referral code is present

### Commissions Not Calculating Correctly

1.  Check your default commission settings in project configuration
2.  Verify product-specific commission overrides if applicable
3.  Check affiliate-specific commission overrides
4.  Ensure the payment amount is greater than zero
5.  Review the webhook payload for correct currency and amount values

### Duplicate Conversions

1.  Check that the same payment is not being processed multiple times
2.  Verify webhook retry logic is not causing duplicates
3.  Review your payment creation flow to prevent duplicate webhooks
4.  Check the conversion logs for duplicate payment IDs

## API Reference

### Webhook Endpoint

```
POST https://refgrow.com/webhook/dodo/{project-id}
```

### Required Headers

```
Content-Type: application/json
dodo-signature: {hmac-sha256-signature}
```

### Webhook Payload Example

```
{
  "type": "payment.completed",
  "data": {
    "payment": {
      "id": "pay_123456789",
      "amount": 2900,
      "currency": "USD",
      "discount_amount": 0,
      "tax_amount": 290
    },
    "customer": {
      "email": "customer@example.com"
    },
    "product": {
      "id": "prod_123456789"
    },
    "metadata": {
      "referral_code": "ABC123"
    },
    "discount": {
      "code": "SAVE10"
    }
  }
}
```

## Best Practices

### Security

-   Always verify webhook signatures
-   Use HTTPS for all webhook endpoints
-   Keep your webhook secrets secure
-   Monitor webhook delivery logs

### Reliability

-   Implement webhook retry logic
-   Handle webhook failures gracefully
-   Monitor webhook delivery status
-   Test webhooks in development first

## Need Help?

If you are experiencing issues with your Dodo Payments integration:

-   Review your webhook delivery logs in your Dodo Payments dashboard
-   Contact our support team with your project ID and specific error details

---



<!-- ===== /docs/api-overview ===== -->

# API Overview

> Source: https://refgrow.com/docs/api-overview

Integrate and extend Refgrow programmatically.

## Introduction

Refgrow provides a RESTful API that allows you to integrate affiliate tracking and management functionality directly into your applications. The API enables you to track conversions, manage affiliates, retrieve statistics, and automate workflows.

The API is organized around REST principles. All requests should be made over HTTPS, and most API actions return JSON-encoded responses. Error responses include descriptive messages to help identify issues.

## Base URL

The base URL for all API requests is:

```
https://refgrow.com/api/v1
```

## Authentication

Authentication to the API is performed via API keys. Each request must include your API key in the Authorization header.

```
const headers = {
  'Authorization': 'Bearer YOUR_API_KEY',
  'Content-Type': 'application/json'
};
```

For more details on obtaining and using API keys, see the [Authentication](/docs/authentication) documentation.

## Available Endpoints

Refgrow API provides several endpoint categories:

### Program Management

Endpoint

Method

Description

`/api/v1/projects/:projectId/stripe-customer-referral-info/:stripeCustomerId`

GET

Get Stripe customer referral info for a project

### Affiliate Management

Endpoint

Method

Description

`/api/v1/affiliates`

GET

List affiliates

`/api/v1/affiliates`

POST

Create affiliate

`/api/v1/affiliates/:email`

GET

Get affiliate details by email

### Tracking

Endpoint

Method

Description

`/api/v1/referrals`

GET

List referrals

`/api/v1/referrals`

POST

Create a referral

### Coupons

Endpoint

Method

Description

`/api/v1/coupons`

GET

List coupons

`/api/v1/coupons`

POST

Create a coupon

### Conversions Management

Endpoint

Method

Description

`/api/v1/conversions`

GET

List conversions (registrations and purchases)

`/api/v1/conversions`

POST

Create a new conversion

`/api/v1/conversions/:id`

GET

Get conversion by ID

`/api/v1/conversions/:id`

PUT

Update conversion by ID

`/api/v1/conversions/:id`

DELETE

Delete conversion by ID

## Rate Limits

To ensure service stability, API requests are subject to rate limiting. Current limits are:

-   100 requests per minute per IP address
-   1000 requests per hour per API key

When a rate limit is exceeded, the API will return a 429 Too Many Requests response with a Retry-After header indicating when you can resume making requests.

## Error Handling

The API uses conventional HTTP response codes to indicate success or failure of requests:

-   **2xx** - Success
-   **4xx** - Client errors (invalid parameters, authentication issues)
-   **5xx** - Server errors

Error responses include a JSON object with error details:

```
{
  "error": {
    "code": "invalid_parameters",
    "message": "Missing required parameter: program_id",
    "status": 400
  }
}
```

## Example Requests

Below is an example of how to make a request to track a conversion:

```
// Example Node.js code for creating a conversion
const axios = require('axios');

async function createConversion() {
  try {
    const response = await axios.post('https://refgrow.com/api/v1/conversions', {
      customer_email: 'customer@example.com',
      amount: 49.99,
      referral_code: 'REF123'
    }, {
      headers: {
        'Authorization': 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json'
      }
    });

    console.log('Conversion created:', response.data);
  } catch (error) {
    console.error('Error creating conversion:', error.response ? error.response.data : error.message);
  }
}
```

## Next Steps

To learn more about specific API endpoints and functionality, explore these resources:

-   [Authentication Guide](/docs/authentication) \- Detailed information on API authentication
-   [API Endpoints](/docs/endpoints) \- Complete reference for all available endpoints
-   [Webhooks](/docs/webhooks) \- Set up real-time notifications for events in your affiliate program

---



<!-- ===== /docs/api-reference ===== -->

# API Reference

> Source: https://refgrow.com/docs/api-reference

The Refgrow REST API lets you manage affiliates, conversions, referrals, and coupons programmatically.

## API Introduction

Welcome to the Refgrow API documentation. This API allows you to programmatically interact with your affiliate program data, including affiliates, conversions, referrals, and coupons.

The base URL for all API endpoints is: `https://refgrow.com/api/v1`

## Authentication

All API requests require a Bearer token. Generate an API key from your project settings under **API Keys**. API keys have the prefix `rgk_`.

```
Authorization: Bearer rgk_YOUR_API_KEY
```

**Security:** API keys are stored hashed (bcrypt) in the database. Keep your key secret and never expose it in client-side code. All API requests must be made over HTTPS.

## Affiliates

Endpoints for managing affiliates within your project.

### List Affiliates

GET`/api/v1/affiliates`

Retrieves a list of affiliates associated with your project. Supports pagination and filtering.

#### Query Parameters

Parameter

Type

Required

Description

`limit`

integer

Optional

Number of affiliates to return (default: 20).

`offset`

integer

Optional

Number of affiliates to skip (for pagination, default: 0).

`status`

string

Optional

Filter by status (e.g., 'active', 'inactive').

#### Example Request (cURL)

```
curl -X GET "https://refgrow.com/api/v1/affiliates?limit=10&status=active" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

#### Example Request (Node.js)

```
const response = await fetch(
  'https://refgrow.com/api/v1/affiliates?limit=10&status=active',
  {
    headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
  }
);
const data = await response.json();
console.log(data);
```

#### Example Response (200 OK)

```
{
  "success": true,
  "data": [
    {
      "id": 123,
      "user_email": "affiliate1@example.com",
      "referral_code": "REF123",
      "created_at": "2024-01-15T10:00:00.000Z",
      "status": "active",
      "clicks": 58,
      "signups": 12,
      "purchases": 5,
      "unpaid_earnings": "50.00",
      "total_earnings": "150.00",
      "eligible_earnings": "35.00",
      "held_earnings": "15.00",
      "next_release_date": "2024-02-15T10:00:00.000Z"
    }
  ],
  "pagination": {
    "limit": 10,
    "offset": 0,
    "total": 55,
    "has_more": true
  }
}
```

#### Hold Period Fields

When a project has a hold period configured, affiliate responses include additional earnings breakdown fields:

Field

Type

Description

`eligible_earnings`

string

Earnings that have passed the hold period and are available for payout.

`held_earnings`

string

Earnings still within the hold period, not yet eligible for payout.

`next_release_date`

string (ISO date) or null

Date when the next batch of held earnings will become eligible. Null if no earnings are held.

**Note:** `total_earnings` = `eligible_earnings` + `held_earnings` + `paid_earnings`

### Create Affiliate

POST`/api/v1/affiliates`

Creates a new affiliate for your project.

#### Request Body (JSON)

Parameter

Type

Required

Description

`email`

string

Yes

The email address of the affiliate. Must be unique per project.

`referral_code`

string

Optional

A unique referral code. If omitted, one will be generated automatically.

`partner_slug`

string

Optional

Sub-program slug (Pro/Business plans).

`payment_method`

string

Optional

Payment method name (e.g. "USDT TRC-20", "Bank Transfer"). Created on the project automatically if it does not already exist.

`payment_details`

string

Optional

Free-text payout details for the chosen method (wallet address, IBAN, etc.).

#### Example Request (cURL)

```
curl -X POST "https://refgrow.com/api/v1/affiliates" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "new.affiliate@example.com",
    "referral_code": "NEWCODE",
    "payment_method": "USDT TRC-20",
    "payment_details": "TXyz...wallet"
  }'
```

#### Example Response (201 Created)

```
{
  "success": true,
  "data": {
    "id": 124,
    "user_email": "new.affiliate@example.com",
    "referral_code": "NEWCODE",
    "unpaid_earnings": null,
    "total_earnings": null,
    "created_at": "2024-07-29T12:30:00.000Z",
    "status": "active"
  }
}
```

**Error Responses:** `400` Invalid email or parameters. `409` Email or referral code already exists.

### Retrieve Affiliate

GET`/api/v1/affiliates/:email`

Retrieves details, including calculated stats, for a specific affiliate by their email address. The email must be URL-encoded.

#### Example Request (cURL)

```
curl -X GET "https://refgrow.com/api/v1/affiliates/affiliate1%40example.com" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

#### Example Response (200 OK)

```
{
  "success": true,
  "data": {
    "id": 123,
    "user_email": "affiliate1@example.com",
    "referral_code": "REF123",
    "created_at": "2024-01-15T10:00:00.000Z",
    "status": "active",
    "clicks": 58,
    "signups": 12,
    "purchases": 5,
    "unpaid_earnings": "50.00",
    "total_earnings": "150.00"
  }
}
```

**Error Responses:** `400` Invalid email format. `404` Affiliate not found.

### Update Affiliate

PUT`/api/v1/affiliates/:email`

Updates specific details for an existing affiliate. Include only the fields you want to update.

#### Request Body (JSON)

Parameter

Type

Description

`email`

string

New email address. Must be unique per project.

`referral_code`

string

New unique referral code.

`status`

string

Update the status ('active' or 'inactive').

`payout_method`

string

Auto-payout channel: 'paypal', 'wise', or 'manual'.

`paypal_email`

string

PayPal email used when `payout_method` is 'paypal'.

`payment_method`

string

Payment method name (e.g. "USDT TRC-20"). Created automatically if it does not exist.

`payment_details`

string

Free-text payout details (wallet address, IBAN, etc.).

#### Example Request (cURL)

```
curl -X PUT "https://refgrow.com/api/v1/affiliates/affiliate1%40example.com" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status": "inactive"}'
```

**Error Responses:** `400` Invalid parameters. `404` Not found. `409` Conflict with existing data.

### Delete Affiliate

DELETE`/api/v1/affiliates/:email`

Permanently deletes an affiliate and all associated data.

**Warning:** This action is irreversible.

#### Example Request (cURL)

```
curl -X DELETE "https://refgrow.com/api/v1/affiliates/affiliate1%40example.com" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Returns `204 No Content` on success.

## Conversions

Endpoints for managing conversions (registrations and purchases) attributed to affiliates. Use these to record, view, and manage conversion events for your project.

### List Conversions

GET`/api/v1/conversions`

Retrieves a list of conversions for your project. Supports pagination and filtering.

#### Query Parameters

Parameter

Type

Required

Description

`limit`

integer

Optional

Number of conversions to return (default: 50).

`offset`

integer

Optional

Number of conversions to skip (default: 0).

`type`

string

Optional

Filter by type (`signup` or `purchase`).

`affiliate_id`

integer

Optional

Filter by affiliate ID.

`referred_user_id`

integer

Optional

Filter by referred user ID.

`paid`

boolean

Optional

Filter by payout status (`true` or `false`).

`from`

string (ISO date)

Optional

Filter conversions created after this date.

`to`

string (ISO date)

Optional

Filter conversions created before this date.

#### Example Request (cURL)

```
curl -X GET "https://refgrow.com/api/v1/conversions?type=purchase&affiliate_id=123&paid=true" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

#### Example Response (200 OK)

```
{
  "success": true,
  "data": [
    {
      "id": 1001,
      "type": "purchase",
      "affiliate_id": 123,
      "referred_user_id": 501,
      "value": 12.5,
      "base_value": 250,
      "base_value_currency": "USD",
      "paid": false,
      "created_at": "2024-07-29T13:00:00.000Z",
      "reference": "ORDER-123",
      "coupon_code_used": "SUMMER2024"
    }
  ],
  "pagination": {
    "limit": 50,
    "offset": 0,
    "total": 2,
    "has_more": false
  }
}
```

### Create Conversion

POST`/api/v1/conversions`

Manually creates a new conversion (registration or purchase). Use this to record conversions from your backend. Also triggers `referral_converted` and `referral_updated` webhook events automatically.

#### Request Body (JSON)

Parameter

Type

Required

Description

`type`

string

Yes

Conversion type: `signup` or `purchase`.

`affiliate_id`

integer

Optional

ID of the affiliate to credit. Takes priority over everything else.

`referral_code`

string

Optional

Referral code of the affiliate to credit, if you have it instead of the ID.

`email`

string

Optional

Customer email. Used to credit the right affiliate when you send neither `affiliate_id` nor `referral_code`, and to detect renewals so recurring commission rates apply.

`referred_user_id`

integer

Optional

ID of the referred user (if known).

`value`

number

Optional

Commission value (will be calculated if omitted).

`base_value`

number

Optional

Original transaction value (required for purchases).

`base_value_currency`

string

Optional

Currency code (e.g., USD, EUR).

`paid`

boolean

Optional

Payout status (default: false).

`reference`

string

Optional

Your own identifier for the charge, such as an invoice or order ID. Also acts as an idempotency key. Sending the same reference twice returns the original conversion instead of creating a second one, so a retried webhook cannot pay an affiliate twice.

`coupon_code_used`

string

Optional

Coupon code used for this conversion.

#### How the affiliate is chosen

Refgrow credits the first match, in this order: `affiliate_id`, then `referral_code`, then the customer `email`.

The email step matters for backend integrations. If your payment step runs on the server (a Clerk hook, a hosted checkout, a billing provider callback) the referral code was captured in the browser at signup and never reaches that code path. Send just the email and the amount: Refgrow looks up which affiliate referred that customer and credits them, exactly as the Stripe integration does. Send the code as well whenever you have it, since that is an exact match rather than a lookup.

Every response includes an `attribution` object showing which affiliate was credited and how, so you can confirm your integration works on the very first call rather than discovering later that nothing was attributed.

#### Hold period

If your program has a hold period, conversions created here respect it just like the ones from your payment provider. The conversion is recorded straight away with a status of `pending` and becomes payable automatically once the period passes. With no hold period configured it is `active` immediately. The status is on the conversion in the response.

#### Recurring payments

Send one call per charge, including renewals, with the same customer email each time. Refgrow recognises a repeat payment from that email and applies your recurring commission rate and your commission duration, so a lifetime program keeps paying and a capped one stops on schedule. Nothing extra is needed on your side.

Give each charge its own `reference`. It doubles as an idempotency key, which matters here because payment hooks retry: a resent webhook returns the original conversion with `duplicate: true` rather than crediting the affiliate a second time.

#### Example Request (cURL)

```
curl -X POST "https://refgrow.com/api/v1/conversions" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "purchase",
    "email": "customer@example.com",
    "base_value": 250,
    "base_value_currency": "USD",
    "reference": "ORDER-123"
  }'

# Response
# {
#   "success": true,
#   "data": { ... },
#   "attribution": { "affiliate_id": 123, "matched_by": "email" }
# }
```

#### Example Request (Node.js)

```
const response = await fetch('https://refgrow.com/api/v1/conversions', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    type: 'purchase',
    affiliate_id: 123,
    base_value: 250,
    base_value_currency: 'USD',
    reference: 'ORDER-123'
  })
});

const result = await response.json();
console.log(result);
```

#### Example Response (201 Created)

```
{
  "success": true,
  "data": {
    "id": 1002,
    "type": "purchase",
    "affiliate_id": 123,
    "referred_user_id": 501,
    "value": 12.5,
    "base_value": 250,
    "base_value_currency": "USD",
    "paid": false,
    "created_at": "2024-07-29T13:05:00.000Z",
    "reference": "ORDER-123",
    "coupon_code_used": null
  }
}
```

**Error Responses:** `400` Invalid parameters or missing required fields. `404` Affiliate or user not found. `409` Duplicate conversion for this reference.

### Retrieve Conversion

GET`/api/v1/conversions/:id`

Retrieves details for a specific conversion by its ID.

#### Example Request (cURL)

```
curl -X GET "https://refgrow.com/api/v1/conversions/1002" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Error Responses:** `400` Invalid conversion ID. `404` Conversion not found.

### Update Conversion

PUT`/api/v1/conversions/:id`

Updates specific fields for an existing conversion. Also triggers `referral_updated` webhook event.

#### Updatable Fields

Parameter

Type

Description

`value`

number

Update the commission value.

`base_value`

number

Update the original transaction value.

`type`

string

Update conversion type (`signup` or `purchase`).

`paid`

boolean

Update the payout status.

`reference`

string

Update the custom reference.

`coupon_code_used`

string

Update the coupon code used.

`base_value_currency`

string

Update the currency code.

#### Example Request (cURL)

```
curl -X PUT "https://refgrow.com/api/v1/conversions/1002" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"paid": true}'
```

### Delete Conversion

DELETE`/api/v1/conversions/:id`

Permanently deletes a conversion by its ID.

**Warning:** This action is irreversible.

#### Example Request (cURL)

```
curl -X DELETE "https://refgrow.com/api/v1/conversions/1002" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Returns `204 No Content` on success.

## Referrals

Endpoints for managing referred users associated with your affiliates.

### List Referrals

GET`/api/v1/referrals`

Retrieves a list of referred users for your project. Supports pagination and filtering.

#### Query Parameters

Parameter

Type

Required

Description

`limit`

integer

Optional

Number of referrals to return (default: 20).

`offset`

integer

Optional

Number of referrals to skip (default: 0).

`affiliate_id`

integer

Optional

Filter by the associated affiliate ID.

`status`

string

Optional

Filter by conversion status ('pending', 'converted', 'direct', 'direct\_signup').

#### Example Request (cURL)

```
curl -X GET "https://refgrow.com/api/v1/referrals?affiliate_id=123&status=converted" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

#### Example Response (200 OK)

```
{
  "success": true,
  "data": [
    {
      "id": 501,
      "user_email": "customer1@example.com",
      "conversion_status": "converted",
      "conversion_date": "2024-02-10T11:05:00.000Z",
      "created_at": "2024-02-01T09:00:00.000Z",
      "affiliate_id": 123,
      "affiliate_code": "REF123"
    }
  ],
  "pagination": {
    "limit": 20,
    "offset": 0,
    "total": 5,
    "has_more": false
  }
}
```

### Create Referral

POST`/api/v1/referrals`

Manually creates a new referred user record. This is typically handled automatically by tracking, but can be used for manual attribution.

#### Request Body (JSON)

Parameter

Type

Required

Description

`email`

string

Yes

Email of the referred user. Must be unique per project.

`affiliate_id`

integer

Optional

ID of the referring affiliate. If omitted, treated as a direct signup.

`status`

string

Optional

Conversion status ('pending', 'converted', 'direct', 'direct\_signup'). Defaults to 'pending'.

#### Example Request (cURL)

```
curl -X POST "https://refgrow.com/api/v1/referrals" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "manual.customer@example.com",
    "affiliate_id": 123,
    "status": "converted"
  }'
```

#### Example Response (201 Created)

```
{
  "success": true,
  "data": {
    "id": 502,
    "user_email": "manual.customer@example.com",
    "affiliate_id": 123,
    "conversion_status": "converted",
    "conversion_date": "2024-07-29T13:00:00.000Z",
    "created_at": "2024-07-29T13:00:00.000Z"
  }
}
```

**Error Responses:** `400` Invalid email or parameters. `404` Specified affiliate\_id does not exist. `409` Referred user with this email already exists.

### Retrieve Referral

GET`/api/v1/referrals/:email`

Retrieves details for a specific referred user by their email address. The email must be URL-encoded.

#### Example Request (cURL)

```
curl -X GET "https://refgrow.com/api/v1/referrals/customer1%40example.com" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Update Referral

PUT`/api/v1/referrals/:email`

Updates specific details for an existing referred user.

#### Updatable Fields

Parameter

Type

Description

`email`

string

New email address. Must be unique per project.

`affiliate_id`

integer | null

Change the associated affiliate ID, or set to null to disassociate.

`status`

string

Update conversion status. Setting to 'converted' or 'direct' updates conversion\_date.

#### Example Request (cURL)

```
curl -X PUT "https://refgrow.com/api/v1/referrals/manual.customer%40example.com" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"affiliate_id": null, "status": "direct"}'
```

## Coupons

Endpoints for managing affiliate coupons. Coupons are used for conversion attribution when customers use a coupon code that matches an affiliate's assigned code.

### List Coupons

GET`/api/v1/coupons`

Returns all coupons associated with affiliates in your project. Supports pagination and filtering.

### Create Coupon

POST`/api/v1/coupons`

#### Request Body (JSON)

```
{
  "affiliate_id": 42,
  "coupon_code": "JANE20",
  "stripe_coupon_id": "promo_xxx"
}
```

### Retrieve Coupon

GET`/api/v1/coupons/:id`

Retrieves details for a specific coupon by its ID.

### Update Coupon

PUT`/api/v1/coupons/:id`

Updates a coupon's details.

### Delete Coupon

DELETE`/api/v1/coupons/:id`

Permanently deletes a coupon.

## Error Handling

The API uses standard HTTP status codes. Error responses include a JSON body with a `success` field set to `false` and an `error` message:

```
{
  "success": false,
  "error": "Affiliate not found"
}
```

Status

Meaning

`200`

Success

`201`

Created

`204`

Deleted (no content)

`400`

Bad request (missing or invalid parameters)

`401`

Unauthorized (invalid or missing API key)

`403`

Forbidden (API key does not have permission)

`404`

Resource not found

`409`

Conflict (duplicate resource)

`429`

Rate limited

`500`

Internal server error

## Rate Limits

API requests are limited to 100 requests per minute per API key. Rate limit headers are included in every response:

-   `X-RateLimit-Limit` — requests allowed per window
-   `X-RateLimit-Remaining` — requests remaining
-   `X-RateLimit-Reset` — Unix timestamp when the window resets

---



<!-- ===== /docs/authentication ===== -->

# Authentication

> Source: https://refgrow.com/docs/authentication

Securing access to your Refgrow instance and affiliate dashboard.

## Overview

Refgrow provides multiple authentication options to meet your security requirements and integrate with your existing user systems. This guide explains how to implement authentication for both program administrators and affiliates.

## Administrator Authentication

### Standard Email/Password Login

Refgrow offers a built-in authentication system for program administrators:

1.  Email and password credentials
2.  Two-factor authentication (2FA) for enhanced security
3.  Password reset functionality

This is the default authentication method used when you create your Refgrow account.

### Social Authentication

Connect your Refgrow administrator account with popular OAuth providers:

-   Google
-   GitHub

To enable social authentication:

1.  Go to your account settings
2.  Navigate to the "Authentication" tab
3.  Select the social providers you want to enable
4.  Follow the prompts to connect your accounts

### Two-Factor Authentication (2FA)

Enable 2FA for an extra layer of security on your Refgrow administrator account:

1.  Go to your account settings
2.  Navigate to the "Security" tab
3.  Click "Enable 2FA"
4.  Scan the QR code with an authenticator app like Google Authenticator or Authy
5.  Enter the verification code to confirm setup
6.  Save your backup codes in a secure location

Once enabled, you'll need to enter both your password and a time-based one-time password (TOTP) from your authenticator app when logging in.

## Affiliate Authentication

### Standalone Authentication

If you're using Refgrow's standalone affiliate dashboard, affiliates can use:

-   Email and password registration
-   Magic link authentication (passwordless login via email)

This is ideal for programs where affiliates don't have accounts in your main application or when you're using Refgrow as a separate affiliate system.

### Integrating with Your Existing User System

If you already have users in your application, you can integrate Refgrow with your existing authentication:

#### JWT Authentication

Pass a JSON Web Token (JWT) when embedding the Refgrow affiliate dashboard:

```
<div
  id="refgrow-affiliate-dashboard"
  data-project-id="YOUR_PROGRAM_ID"
  data-project-email="user@example.com"
  data-auth-token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
></div>

<script src="https://cdn.refgrow.com/js/affiliate-dashboard.js"></script>
```

The JWT should include:

-   `email`: The affiliate's email address
-   `name`: The affiliate's display name
-   `exp`: Expiration timestamp

Sign the JWT with your Refgrow API secret from your program settings.

### Setting Up a Custom Authentication Endpoint

For advanced integration, you can set up a custom authentication endpoint:

1.  Create an API endpoint in your application that validates user credentials
2.  Configure this endpoint in your Refgrow program settings under "Authentication"
3.  Refgrow will call this endpoint when affiliates attempt to log in

Your endpoint should:

-   Accept POST requests with username/password or token
-   Return a JSON response with authentication status and user details
-   Include proper CORS headers if your application and Refgrow are on different domains

#### Example Endpoint Response:

```
{
  "success": true,
  "user": {
    "email": "affiliate@example.com",
    "name": "John Doe",
    "id": "user_12345",
    "customData": {
      "accountType": "premium",
      "joinedDate": "2023-01-15"
    }
  }
}
```

## Security Best Practices

### Use Strong Passwords

Encourage administrators and affiliates to use strong, unique passwords with a combination of uppercase and lowercase letters, numbers, and special characters.

### Enable 2FA

Enable two-factor authentication for all administrator accounts and consider making it mandatory for enhanced security.

### Regular Token Rotation

Regularly rotate your API keys and authentication tokens, especially if you suspect a security breach.

### Set Short JWT Expiration

When using JWTs, set reasonable expiration times to limit the window of opportunity if a token is compromised.

## Troubleshooting

### JWT Authentication Issues

If affiliates can't log in with JWT authentication:

1.  Verify your JWT is properly signed with the correct secret key
2.  Ensure the JWT hasn't expired
3.  Check that all required claims (email, name, exp) are included
4.  Verify the email in the JWT matches the email in data-project-email

### Custom Endpoint Authentication Failures

If your custom authentication endpoint isn't working:

1.  Check your server logs for detailed error information
2.  Verify CORS headers are properly set if needed
3.  Ensure your endpoint returns the expected JSON structure
4.  Test the endpoint directly with a tool like Postman

### 2FA Issues

If you're having trouble with two-factor authentication:

1.  Ensure your device's time is correctly synchronized
2.  Try using your backup codes if you can't access your authenticator app
3.  Contact support if you've lost access to both your authenticator app and backup codes

## Next Steps

-   Learn about [security best practices](/docs/security) for your Refgrow installation
-   Explore [dashboard customization](/docs/customization) options
-   Set up [conversion tracking](/docs/tracking) for your affiliates

---



<!-- ===== /docs/endpoints ===== -->

# API Endpoints

> Source: https://refgrow.com/docs/endpoints

Reference for the Refgrow API endpoints.

## Overview

The Refgrow API allows you to integrate affiliate functionality directly into your application. This reference documents the available endpoints, required parameters, and response formats.

All API requests require authentication using your API key, which you can find in your program settings under the "API" tab.

## Authentication

To authenticate API requests, include your API key in the request headers:

```
{
  "Authorization": "Bearer YOUR_API_KEY"
}
```

## Base URL

All API endpoints use the following base URL:

```
https://refgrow.com/api/v1
```

## Affiliate Endpoints

### GET/affiliates - List Affiliates

Retrieves a list of all affiliates in your program.

#### Query Parameters

Parameter

Type

Description

`limit`

integer

Maximum number of affiliates to return (default: 20, max: 100)

`offset`

integer

Number of affiliates to skip (for pagination)

`status`

string

Filter affiliates by status (active, pending, blocked)

#### Response Example

```
{
  "success": true,
  "data": {
    "affiliates": [
      {
        "id": "aff_123456",
        "email": "affiliate@example.com",
        "name": "John Doe",
        "status": "active",
        "createdAt": "2023-06-15T10:30:00Z",
        "totalEarnings": 1250.75,
        "pendingEarnings": 350.25,
        "paidEarnings": 900.50,
        "conversionRate": 0.12,
        "clickCount": 1840,
        "conversionCount": 221
      }
    ],
    "total": 45,
    "limit": 20,
    "offset": 0
  }
}
```

### GET/affiliates/:email - Get Affiliate Details

Retrieves detailed information about a specific affiliate by email address.

#### URL Parameters

Parameter

Type

Description

`email`

string

The affiliate's email address

#### Response Example

```
{
  "success": true,
  "data": {
    "affiliate": {
      "id": "aff_123456",
      "email": "affiliate@example.com",
      "name": "John Doe",
      "status": "active",
      "createdAt": "2023-06-15T10:30:00Z",
      "totalEarnings": 1250.75,
      "pendingEarnings": 350.25,
      "paidEarnings": 900.50,
      "conversionRate": 0.12,
      "clickCount": 1840,
      "conversionCount": 221,
      "referralCode": "JOHNDOE10",
      "paymentMethod": "paypal",
      "paymentDetails": "affiliate@example.com"
    }
  }
}
```

### POST/affiliates - Create Affiliate

Creates a new affiliate in your program.

#### Request Body Parameters

Parameter

Type

Required

Description

`email`

string

Yes

The affiliate's email address

`name`

string

Yes

The affiliate's full name

`referralCode`

string

No

Custom referral code (if not provided, one will be generated)

`parent_referral_code`

string

No

For multi-tier programs: the referral code of the affiliate who recruited this one. Sets parent\_affiliate\_id so the new affiliate becomes a tier-2 partner. Requires multi-tier enabled on the project.

`parent_affiliate_id`

number

No

Same purpose as parent\_referral\_code, but you pass the numeric affiliate id directly. Use either field, not both.

`customFields`

object

No

Any additional custom data for the affiliate

#### Response Example

```
{
  "success": true,
  "data": {
    "affiliate": {
      "id": "aff_123456",
      "email": "affiliate@example.com",
      "name": "John Doe",
      "status": "active",
      "createdAt": "2023-06-15T10:30:00Z",
      "referralCode": "JOHNDOE10"
    }
  }
}
```

## Referral Endpoints

### GET/referrals - List Referrals

Retrieves a list of referrals in your program.

#### Query Parameters

Parameter

Type

Description

`limit`

integer

Maximum number of referrals to return (default: 20, max: 100)

`offset`

integer

Number of referrals to skip (for pagination)

#### Response Example

```
{
  "success": true,
  "data": {
    "referrals": [
      {
        "email": "referred@example.com",
        "referral_code": "JOHNDOE10",
        "affiliate_email": "affiliate@example.com",
        "created_at": "2023-06-18T14:25:30Z"
      }
    ],
    "total": 120,
    "limit": 20,
    "offset": 0
  }
}
```

### POST/referrals - Create Referral

Creates a new referral attribution.

#### Request Body Parameters

Parameter

Type

Required

Description

`email`

string

Yes

The referred customer's email address

`referral_code`

string

Yes

The affiliate's referral code

#### Response Example

```
{
  "success": true,
  "data": {
    "referral": {
      "email": "referred@example.com",
      "referral_code": "JOHNDOE10",
      "created_at": "2023-06-18T15:10:45Z"
    }
  }
}
```

### GET/referrals/:email - Get Referral by Email

Retrieves referral information for a specific email address.

#### URL Parameters

Parameter

Type

Description

`email`

string

The referred customer's email address

## Conversion Endpoints

### GET/conversions - List Conversions

Retrieves a list of conversions (registrations and purchases) in your program.

#### Query Parameters

Parameter

Type

Description

`limit`

integer

Maximum number of conversions to return (default: 20, max: 100)

`offset`

integer

Number of conversions to skip (for pagination)

#### Response Example

```
{
  "success": true,
  "data": {
    "conversions": [
      {
        "id": 12345,
        "customer_email": "customer@example.com",
        "amount": 99.99,
        "commission_amount": 20.00,
        "status": "pending",
        "created_at": "2023-06-18T15:10:45Z",
        "referral_code": "JOHNDOE10"
      }
    ],
    "total": 32,
    "limit": 20,
    "offset": 0
  }
}
```

### POST/conversions - Create Conversion

Creates a new conversion record.

#### Request Body Parameters

Parameter

Type

Required

Description

`customer_email`

string

Yes

The customer's email address

`amount`

number

Yes

The purchase amount or value of the conversion

`referral_code`

string

No

The affiliate's referral code (used for attribution if no prior referral exists)

#### Response Example

```
{
  "success": true,
  "data": {
    "conversion": {
      "id": 12345,
      "customer_email": "customer@example.com",
      "amount": 99.99,
      "commission_amount": 20.00,
      "referral_code": "JOHNDOE10",
      "created_at": "2023-06-18T15:10:45Z"
    }
  }
}
```

## Coupon Endpoints

### GET/coupons - List Coupons

Retrieves a list of coupons in your program.

#### Response Example

```
{
  "success": true,
  "data": {
    "coupons": [
      {
        "id": 1,
        "code": "PARTNER20",
        "affiliate_email": "affiliate@example.com",
        "discount_type": "percentage",
        "discount_value": 20,
        "created_at": "2023-06-15T10:30:00Z"
      }
    ],
    "total": 10,
    "limit": 20,
    "offset": 0
  }
}
```

### POST/coupons - Create Coupon

Creates a new coupon linked to an affiliate.

#### Request Body Parameters

Parameter

Type

Required

Description

`code`

string

Yes

The coupon code

`affiliate_email`

string

Yes

The email of the affiliate to link the coupon to

#### Response Example

```
{
  "success": true,
  "data": {
    "coupon": {
      "id": 1,
      "code": "PARTNER20",
      "affiliate_email": "affiliate@example.com",
      "created_at": "2023-06-15T10:30:00Z"
    }
  }
}
```

## Payout Endpoints

Use these when you pay commissions outside Refgrow, for example by bank transfer, Wise or PayPal. Recording the payout files it in payout history, subtracts it from the affiliate's unpaid balance, and marks the conversions it covers as paid, all in one call.

### POST/payouts - Record a Payout

#### Body Parameters

Parameter

Type

Description

`affiliate_id`

integer

The affiliate you paid. Either this or `affiliate_email` is required.

`affiliate_email`

string

Alternative to `affiliate_id`.

`amount`

number

Required. Cannot exceed the affiliate's unpaid earnings.

`method`

string

manual (default), paypal, wise, bank, crypto or other.

`payment_date`

string

ISO date the money actually went out. Defaults to now.

#### Example Request

```
curl -X POST https://refgrow.com/api/v1/payouts \
  -H "Authorization: Bearer rgk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "affiliate_email": "affiliate@example.com",
    "amount": 179.78,
    "method": "wise",
    "payment_date": "2026-07-21"
  }'
```

#### Example Response

```
{
  "success": true,
  "data": {
    "id": 412,
    "affiliate_id": 60890,
    "affiliate_email": "affiliate@example.com",
    "amount": "179.78",
    "status": "Paid",
    "payment_method": "wise",
    "payment_date": "2026-07-21T00:00:00.000Z",
    "conversions_settled": 3,
    "unpaid_earnings_after": 0
  }
}
```

Conversions are settled oldest first, and only up to the amount you recorded, so a partial payout leaves the remainder outstanding. Conversions still inside the hold period, refunded, rejected or held for review are never touched. A `payout.created` webhook fires after a successful call.

### GET/payouts - List Payouts

Returns recorded payouts, newest first. Accepts `limit`(max 200), `offset`, and `affiliate_id` to filter to a single affiliate.

```
curl https://refgrow.com/api/v1/payouts?limit=20 \
  -H "Authorization: Bearer rgk_your_api_key"
```

## Error Responses

When an error occurs, the API will return an appropriate HTTP status code along with a JSON response containing error details:

```
{
  "success": false,
  "error": {
    "code": "invalid_request",
    "message": "Invalid affiliate ID format",
    "details": {
      "field": "affiliateId",
      "issue": "must be a string beginning with 'aff_'"
    }
  }
}
```

### Common Error Codes

Error Code

HTTP Status

Description

`authentication_error`

401

Invalid API key or authentication token

`permission_denied`

403

The authenticated user doesn't have permission for the requested operation

`resource_not_found`

404

The requested resource (affiliate, commission, etc.) doesn't exist

`invalid_request`

400

The request parameters are invalid or incomplete

`rate_limit_exceeded`

429

You've exceeded the API rate limit

`server_error`

500

An internal server error occurred

## Next Steps

-   Explore Refgrow's [tracking options](/docs/tracking)
-   Learn about [webhooks](/docs/webhooks) for real-time notifications
-   Understand how to [secure your API integration](/docs/security)

---



<!-- ===== /docs/cli ===== -->

# Refgrow CLI

> Source: https://refgrow.com/docs/cli

Manage your Refgrow affiliate program from the command line. Wraps the public REST API v1 so shell scripts, cron jobs, and CI pipelines can do anything the dashboard does.

## Install

```
npm install -g @refgrow/cli
```

Or one-shot via npx, no install needed:

```
npx @refgrow/cli affiliates list
```

## Authenticate

```
refgrow login
```

You will be prompted for an API key. Generate one at [Settings → API Keys](/settings?tab=api-keys). The key is saved to `~/.refgrowrc` with mode 600.

Alternatives, evaluated in this order:

-   `--api-key <key>` flag — one-shot use, handy in CI where you keep the key in a secret store.
-   `REFGROW_API_KEY` environment variable.
-   `~/.refgrowrc` from `refgrow login`.

Verify the current setup:

```
refgrow whoami
```

## Commands

### Affiliates

```
refgrow affiliates list [--status active|inactive] [--limit 100] [--page 1] [--all]
refgrow affiliates get <email>
refgrow affiliates create <email> [--code XYZ] [--partner-slug s] \
  [--payment-method "USDT TRC-20"] [--payment-details "0xabc..."]
refgrow affiliates update <email> [--email new@x.com] [--code NEW] \
  [--status active|inactive] [--payout-method paypal|wise|manual] \
  [--paypal-email e] [--payment-method m] [--payment-details d]
refgrow affiliates delete <email> [--yes]
```

### Referrals

```
refgrow referrals list [--all]
refgrow referrals get <email>
refgrow referrals create <email> --affiliate-id 123 [--status active]
refgrow referrals update <email> [--email new@x.com] [--affiliate-id 456] [--status s]
refgrow referrals delete <email> [--yes]
```

### Conversions

```
refgrow conversions list [--type signup|purchase] [--all]
refgrow conversions get <id>
refgrow conversions create --email x@y.com --type purchase --value 100 \
  [--currency USD] [--affiliate-code CODE] [--reference ord_xyz]
refgrow conversions update <id> [--value 200] [--type signup|purchase] [--reference ref] \
  [--coupon-code CODE] [--paid] [--unpaid]
refgrow conversions delete <id> [--yes]
```

### Coupons

```
refgrow coupons list [--affiliate-id 123] [--coupon-code XYZ] [--all]
refgrow coupons get <id>
refgrow coupons create --affiliate-id 123 --code XYZ20
refgrow coupons update <id> [--code NEW] [--status active|inactive]
refgrow coupons delete <id> [--yes]
```

## Output formats

By default, list commands print a pretty aligned table and `get` prints key-value pairs. Override the format with:

-   `--json` — raw JSON, pipe-friendly with `jq`.
-   `--csv` — CSV with header row.
-   `--quiet` — drop headers and decorations, useful in shell loops.
-   `--no-color` — disable ANSI colors. Auto-disabled when stdout is not a TTY.

## Examples

Export every affiliate to a CSV file:

```
refgrow affiliates list --all --csv > affiliates.csv
```

Bulk-mark a list of conversion ids as paid:

```
cat conversion-ids.txt | while read id; do
  refgrow conversions update "$id" --paid
done
```

Record a manual conversion from a Stripe charge inside a webhook handler:

```
refgrow conversions create \
  --email "$EMAIL" \
  --type purchase \
  --value "$AMOUNT" \
  --currency USD \
  --reference "$STRIPE_CHARGE_ID"
```

Pipe into jq to find a referral's source affiliate:

```
refgrow referrals get user@example.com --json | jq '.affiliate_email'
```

## Exit codes

-   `0` — success
-   `1` — user error (no API key configured, invalid flag)
-   `2` — API error (4xx / 5xx response or network failure)

## Which surface should I use?

Surface

Best for

CLI (this page)

Shell scripts, cron jobs, CI, ad-hoc queries

[MCP server](/docs/mcp-server)

AI assistants (Claude Desktop, Cursor, etc.)

[REST API](/docs/api-reference)

Custom backend integrations

Zapier / Make / n8n

No-code automation flows

## Support

Bug reports and feature requests: [support@refgrow.com](mailto:support@refgrow.com), or the chat widget in the bottom-right corner of any page on refgrow.com.

---



<!-- ===== /docs/mcp-server ===== -->

# MCP Server

> Source: https://refgrow.com/docs/mcp-server

Connect Refgrow to AI assistants like Claude Desktop, Cursor, and Claude Code using the Model Context Protocol (MCP). Manage your affiliate program with natural language.

## What is MCP?

The [Model Context Protocol (MCP)](https://modelcontextprotocol.io) is an open standard that allows AI assistants to securely connect to external data sources and tools. With the Refgrow MCP server, you can manage your affiliate program directly from your AI assistant — view stats, manage affiliates, process payouts, and more using natural language.

## Prerequisites

-   A Refgrow account with at least one project ([sign up free](/register))
-   A Refgrow API key (generated from your project settings)
-   Node.js 18 or later installed on your machine
-   An MCP-compatible AI client (Claude Desktop, Cursor, or Claude Code)

## Installation

The Refgrow MCP server runs via `npx` — no global install required. It is automatically downloaded and executed when you configure your AI client.

```
npx @refgrow/mcp
```

**Note:** You do not need to run this command manually. The AI client will start the server automatically based on the configuration below.

## Getting your API Key

1.  Log in to your Refgrow dashboard
2.  Navigate to your project's **Settings** tab
3.  Scroll to the **API Keys** section
4.  Click **Generate API Key**
5.  Copy the key (it starts with `rgk_`). You will not be able to see it again.

**Important:** Store your API key securely. Do not commit it to version control or share it publicly.

## Setup for Claude Desktop

Add the following to your Claude Desktop MCP configuration file:

-   **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
-   **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`

```
{
  "mcpServers": {
    "refgrow": {
      "command": "npx",
      "args": ["-y", "@refgrow/mcp"],
      "env": {
        "REFGROW_API_KEY": "rgk_your_api_key_here"
      }
    }
  }
}
```

After saving the configuration, restart Claude Desktop. You should see the Refgrow tools available in the tools menu.

## Setup for Cursor

Add the MCP server to your Cursor configuration. Create or edit `.cursor/mcp.json` in your project root:

```
{
  "mcpServers": {
    "refgrow": {
      "command": "npx",
      "args": ["-y", "@refgrow/mcp"],
      "env": {
        "REFGROW_API_KEY": "rgk_your_api_key_here"
      }
    }
  }
}
```

Restart Cursor after saving. The Refgrow tools will appear in the AI assistant's available tools.

## Setup for Claude Code

Add the Refgrow MCP server to your project's `.mcp.json` file:

```
{
  "mcpServers": {
    "refgrow": {
      "command": "npx",
      "args": ["-y", "@refgrow/mcp"],
      "env": {
        "REFGROW_API_KEY": "rgk_your_api_key_here"
      }
    }
  }
}
```

## Available Tools

The MCP server exposes 18 tools organized in 4 categories. Your AI assistant can call any of these tools based on your natural-language requests.

### Affiliates

Tool

Description

`list_affiliates`

List all affiliates with stats (clicks, signups, purchases, earnings)

`get_affiliate_details`

Get details for a specific affiliate by email

`create_affiliate`

Create a new affiliate with optional custom referral code

`update_affiliate`

Update affiliate email, referral code, status, or partner slug

`delete_affiliate`

Remove an affiliate from the project

### Referrals

Tool

Description

`list_referrals`

List referred users, filterable by affiliate or status

`get_referral_details`

Get details for a specific referred user by email

`create_referral`

Manually create a referred user record

### Conversions

Tool

Description

`list_conversions`

List conversions with filters for type, affiliate, date range, paid status

`get_conversion`

Get a specific conversion by ID

`create_conversion`

Create a conversion (signup/purchase) with auto-commission calculation

`update_conversion`

Update conversion details or mark as paid

`delete_conversion`

Delete a conversion record

### Coupons

Tool

Description

`list_coupons`

List coupon codes with affiliate info

`get_coupon`

Get a specific coupon by ID

`create_coupon`

Create a coupon linked to an affiliate (with optional Stripe/LemonSqueezy IDs)

`update_coupon`

Update coupon details

`delete_coupon`

Delete a coupon (also removes from Stripe if linked)

## Environment Variables

Variable

Required

Description

`REFGROW_API_KEY`

Yes

Your Refgrow API key (starts with `rgk_`)

`REFGROW_API_URL`

No

Custom API base URL (defaults to `https://refgrow.com/api/v1`)

## Example Conversations

Here are some examples of what you can ask your AI assistant once the MCP server is connected:

### View program performance

You:

"Show me my affiliate program stats for this month. Who are my top performers?"

Assistant:

The assistant calls `get_project_stats` and `get_top_affiliates`, then summarizes your clicks, conversions, revenue, and top-performing affiliates.

### Manage affiliates

You:

"Add a new affiliate john@example.com with a 30% commission override and the coupon code JOHN30."

Assistant:

The assistant calls `create_affiliate` with the email, commission override, and coupon parameters.

### Process payouts

You:

"Show me all pending payouts and process them via PayPal."

Assistant:

The assistant calls `list_payouts` filtered by pending status, then calls `create_payout` for each affiliate after confirmation.

### Analyze conversions

You:

"List all conversions from last week and tell me the total revenue."

Assistant:

The assistant calls `list_conversions` with a date range filter and calculates the total.

## Troubleshooting

### "Server not found" or connection errors

-   Ensure Node.js 18+ is installed: `node --version`
-   Verify `npx` is available: `npx --version`
-   Check your internet connection — the package is downloaded on first run
-   Try running `npx @refgrow/mcp` manually to see any error output

### "Authentication failed" or 401 errors

-   Verify your API key starts with `rgk_`
-   Ensure the API key has not been revoked in your project settings
-   Check that the API key belongs to the correct project
-   Regenerate the API key if needed

### "Tool not available" in AI assistant

-   Restart your AI client after saving the configuration
-   Verify the JSON configuration is valid (no trailing commas, correct syntax)
-   Check the AI client's logs for MCP connection errors

### Rate limiting

-   The Refgrow API has a rate limit of 60 requests per minute per API key
-   If you hit rate limits, wait a minute before retrying
-   For high-volume usage, consider batching your requests

## Next Steps

-   [API Reference](/docs/api-reference) — full documentation of all API endpoints
-   [API Overview](/docs/api-overview) — understand authentication and rate limits
-   [Quickstart](/docs/quickstart) — set up your first affiliate program

## Need help?

If you have questions about the MCP server, contact us at [support@refgrow.com](mailto:support@refgrow.com).

---



<!-- ===== /docs/webhooks ===== -->

# Webhooks

> Source: https://refgrow.com/docs/webhooks

Get real-time notifications about events in your affiliate program.

## Overview

Refgrow's webhook system allows you to receive HTTP POST notifications about important events in your affiliate program. This enables you to integrate Refgrow with your internal systems for automated conversion processing, notifications, and analytics.

**Security:** All webhooks are signed with HMAC-SHA256 signatures for authenticity verification.

## Supported Events

Event

Description

When it triggers

`referral_signed_up`

New user signed up via referral link

When a user registers through a referral link

`referral_converted`

Referral converted to paying customer

When a referred user makes a purchase

`referral_canceled`

Conversion canceled or refunded

When a payment is refunded or canceled

`referral_updated`

Conversion updated or modified

When a conversion is created or updated via API

## Payout Preferences in Webhooks

Webhook payloads automatically include PayPal and Wise payout preferences when available. This allows finance systems to process payouts directly from webhook data without requiring additional API calls.

### Payout Preferences Structure

```
{
  "referrer": {
    "id": "456",
    "email": "affiliate@example.com",
    "payout_preferences": {
      "paypal_email": "affiliate@example.com",
      "wise_details": {
        "accountId": "wise_account_123",
        "email": "affiliate@example.com"
      }
    }
  }
}
```

**Benefits:**

-   No need to call `GET /api/v1/affiliates/:email` to enrich webhook data
-   Automatic payout processing directly from webhook payloads
-   Reduced API calls and faster integration setup
-   Payout preferences are retrieved from both `client_payment_settings` and custom attributes

**Note:** The `payout_preferences` field is only included when an affiliate has configured PayPal email or Wise payment details. If no payout preferences are configured, this field will be omitted from the payload.

## Setting up Webhooks

### 1\. Creating a Webhook

1.  Go to Project Settings → "Webhooks" tab
2.  Click "Add Webhook" button
3.  Enter your endpoint URL (e.g.: `https://yourapp.com/webhooks/refgrow`)
4.  Select the events you want to receive
5.  Optional: Generate a secret key for signature verification
6.  Save the settings

### 2\. Testing Your Webhook

After creating a webhook, you can test it:

1.  In the webhooks table, click the test button next to your webhook
2.  Select the event type to test
3.  Click "Send Test" - the system will send test data
4.  Check the delivery status and server response

**Important:** Make sure your endpoint responds with HTTP status 200-299 for successful delivery.

## Payload Format

All webhooks are sent as HTTP POST requests with JSON payload.

**Payout Preferences:** Webhook payloads automatically include PayPal and Wise payout preferences in the `referrer.payout_preferences` field when available. This eliminates the need for manual API enrichment steps.

### Request Headers

```
Content-Type: application/json
User-Agent: Refgrow-Webhooks/1.0
X-Refgrow-Event: referral_converted
X-Refgrow-Signature: sha256=abc123... (if signature is configured)
```

### referral\_signed\_up

```
{
  "event": "referral_signed_up",
  "timestamp": 1703123456,
  "project_id": "123",
  "referrer": {
    "id": "456",
    "email": "affiliate@example.com",
    "payout_preferences": {
      "paypal_email": "affiliate@example.com",
      "wise_details": {
        "accountId": "wise_account_123",
        "email": "affiliate@example.com"
      }
    }
  },
  "referred": {
    "id": "789",
    "email": "customer@example.com"
  },
  "data": {
    "referral_code": "REF123",
    "signup_date": "2024-01-15T10:00:00Z",
    "user_agent": "Mozilla/5.0...",
    "ip_address": "192.168.1.1"
  }
}
```

### referral\_converted

```
{
  "event": "referral_converted",
  "timestamp": 1703123456,
  "project_id": "123",
  "referrer": {
    "id": "456",
    "email": "affiliate@example.com",
    "payout_preferences": {
      "paypal_email": "affiliate@example.com",
      "wise_details": {
        "accountId": "wise_account_123",
        "email": "affiliate@example.com"
      }
    }
  },
  "referred": {
    "id": "789",
    "email": "customer@example.com"
  },
  "conversion": {
    "id": "conv_123",
    "amount": 99.99,
    "currency": "USD",
    "commission_amount": 19.99,
    "commission_type": "percentage",
    "commission_rate": 20,
    "payment_processor": "stripe",
    "product_id": "prod_abc123",
    "order_id": "order_456",
    "conversion_date": "2024-01-15T10:30:00Z"
  }
}
```

### referral\_canceled

```
{
  "event": "referral_canceled",
  "timestamp": 1703123456,
  "project_id": "123",
  "referrer": {
    "id": "456",
    "email": "affiliate@example.com",
    "payout_preferences": { ... }
  },
  "referred": {
    "id": "789",
    "email": "customer@example.com"
  },
  "conversion": {
    "id": "conv_123",
    "amount": 99.99,
    "commission_amount": 19.99,
    "refund_amount": 99.99,
    "reason": "Customer requested refund",
    "canceled_date": "2024-01-16T14:20:00Z"
  }
}
```

### referral\_updated

```
{
  "event": "referral_updated",
  "timestamp": 1703123456,
  "project_id": "123",
  "referrer": {
    "id": "456",
    "email": "affiliate@example.com",
    "payout_preferences": { ... }
  },
  "referred": {
    "id": "789",
    "email": "customer@example.com"
  },
  "conversion": {
    "id": "conv_123",
    "amount": 99.99,
    "amount_usd": 19.99,
    "commission_amount": 19.99,
    "base_value": 99.99,
    "conversion_date": "2024-01-15T10:30:00Z",
    "reference": "order_456"
  }
}
```

## Signature Verification

If you configured a secret key, each webhook will contain an HMAC-SHA256 signature in the `X-Refgrow-Signature` header.

### Signature Verification (PHP)

```
function verifySignature($payload, $signature, $secret) {
    $expectedSignature = 'sha256=' . hash_hmac('sha256', $payload, $secret);
    return hash_equals($expectedSignature, $signature);
}

// Usage
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_REFGROW_SIGNATURE'] ?? '';
$secret = 'your_webhook_secret';

if (!verifySignature($payload, $signature, $secret)) {
    http_response_code(401);
    exit('Invalid signature');
}
```

### Signature Verification (Node.js)

```
const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
    const expectedSignature = 'sha256=' + crypto
        .createHmac('sha256', secret)
        .update(payload, 'utf8')
        .digest('hex');

    return crypto.timingSafeEqual(
        Buffer.from(expectedSignature),
        Buffer.from(signature)
    );
}

// Express middleware
app.use('/webhooks/refgrow', express.raw({type: 'application/json'}), (req, res) => {
    const signature = req.headers['x-refgrow-signature'];
    const secret = process.env.REFGROW_WEBHOOK_SECRET;

    if (!verifySignature(req.body, signature, secret)) {
        return res.status(401).send('Invalid signature');
    }

    // Process webhook
    const event = JSON.parse(req.body);
    console.log('Received event:', event.event);

    res.status(200).send('OK');
});
```

## Implementation Examples

### Basic PHP Handler

```
<?php
header('Content-Type: application/json');

$payload = file_get_contents('php://input');
$event = json_decode($payload, true);

switch ($event['event']) {
    case 'referral_signed_up':
        $referrerEmail = $event['referrer']['email'];
        $referredEmail = $event['referred']['email'];
        sendEmailNotification($referrerEmail, "New referral: $referredEmail");
        break;

    case 'referral_converted':
        $commissionAmount = $event['conversion']['commission_amount'];
        $referrerEmail = $event['referrer']['email'];

        // Get payout preferences if available
        $payoutPreferences = $event['referrer']['payout_preferences'] ?? null;
        if ($payoutPreferences) {
            $paypalEmail = $payoutPreferences['paypal_email'] ?? null;
            $wiseDetails = $payoutPreferences['wise_details'] ?? null;

            if ($paypalEmail) {
                processPayPalPayout($referrerEmail, $commissionAmount, $paypalEmail);
            } elseif ($wiseDetails) {
                processWisePayout($referrerEmail, $commissionAmount, $wiseDetails);
            }
        }

        updatePartnerCommission($referrerEmail, $commissionAmount);
        break;

    case 'referral_canceled':
        $refundAmount = $event['conversion']['refund_amount'];
        $referrerEmail = $event['referrer']['email'];
        adjustPartnerCommission($referrerEmail, -$refundAmount);
        break;
}

http_response_code(200);
echo json_encode(['status' => 'success']);
?>
```

### Express.js Handler

```
const express = require('express');
const app = express();

app.post('/webhooks/refgrow', express.raw({type: 'application/json'}), async (req, res) => {
    try {
        const event = JSON.parse(req.body);

        switch (event.event) {
            case 'referral_signed_up':
                await handleReferralSignup(event);
                break;
            case 'referral_converted':
                await handleReferralConversion(event);
                break;
            case 'referral_updated':
                await handleReferralUpdate(event);
                break;
            case 'referral_canceled':
                await handleReferralCancellation(event);
                break;
            default:
                console.log('Unknown event type:', event.event);
        }

        res.status(200).json({ received: true });
    } catch (error) {
        console.error('Webhook error:', error);
        res.status(400).send('Webhook Error');
    }
});

async function handleReferralConversion(event) {
    const { referrer, conversion } = event;

    const payoutPreferences = referrer.payout_preferences;
    if (payoutPreferences) {
        const { paypal_email, wise_details } = payoutPreferences;
        if (paypal_email) {
            await processPayPalPayout(referrer.email, conversion.commission_amount, paypal_email);
        } else if (wise_details) {
            await processWisePayout(referrer.email, conversion.commission_amount, wise_details);
        }
    }

    await db.updatePartnerStats(referrer.id, {
        totalCommissions: conversion.commission_amount,
        lastConversionDate: new Date()
    });
}
```

## Monitoring and Logs

### Viewing Delivery Logs

In the webhook settings you can:

-   View delivery history for each webhook
-   See HTTP status codes and response times
-   Analyze delivery errors
-   Retry failed webhooks

### Successful Delivery

HTTP Status: 200-299  
Response Time: <5 seconds

### Delivery Error

HTTP Status: 400+ or timeout  
Automatic Retries: 3 attempts

## Best Practices

### Security

-   Always verify webhook signatures
-   Use HTTPS endpoints
-   Store secret keys securely
-   Restrict endpoint access

### Performance

-   Respond quickly (within 10 seconds)
-   Return HTTP 200 on success
-   Handle duplicate events
-   Use queues for heavy operations

## Troubleshooting

### Webhook not being delivered

1.  Check that the URL is publicly accessible
2.  Ensure your server responds with HTTP 200
3.  Check delivery logs in the admin panel
4.  Use the test webhook for diagnostics
5.  Check firewall and security settings

### Signature verification error

1.  Make sure you are using the correct secret key
2.  Verify you are reading the raw request body
3.  Compare your signature algorithm with examples
4.  Check encoding (should be UTF-8)

### Duplicate events

Webhooks may be delivered multiple times in case of errors. Implement idempotency:

-   Use event IDs for deduplication
-   Store processed events in database
-   Check for existing records before processing

## Testing Endpoint

You can use a test endpoint to verify your webhook implementation:

```
curl -X POST https://yourdomain.com/webhook/test \
  -H "Content-Type: application/json" \
  -H "X-Refgrow-Signature: sha256=test_signature" \
  -d '{
    "event": "referral_converted",
    "timestamp": 1703123456,
    "project_id": "test",
    "referrer": {"id": "123", "email": "test@example.com"},
    "referred": {"id": "456", "email": "customer@example.com"},
    "conversion": {"amount": 99.99, "commission_amount": 19.99}
  }'
```

## API Reference

### Test Webhook Endpoint

**POST** `/api/project/{projectId}/webhooks/{webhookId}/test`

Sends a test webhook with generated test data.

#### Parameters:

```
{
  "eventType": "referral_converted"
}
```

#### Response:

```
{
  "success": true,
  "status": 200,
  "response": "OK"
}
```

**Need Help?** If you have questions about setting up webhooks, contact [support](mailto:support@refgrow.com) or check our other guides.

---



<!-- ===== /docs/security ===== -->

# Security

> Source: https://refgrow.com/docs/security

Protecting your affiliate program and data.

## Overview

Security is paramount when managing an affiliate program. This guide outlines the security measures built into Refgrow and best practices to protect your account, affiliate data, and integration points.

## Account Security

### Password Requirements

Refgrow enforces strong password policies to protect your account:

-   Minimum 8 characters in length
-   Must contain at least one uppercase letter
-   Must contain at least one lowercase letter
-   Must include at least one number
-   Must include at least one special character

We recommend using a password manager to generate and store unique, complex passwords.

### Two-Factor Authentication (2FA)

Enabling two-factor authentication adds an essential layer of security to your account:

1.  Go to your account settings
2.  Navigate to the "Security" tab
3.  Click "Enable 2FA"
4.  Scan the QR code with an authenticator app
5.  Enter the verification code to confirm setup
6.  Save your backup codes in a secure location

With 2FA enabled, you'll need both your password and a time-based code from your authenticator app to log in.

### Session Management

Refgrow includes several features to manage active sessions:

-   **Automatic Timeouts:** Sessions automatically expire after 30 minutes of inactivity
-   **View Active Sessions:** See all devices currently logged into your account
-   **Remote Logout:** Force logout of any suspicious sessions

To view and manage your sessions:

1.  Go to your account settings
2.  Navigate to the "Security" tab
3.  Review the "Active Sessions" section

## Data Protection

### Encryption

Refgrow implements multiple layers of encryption to protect your data:

-   **Data in Transit:** All communications between your browser and Refgrow servers use TLS 1.2+ encryption
-   **Data at Rest:** Sensitive information stored in our databases is encrypted using industry-standard AES-256 encryption
-   **Sensitive Data:** API keys, payment information, and authentication tokens are additionally protected with strong hashing algorithms

### Data Retention

Refgrow follows these data retention practices:

-   Account data is retained as long as your account is active
-   Backup data is retained for 30 days
-   Access logs are kept for 90 days
-   Deleted account data is fully removed from our systems within 30 days

You can request data export or deletion at any time through your account settings.

### Privacy Controls

Control what data you collect from affiliates:

1.  Go to your program settings
2.  Navigate to the "Privacy" tab
3.  Configure the following options:
    -   Required affiliate profile fields
    -   Optional affiliate information
    -   Data visibility settings for your affiliates
4.  Save your settings

These settings help ensure you collect only the data necessary for your program and comply with privacy regulations.

## API Security

### API Key Management

Secure handling of API keys is essential:

-   **Key Generation:** API keys are randomly generated with high entropy
-   **Key Storage:** Never store API keys in client-side code or public repositories
-   **Rotation:** Regularly rotate API keys, especially if you suspect they've been compromised

To generate or rotate your API keys:

1.  Go to your program settings
2.  Navigate to the "API" tab
3.  Click "Generate New Key" or "Rotate Key"
4.  Confirm the action (note that existing keys will be invalidated)
5.  Update your integrations with the new key

### Rate Limiting

Refgrow implements rate limiting on API endpoints to prevent abuse:

-   Standard plan: 60 requests per minute
-   Pro plan: 300 requests per minute
-   Business plan: Customizable limits

If you exceed these limits, requests will return a 429 status code until the rate limit window resets.

### IP Restrictions

Restrict API access to specific IP addresses:

1.  Go to your program settings
2.  Navigate to the "API" tab
3.  Find the "IP Restrictions" section
4.  Add approved IP addresses or CIDR ranges
5.  Save your settings

Once IP restrictions are enabled, API requests from non-approved IP addresses will be rejected.

**Note:** IP restrictions are available for users on Pro and Business plans.

## Fraud Prevention

### Affiliate Verification

Verify affiliate identities to prevent fraud:

1.  Go to your program settings
2.  Navigate to the "Affiliates" tab
3.  Enable these verification options:
    -   Email verification requirement
    -   Manual approval for new affiliates
    -   Domain restrictions for affiliate signups
4.  Save your settings

### Commission Approval

Implement a commission approval workflow to prevent fraudulent commissions:

1.  Go to program settings
2.  Navigate to the "Commissions" tab
3.  Enable "Manual Commission Approval"
4.  Configure the approval rules
5.  Save your settings

With this setting enabled, commissions will be held in a pending state until manually approved.

### Click Fraud Detection

Refgrow includes several mechanisms to detect fraudulent clicks:

-   **IP Tracking:** Identifies multiple clicks from the same IP address
-   **Bot Detection:** Filters out non-human traffic
-   **Conversion Validation:** Verifies legitimate conversions
-   **Anomaly Detection:** Flags unusual patterns in click activity

Configure fraud detection sensitivity:

1.  Go to program settings
2.  Navigate to the "Tracking" tab
3.  Adjust fraud detection settings
4.  Save your changes

## Compliance

### GDPR Compliance

Refgrow includes features to help with GDPR compliance:

-   Data processing agreements available for Business customers
-   Tools for data subject access requests
-   Right to be forgotten functionality
-   Configurable cookie consent options
-   Data minimization controls

For specific GDPR guidance, please consult with a legal professional familiar with your business requirements.

### PCI Compliance

For payment-related functionality, Refgrow:

-   Never stores full credit card information
-   Uses PCI-compliant payment processors for all transactions
-   Ensures secure transmission of payment data
-   Maintains separation between affiliate tracking data and payment information

## Security Best Practices

### Enable 2FA for All Admin Accounts

Require two-factor authentication for anyone with administrative access to your Refgrow account to prevent unauthorized account access.

### Regularly Review Access

Periodically audit user access to your affiliate program and remove access for team members who no longer need it.

### Secure API Integration

Keep API keys secure by storing them in environment variables or secure key vaults, never in source code or client-side applications.

### Monitor for Unusual Activity

Regularly check your affiliate dashboard for unusual patterns in signups, clicks, or conversions that could indicate fraudulent activity.

## Security Updates and Notifications

Refgrow regularly updates its security measures and will notify you of:

-   Critical security patches
-   Updates to security features
-   Changes to our security policies
-   Potential security concerns relevant to your account

Ensure your notification settings are configured to receive these important updates:

1.  Go to your account settings
2.  Navigate to the "Notifications" tab
3.  Ensure "Security Alerts" are enabled
4.  Verify your contact email is current

## Reporting Security Issues

If you discover a security vulnerability or have concerns about your account security:

1.  Email [security@refgrow.com](mailto:security@refgrow.com) with details
2.  Do not disclose the issue publicly until it has been addressed
3.  Include as much information as possible about the potential vulnerability

Our security team will acknowledge your report within 24 hours and work to address any valid concerns promptly.

## Next Steps

-   Review your [authentication settings](/docs/authentication)
-   Learn about [API security](/docs/api-overview)
-   Understand how to [securely manage affiliates](/docs/affiliates)

---



<!-- ===== /docs/troubleshooting ===== -->

# Troubleshooting

> Source: https://refgrow.com/docs/troubleshooting

Solving common issues with your Refgrow implementation.

## Overview

This guide addresses common issues you might encounter when using Refgrow and provides step-by-step solutions. If you don't find an answer to your specific problem, please contact our support team.

## Dashboard Issues

### Dashboard Not Loading

**Symptoms:** Blank screen, loading spinner that never completes, or JavaScript errors.

**Possible Causes & Solutions:**

1.  **JavaScript Errors:**
    -   Check your browser's console for error messages
    -   Ensure you've properly included the Refgrow script in your HTML
    -   Verify that you haven't added custom JavaScript that conflicts with the dashboard
2.  **Content Security Policy (CSP) Blocking:**
    -   If you have a strict CSP, add the following domains to your `script-src` directive:
        -   `https://scripts.refgrowcdn.com` - Required for the tracking script (`latest.js`)
        -   `https://*.refgrow.com` or `https://refgrow.com` - Required for the affiliate dashboard widget (`embed.js`)
    -   Also add `https://*.refgrow.com` or `https://refgrow.com` to your `connect-src` directive for API calls
    -   **Example CSP header:**
        
        ```
        Content-Security-Policy: script-src 'self' 'unsafe-eval' 'unsafe-inline' https://scripts.refgrowcdn.com https://*.refgrow.com https://refgrow.com; connect-src 'self' https://*.refgrow.com https://refgrow.com;
        ```
        
3.  **Network Issues:**
    -   Verify your internet connection
    -   Check if your firewall or proxy is blocking connections to Refgrow domains
4.  **Incorrect Installation:**
    -   Review the [installation guide](/docs/installation) to ensure you've correctly implemented the dashboard
    -   Verify your program ID is correct in the dashboard element attributes

### Dashboard Styling Issues

**Symptoms:** Dashboard appears unstyled, misaligned elements, or conflicting styles.

**Possible Causes & Solutions:**

1.  **CSS Conflicts:**
    -   Check if your website's CSS is overriding Refgrow's styles
    -   Try adding the dashboard in an isolated container with minimal styling
2.  **Missing CSS Resources:**
    -   Verify that your CSP doesn't block stylesheets from Refgrow domains
3.  **Responsive Layout Issues:**
    -   Ensure the container for the dashboard is wide enough
    -   Check that you haven't applied CSS that affects the dashboard's responsive behavior

### Authentication Problems

**Symptoms:** Unable to log in, constant redirects, or "unauthorized" errors.

**Possible Causes & Solutions:**

1.  **JWT Token Issues:**
    -   Verify your JWT is properly signed with the correct secret
    -   Check that the token hasn't expired
    -   Ensure all required claims are included in the token
2.  **Cookie Issues:**
    -   Ensure cookies are enabled in the user's browser
    -   Check for any third-party cookie blocking that might affect authentication
3.  **Cross-Origin Problems:**
    -   If you're using a custom authentication endpoint, verify your CORS headers are properly set

## Tracking Issues

### Referrals Not Being Tracked

1.  Verify the tracking script is on all pages with links
2.  Check your browser console for any error messages
3.  Ensure third-party cookies are not blocked
4.  Test with a known referral link format (e.g., yoursite.com?ref=CODE)
5.  Verify the referral parameter name matches your project settings

### Conversions Not Attributing to Affiliates

#### For Stripe/LemonSqueezy:

-   Ensure webhooks are properly configured
-   Verify you're passing the referral code to the checkout metadata
-   Check webhook logs in your payment provider dashboard

#### For Manual Tracking:

-   Ensure you're providing a valid email address in the tracking call
-   Verify the cookie exists when making the conversion call
-   Check your browser console for any API errors

### Affiliate Dashboard Issues

-   Verify the embed script is correctly installed
-   Check if there are any JavaScript errors in the browser console
-   Ensure your container element has sufficient width and height
-   Verify your project's customization settings

### Inaccurate Reporting

**Symptoms:** Discrepancies between your internal data and Refgrow's reports.

**Possible Causes & Solutions:**

1.  **Attribution Window Settings:**
    -   Check your attribution window settings in program configuration
    -   Understand how the attribution model works (first-click, last-click, etc.)
2.  **Duplicate Transactions:**
    -   Ensure your conversion tracking isn't firing multiple times for the same transaction
    -   Implement deduplication logic if necessary
3.  **Data Processing Delay:**
    -   Allow 24 hours for all data to be processed and aggregated in reports
4.  **Timezone Differences:**
    -   Verify your program's timezone setting matches your expected reporting timezone

## Integration Issues

### Stripe Integration Failures

**Symptoms:** Stripe payments not triggering commissions, webhook errors.

**Possible Causes & Solutions:**

1.  **Webhook Configuration:**
    -   Verify your Stripe webhook is set up correctly with the right events
    -   Check that the webhook secret is properly configured in Refgrow
2.  **API Key Issues:**
    -   Ensure you're using a live API key in production (not test mode)
    -   Verify the API key has sufficient permissions for webhook operations
3.  **Product Mapping:**
    -   Check that your Stripe products are properly mapped to commission structures in Refgrow
4.  **Webhook Deliverability:**
    -   Check Stripe dashboard for failed webhook attempts
    -   Ensure your firewall isn't blocking incoming webhook requests

For more details, see the [Stripe Integration](/docs/stripe) documentation.

### LemonSqueezy Integration Issues

**Symptoms:** LemonSqueezy purchases not registering as conversions.

**Possible Causes & Solutions:**

1.  **API Connection:**
    -   Verify your LemonSqueezy API key is correct and active
    -   Check that you've enabled the necessary webhook events
2.  **Webhook URL:**
    -   Ensure the webhook URL in LemonSqueezy points to the correct Refgrow endpoint
3.  **Event Filtering:**
    -   Check that you've selected the correct events to trigger (order\_created, etc.)

### API Integration Problems

**Symptoms:** API requests failing, returning errors, or timing out.

**Possible Causes & Solutions:**

1.  **Authentication Issues:**
    -   Verify your API key is valid and included in the request headers
    -   Check for proper formatting of the Authorization header
2.  **Rate Limiting:**
    -   Check if you're exceeding the rate limits for your plan
    -   Implement retry logic with exponential backoff for 429 responses
3.  **Invalid Parameters:**
    -   Review the API documentation to ensure you're sending all required parameters
    -   Check parameter formats (dates, IDs, etc.)
4.  **IP Restrictions:**
    -   If you've enabled IP restrictions, verify your requests are coming from approved IPs

For more information, see the [API Endpoints](/docs/endpoints) documentation.

## Account & Billing Issues

### Account Access Problems

**Symptoms:** Unable to log in, forgotten password, 2FA issues.

**Possible Causes & Solutions:**

1.  **Forgotten Password:**
    -   Use the "Forgot Password" link on the login page
    -   Check your spam folder for reset emails
2.  **2FA Problems:**
    -   Use recovery codes if you've lost access to your authenticator app
    -   Ensure your device's time is properly synchronized
3.  **Account Suspension:**
    -   Check if your account has been suspended due to billing issues or terms violations
    -   Contact support if you believe this is in error

### Billing and Subscription Issues

**Symptoms:** Payment failures, unexpected charges, plan limitations.

**Possible Causes & Solutions:**

1.  **Payment Method Issues:**
    -   Verify your credit card information is current and valid
    -   Check if your card has expired or been replaced
2.  **Subscription Status:**
    -   Confirm your subscription is active in the billing section
    -   Check for any failed payment notices
3.  **Plan Limitations:**
    -   Verify you haven't exceeded your plan's limits for affiliates, programs, or API calls
    -   Consider upgrading if you're consistently hitting limits

## Performance Optimization

### Slow Dashboard Loading

**Symptoms:** Dashboard takes a long time to load or interact with.

**Possible Causes & Solutions:**

1.  **Large Data Volume:**
    -   If you have thousands of affiliates or transactions, consider narrowing date ranges
    -   Use filters to focus on specific segments
2.  **Script Loading Order:**
    -   Ensure the Refgrow script is loaded efficiently (consider async or defer attributes)
    -   Place the script near the bottom of your page if possible
3.  **Browser Performance:**
    -   Clear browser cache and cookies
    -   Try a different browser to isolate performance issues

### Optimizing Tracking Script Performance

**Symptoms:** Tracking script slowing down page load or affecting user experience.

**Possible Causes & Solutions:**

1.  **Script Loading:**
    -   Use the async attribute to load the tracking script without blocking page rendering
    -   Consider implementing the script with a tag manager for better control
2.  **Conditional Loading:**
    -   Only load the full tracking capabilities when a referral parameter is present
    -   Use a lightweight script for non-referred visitors
3.  **Caching:**
    -   Ensure your CDN or hosting provider properly caches the tracking script

## Common Error Messages

### API Error: "Invalid Authentication"

**Cause:** The API key provided is invalid or expired.

**Solution:**

1.  Generate a new API key in your program settings
2.  Ensure you're prefixing the key with "Bearer" in the Authorization header
3.  Check for any whitespace or formatting issues in the key

### Dashboard Error: "Program ID Not Found"

**Cause:** The program ID provided in the dashboard configuration doesn't exist or is inaccessible.

**Solution:**

1.  Verify the program ID in your dashboard HTML matches what's in your Refgrow account
2.  Check that the program is active and not archived
3.  Ensure your account has access to this program

### Webhook Error: "Invalid Signature"

**Cause:** The webhook signature verification failed, often due to mismatched secrets.

**Solution:**

1.  Verify the webhook secret in your integration settings matches what's configured in the service (Stripe, etc.)
2.  Check that you haven't regenerated the webhook secret without updating the external service
3.  Ensure the webhook payload isn't being modified in transit (by proxies, etc.)

## Getting Help

If you've tried the troubleshooting steps above and still can't resolve your issue, there are several ways to get additional help:

### Support Ticket

Submit a support ticket through your Refgrow dashboard:

1.  Log in to your account
2.  Click on the Help icon in the bottom right
3.  Choose "Submit a Ticket"
4.  Provide detailed information about your issue

Our support team typically responds within 24 hours on business days.

### Email Support

Send an email directly to our support team:

[support@refgrow.com](mailto:support@refgrow.com)

Include the following information:

-   Your account email address
-   Program ID (if applicable)
-   Detailed description of the issue
-   Screenshots of any error messages
-   Steps you've already taken to troubleshoot

For urgent issues affecting your production environment, Pro and Business customers can access priority support with faster response times.

## Next Steps

-   Review your [tracking implementation](/docs/tracking)
-   Check the integration guides for platform-specific issues ([Stripe](/docs/stripe), [LemonSqueezy](/docs/lemonsqueezy), [Paddle](/docs/paddle))
-   Learn about [security best practices](/docs/security) to avoid common problems

---



<!-- ===== /docs/widget-troubleshooting ===== -->

# Widget Troubleshooting

> Source: https://refgrow.com/docs/widget-troubleshooting

Fix common issues with the Refgrow affiliate widget, including disappearing widgets and visibility problems.

## Common Problem: Widget Disappears on Tab Switch

Some users report that the Refgrow widget disappears or becomes empty when:

-   Switching between browser tabs
-   Returning to the page after being away
-   Navigating in Single Page Applications (SPAs)
-   Losing window focus

## Automatic Recovery Solution

Use our widget script that includes automatic recovery functionality:

```
<div id="refgrow" data-project-id="YOUR_PROJECT_ID"></div>
<script src="https://scripts.refgrowcdn.com/page.js"></script>
```

### Automatic Features:

-   Automatic recovery when switching browser tabs
-   Periodic health checks every 10 seconds
-   Page visibility change detection
-   Window focus/blur event handling
-   Manual recovery methods for custom implementations

## Manual Recovery Methods

If you need to manually restore the widget or implement custom recovery logic:

### JavaScript

```
// Check and restore the widget
window.Refgrow.restore();

// Force re-initialization
window.Refgrow.forceInit();

// Complete reset and re-initialization
window.Refgrow.reset();
window.Refgrow.init();
```

### TypeScript

```
// TypeScript interface for Refgrow methods
interface RefgrowWidget {
  restore(): void;
  forceInit(): void;
  reset(): void;
  init(): void;
}

// Usage
declare global {
  interface Window {
    Refgrow: RefgrowWidget;
  }
}

// Check and restore the widget
window.Refgrow.restore();

// Force re-initialization
window.Refgrow.forceInit();
```

## SPA Framework Integration

For Single Page Applications, you may need additional integration to handle route changes and component lifecycles:

### React

```
import { useEffect } from 'react';

function RefgrowWidget({ projectId, userEmail }) {
  useEffect(() => {
    // Initialize widget when component mounts
    const element = document.getElementById('refgrow');
    if (element && window.Refgrow) {
      window.Refgrow.forceInit();
    }
  }, []);

  useEffect(() => {
    // Check widget state on route changes
    const timer = setTimeout(() => {
      if (window.Refgrow) {
        window.Refgrow.restore();
      }
    }, 500);

    return () => clearTimeout(timer);
  });

  // Handle page visibility changes
  useEffect(() => {
    const handleVisibilityChange = () => {
      if (!document.hidden && window.Refgrow) {
        setTimeout(() => {
          const element = document.getElementById('refgrow');
          if (element && element.innerHTML.trim() === '') {
            window.Refgrow.restore();
          }
        }, 1000);
      }
    };

    document.addEventListener('visibilitychange', handleVisibilityChange);

    return () => {
      document.removeEventListener('visibilitychange', handleVisibilityChange);
    };
  }, []);

  return (
    <div
      id="refgrow"
      data-project-id={projectId}
      data-project-email={userEmail}
    ></div>
  );
}
```

### Vue.js

```
<template>
  <div
    id="refgrow"
    :data-project-id="projectId"
    :data-project-email="userEmail"
  ></div>
</template>

<script>
export default {
  name: 'RefgrowWidget',
  props: {
    projectId: {
      type: String,
      required: true
    },
    userEmail: {
      type: String,
      default: null
    }
  },
  mounted() {
    this.initWidget();
    this.setupVisibilityListener();
  },
  activated() {
    // For keep-alive components
    this.$nextTick(() => {
      this.restoreWidget();
    });
  },
  beforeUnmount() {
    this.cleanup();
  },
  methods: {
    initWidget() {
      if (window.Refgrow) {
        window.Refgrow.forceInit();
      }
    },
    restoreWidget() {
      if (window.Refgrow) {
        window.Refgrow.restore();
      }
    },
    setupVisibilityListener() {
      this.handleVisibilityChange = () => {
        if (!document.hidden && window.Refgrow) {
          setTimeout(() => {
            const element = document.getElementById('refgrow');
            if (element && element.innerHTML.trim() === '') {
              window.Refgrow.restore();
            }
          }, 1000);
        }
      };

      document.addEventListener('visibilitychange', this.handleVisibilityChange);
    },
    cleanup() {
      if (this.handleVisibilityChange) {
        document.removeEventListener('visibilitychange', this.handleVisibilityChange);
      }

      if (window.Refgrow) {
        window.Refgrow.reset();
      }
    }
  }
}
</script>
```

### Angular

```
import { Component, Input, OnInit, OnDestroy } from '@angular/core';

declare global {
  interface Window {
    Refgrow: any;
  }
}

@Component({
  selector: 'app-refgrow-widget',
  template: `
    <div
      id="refgrow"
      [attr.data-project-id]="projectId"
      [attr.data-project-email]="userEmail"
    ></div>
  `
})
export class RefgrowWidgetComponent implements OnInit, OnDestroy {
  @Input() projectId!: string;
  @Input() userEmail?: string;

  private visibilityChangeHandler?: () => void;

  ngOnInit() {
    this.initWidget();
    this.setupVisibilityListener();
  }

  ngOnDestroy() {
    this.cleanup();
  }

  private initWidget() {
    setTimeout(() => {
      if (window.Refgrow) {
        window.Refgrow.forceInit();
      }
    }, 100);
  }

  private restoreWidget() {
    if (window.Refgrow) {
      window.Refgrow.restore();
    }
  }

  private setupVisibilityListener() {
    this.visibilityChangeHandler = () => {
      if (!document.hidden && window.Refgrow) {
        setTimeout(() => {
          const element = document.getElementById('refgrow');
          if (element && element.innerHTML.trim() === '') {
            window.Refgrow.restore();
          }
        }, 1000);
      }
    };

    document.addEventListener('visibilitychange', this.visibilityChangeHandler);
  }

  private cleanup() {
    if (this.visibilityChangeHandler) {
      document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
    }

    if (window.Refgrow) {
      window.Refgrow.reset();
    }
  }
}
```

## Custom Visibility Monitoring

For advanced use cases, you can implement your own visibility monitoring:

```
// Enhanced visibility monitoring
document.addEventListener('visibilitychange', function() {
  if (!document.hidden) {
    // Page became visible
    setTimeout(function() {
      const element = document.getElementById('refgrow');
      if (element && element.innerHTML.trim() === '' && window.Refgrow) {
        console.log('Restoring empty Refgrow widget');
        window.Refgrow.restore();
      }
    }, 1000);
  }
});

// Periodic health check
function healthCheck() {
  const element = document.getElementById('refgrow');
  const isEmpty = !element || element.innerHTML.trim() === '';

  if (isEmpty && window.Refgrow) {
    console.warn('Refgrow widget appears empty, attempting restore...');
    window.Refgrow.restore();
  }

  return !isEmpty;
}

// Run health check every 30 seconds
setInterval(healthCheck, 30000);
```

## Debugging Widget Issues

Use these debugging techniques to diagnose widget problems:

```
// Debug widget status
function checkRefgrowStatus() {
  const element = document.getElementById('refgrow');
  console.log('Refgrow element:', element);
  console.log('Element content:', element ? element.innerHTML : 'Not found');
  console.log('Refgrow object:', window.Refgrow);
  console.log('ReferralProgram object:', window.ReferralProgram);
}

// Run debug check
checkRefgrowStatus();

// Monitor for errors
window.addEventListener('error', function(e) {
  if (e.message && e.message.includes('Refgrow')) {
    console.error('Refgrow widget error:', e);
    // Send error to your monitoring service
  }
});
```

## Platform-Specific Solutions

### WordPress

Add this to your theme's `functions.php`:

```
function refgrow_widget_monitor() {
    ?>
    <script>
    jQuery(document).ready(function($) {
        setInterval(function() {
            if (window.Refgrow && $('#refgrow').is(':empty')) {
                window.Refgrow.restore();
            }
        }, 10000);
    });
    </script>
    <?php
}
add_action('wp_footer', 'refgrow_widget_monitor');
```

### Shopify

Add to your theme's `theme.liquid`:

```
{% comment %} Refgrow Widget Monitor {% endcomment %}
<script>
document.addEventListener('DOMContentLoaded', function() {
    // Monitor for theme changes
    document.addEventListener('shopify:section:load', function() {
        setTimeout(function() {
            if (window.Refgrow) {
                window.Refgrow.restore();
            }
        }, 1000);
    });
});
</script>
```

## Performance Optimization

**Important:** While monitoring helps ensure widget availability, avoid excessive polling that could impact page performance.

### Best Practices:

-   Use the built-in recovery mechanisms first
-   Implement debounced visibility checks
-   Limit health check frequency to 10-30 seconds
-   Use Intersection Observer for performance-sensitive applications
-   Clean up event listeners when components unmount

```
// Debounced restore function
function debounce(func, wait) {
  let timeout;
  return function executedFunction(...args) {
    const later = () => {
      clearTimeout(timeout);
      func(...args);
    };
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
  };
}

// Debounced widget restore
const debouncedRestore = debounce(() => {
  if (window.Refgrow) {
    window.Refgrow.restore();
  }
}, 1000);

// Use Intersection Observer for better performance
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting && entry.target.innerHTML.trim() === '') {
      debouncedRestore();
    }
  });
});

const refgrowElement = document.getElementById('refgrow');
if (refgrowElement) {
  observer.observe(refgrowElement);
}
```

## Still Having Issues?

If the widget is still not working properly after trying these solutions:

1.  **Check browser console** for JavaScript errors
2.  **Verify** you are using the latest version of page.js
3.  **Test** manual restoration with `window.Refgrow.restore()`
4.  **Check** for conflicts with other scripts or frameworks
5.  **Contact support** with console logs and detailed reproduction steps

**Need help?** Contact us at [support@refgrow.com](mailto:support@refgrow.com) with:

-   Browser console logs
-   Steps to reproduce the issue
-   Your website URL (if possible)
-   Framework/platform you are using

---
