Lemon Squeezy Provider
Learn how to integrate Lemon Squeezy as your payment provider.
Lemon Squeezy is a merchant of record platform designed specifically for digital products and SaaS. It handles taxes, VAT, and compliance automatically, making it ideal for selling globally without the hassle.
Setup
1. Create a Lemon Squeezy Account
- Sign up at https://lemonsqueezy.com
- Complete your account setup and verification
- Navigate to the Dashboard
2. Create a Store
- Go to Settings → Stores
- Click New Store
- Fill in your store details
- Copy your Store ID (you'll need this later)
Where to find Store ID:
- Settings → Stores → Your store → URL contains the ID
- Or check the store settings page
3. Get Your API Key
- Go to Settings → API
- Click Create API key
- Give it a name (e.g., "Production API Key")
- Copy the API key (starts with
lemon_)
Important
4. Create Products and Variants
- Go to Products → New Product
- Create your product:
- Set product name and description
- Upload images if needed
- Add Variants (pricing options):
- For subscriptions: Set recurring interval (monthly/yearly)
- For one-time: Set as one-time payment
- Set price and currency
- After creating, copy the Variant ID (a numeric ID)
Example Setup:
- Product: "Pro Plan"
- Variant 1: Monthly ($19/month) → Variant ID:
123456 - Variant 2: Yearly ($190/year) → Variant ID:
123457
- Variant 1: Monthly ($19/month) → Variant ID:
5. Set Up Webhooks
Webhooks notify your application about payment events.
For Production:
- Go to Settings → Webhooks
- Click Add endpoint
- Set the webhook URL:
https://yourdomain.com/api/webhooks/lemonsqueezy - Select events to listen to based on your payment types:
For One-Time Payments:
order_created(required) - Records the purchase when order is created
For Subscriptions:
subscription_created(required) - Creates subscription recordsubscription_updated(required) - Updates subscription status/plansubscription_cancelled(required) - Handles cancellationsubscription_resumed(required) - Handles resumption after pausesubscription_expired(required) - Removes expired subscriptions
If you use both payment types, select all events above.
- Copy the Signing secret to your environment variables
For Local Development:
Use a tunneling service like ngrok:
# Using ngrok
ngrok http 3000
# Then use the ngrok URL in webhook settings
https://your-ngrok-url.ngrok.io/api/webhooks/lemonsqueezy6. Configure Environment Variables
Add these variables to your .env.local file:
# Lemon Squeezy API Key
LEMONSQUEEZY_API_KEY=lemon_xxxxxxxxxxxxx
# Lemon Squeezy Store ID
LEMONSQUEEZY_STORE_ID=12345
# Lemon Squeezy Webhook Secret
LEMONSQUEEZY_WEBHOOK_SECRET=your_webhook_secret
# Your Price IDs (use Lemon Squeezy Variant IDs)
NEXT_PUBLIC_PRICE_ID_LIFETIME=123456
NEXT_PUBLIC_PRICE_ID_PRO_MONTHLY=123457
NEXT_PUBLIC_PRICE_ID_PRO_YEARLY=123458Where to find these:
- API Key: Settings → API → Create/copy API key
- Store ID: Settings → Stores → Your store ID in URL
- Webhook Secret: Settings → Webhooks → Copy signing secret (from step 5)
- Price IDs: Products → Click product → Copy variant IDs (use as Price IDs)
Configuration
Set Lemon Squeezy as your payment provider in config/index.ts:
export const config = {
payments: {
provider: "lemonsqueezy",
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 Variant IDs (not Product IDs) in your configuration.
Multi-Currency Support
Lemon Squeezy supports multiple currencies:
- Set up variants for different currencies in your Lemon Squeezy dashboard
- Configure multiple prices in your config:
pro: {
recommended: false,
prices: [
{
type: "subscription",
productId: process.env.NEXT_PUBLIC_PRICE_ID_PRO_USD as string,
amount: 19,
currency: "USD",
interval: "month",
},
{
type: "subscription",
productId: process.env.NEXT_PUBLIC_PRICE_ID_PRO_EUR as string,
amount: 17,
currency: "EUR",
interval: "month",
},
],
}Advanced Features
Seat-Based Billing
Enable quantity-based pricing for team plans:
{
type: "subscription",
productId: process.env.NEXT_PUBLIC_PRICE_ID_ENTERPRISE as string,
amount: 99,
currency: "USD",
interval: "month",
seats: {
min: 5,
max: 100,
},
}