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
Setup
1. Create a Polar Account
- Sign up at https://polar.sh
- Complete your account setup
- 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
- Go to Settings → API in your Polar dashboard
- 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
- Copy the access token
Where to find Access Token:
- Dashboard → Settings → API → Create Access Token
- Keep sandbox and production tokens separate
4. Create Products
- Go to Products in your dashboard
- Click Create Product
- 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
- Publish the product
- 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:
- Go to your Organization Settings in Polar dashboard
- Navigate to the Webhooks section
- Click Add Endpoint
- Enter the endpoint URL:
https://yourdomain.com/api/webhooks/polar - 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
- Choose delivery format: Raw JSON (default, recommended)
- 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 purchasedsubscription.updated(required) - Updates subscription status/plan changessubscription.canceled(required) - Handles cancellation requestssubscription.revoked(optional) - Handles immediate subscription termination
Additional Optional Events:
order.created- Order creation notificationsorder.paid- Payment confirmation (redundant if usingcheckout.updated)order.refunded- Refund notificationssubscription.active- Subscription activation confirmationcustomer.created- New customer trackingcheckout.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/polar6. Configure Environment Variables
Add these variables to your .env.local file:
# 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-zzzzzzzzzzzzWhere 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:
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