Documentation

Polar Provider

Learn how to integrate Polar as your payment provider.

Polar is an open-source payment platform built for developers. It offers transparent pricing, developer-friendly APIs, and focuses on subscriptions and digital products.

Note

Seat-based billing is not currently implemented in the Polar provider.

Setup

1. Create a Polar Account

  1. Sign up at https://polar.sh
  2. Complete your account setup
  3. Navigate to the Dashboard

2. Choose Your Environment

Polar provides two environments:

  • Sandbox: For development and testing
  • Production: For live payments

The environment is automatically selected based on NODE_ENV:

  • Development: Uses sandbox mode
  • Production: Uses production mode

3. Get Your Access Token

  1. Go to SettingsAPI in your Polar dashboard
  2. Create a new access token:
    • Give it a name (e.g., "Production API Token")
    • Select appropriate permissions
    • For sandbox: Create token in sandbox mode
    • For production: Create token in production mode
  3. Copy the access token

Where to find Access Token:

  • Dashboard → Settings → API → Create Access Token
  • Keep sandbox and production tokens separate

4. Create Products

  1. Go to Products in your dashboard
  2. Click Create Product
  3. Configure your product:
    • Product name (e.g., "Pro Plan")
    • Description
    • Pricing:
      • For subscriptions: Set recurring interval (monthly/yearly)
      • For one-time: Set as one-time payment
    • Price amount and currency
  4. Publish the product
  5. Copy the Product ID (UUID format)

Example Products:

  • Pro Monthly: $19/month → Product ID: prod_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  • Pro Yearly: $190/year → Product ID: prod_yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
  • Lifetime: $199 one-time → Product ID: prod_zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz

5. Set Up Webhooks

Webhooks notify your application about payment events.

For Production:

  1. Go to your Organization Settings in Polar dashboard
  2. Navigate to the Webhooks section
  3. Click Add Endpoint
  4. Enter the endpoint URL: https://yourdomain.com/api/webhooks/polar
  5. Set a webhook secret:
    • You can generate a random secret or set your own
    • This secret is used to cryptographically sign webhook requests for security
    • Save this secret securely - you'll need it for verification
  6. Choose delivery format: Raw JSON (default, recommended)
  7. Select events to listen to based on your payment types:

For One-Time Payments:

  • checkout.updated (required) - Handles checkout completion and payment confirmation

For Subscriptions:

  • subscription.created (required) - Creates subscription record when first purchased
  • subscription.updated (required) - Updates subscription status/plan changes
  • subscription.canceled (required) - Handles cancellation requests
  • subscription.revoked (optional) - Handles immediate subscription termination

Additional Optional Events:

  • order.created - Order creation notifications
  • order.paid - Payment confirmation (redundant if using checkout.updated)
  • order.refunded - Refund notifications
  • subscription.active - Subscription activation confirmation
  • customer.created - New customer tracking
  • checkout.created - Checkout session initiation

For Local Development (Sandbox):

Use ngrok for local testing (recommended by Polar):

# Start ngrok
ngrok http 3000

# Use the ngrok URL in webhook settings
https://your-ngrok-url.ngrok.io/api/webhooks/polar

6. Configure Environment Variables

Add these variables to your .env.local file:

.env.local
# Polar Access Token
POLAR_ACCESS_TOKEN=polar_at_xxxxxxxxxxxxx

# Polar Webhook Secret
POLAR_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxx

# Your Price IDs (use Polar Product IDs in UUID format)
NEXT_PUBLIC_PRICE_ID_LIFETIME=prod_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
NEXT_PUBLIC_PRICE_ID_PRO_MONTHLY=prod_yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
NEXT_PUBLIC_PRICE_ID_PRO_YEARLY=prod_zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz

Where to find these:

  • Access Token: Dashboard → Settings → API → Create/copy token
  • Webhook Secret: The secret you generated or set when creating the webhook endpoint (from step 5)
  • Price IDs: Dashboard → Products → Copy Product UUID (use as Price ID)

Important:

  • Use separate access tokens for sandbox and production environments
  • Keep your webhook secret secure - it's used to verify webhook authenticity
  • Polar follows the Standard Webhooks specification for secure webhook delivery

Configuration

Set Polar as your payment provider in config/index.ts:

config/index.ts
export const config = {
  payments: {
    provider: "polar",
    plans: {
      lifetime: {
        recommended: true,
        prices: [
          {
            type: "one-time",
            productId: process.env.NEXT_PUBLIC_PRICE_ID_LIFETIME as string,
            amount: 199,
            currency: "USD",
          },
        ],
      },
      pro: {
        recommended: false,
        prices: [
          {
            type: "subscription",
            productId: process.env.NEXT_PUBLIC_PRICE_ID_PRO_MONTHLY as string,
            amount: 19,
            currency: "USD",
            interval: "month",
          },
          {
            type: "subscription",
            productId: process.env.NEXT_PUBLIC_PRICE_ID_PRO_YEARLY as string,
            amount: 190,
            currency: "USD",
            interval: "year",
          },
        ],
      },
    },
  },
};

Note: Use Product IDs in UUID format, not numeric IDs.

Limitations

Seat-Based Billing Not Implemented

The current Polar provider implementation does not support seat-based billing. The setSubscriptionSeats function throws an error:

export const setSubscriptionSeats: SetSubscriptionSeats = async () => {
  throw new Error("Not implemented");
};

Workaround:

  • Use separate products for different team sizes
  • Or implement custom seat management logic
  • Or consider using a different provider for seat-based billing