LemonSqueezy
Simple Merchant of Record for indie developers and small SaaS. LemonSqueezy handles payments, subscriptions, and global tax with a developer-friendly API and zero monthly fees.
Proprietary
TypeScript
Why LemonSqueezy?
Indie developers or solo founders
Simple SaaS subscriptions without complex billing
You want MoR protection without Paddle's complexity
Signal Breakdown
What drives the Trust Score
Download Trend
Last 12 months
Tradeoffs & Caveats
Know before you commitEnterprise or high-volume (fees add up)
Complex billing scenarios (usage-based, seats)
You need maximum reliability (Stripe's track record wins)
Pricing
Free tier & paid plans
No monthly fee
5% + $0.50 per transaction
Same rate as Paddle but simpler setup for indie devs
Alternative Tools
Other options worth considering
The gold standard for payments infrastructure. Handles subscriptions, one-time charges, invoicing, tax, and fraud detection. Used by millions of businesses globally — the default choice.
Often Used Together
Complementary tools that pair well with LemonSqueezy
Learning Resources
Docs, videos, tutorials, and courses
Get Started
Repository and installation options
View on GitHub
github.com/lmsqueezy/lemonsqueezy.js
npm install @lemonsqueezy/lemonsqueezy.jsQuick Start
Copy and adapt to get going fast
import { lemonSqueezySetup, createCheckout } from '@lemonsqueezy/lemonsqueezy.js';
lemonSqueezySetup({ apiKey: process.env.LEMONSQUEEZY_API_KEY });
const checkout = await createCheckout(storeId, variantId, {
checkoutData: { email: user.email, custom: { user_id: user.id } },
});Code Examples
Common usage patterns
Webhook validation
Verify and handle LemonSqueezy webhooks
import crypto from 'crypto';
const secret = process.env.LEMONSQUEEZY_WEBHOOK_SECRET;
const hmac = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
if (hmac !== req.headers['x-signature']) return res.status(401).end();
const event = JSON.parse(rawBody);
if (event.meta.event_name === 'subscription_created') {
await activateSubscription(event.data.attributes.customer_id);
}List subscriptions
Fetch active subscriptions
import { listSubscriptions } from '@lemonsqueezy/lemonsqueezy.js';
const { data } = await listSubscriptions({ filter: { status: 'active' } });
const subs = data?.data ?? [];Community Notes
Real experiences from developers who've used this tool