Lemonsqueezy
Lemon Squeezy is an all-in-one platform for selling digital products and subscriptions.
You are a Lemon Squeezy integration specialist who expertly sets up and manages digital product sales and subscriptions. You configure stores, define products, orchestrate checkout flows, process payments, and leverage webhooks for real-time event handling, ensuring global tax compliance and seamless customer experiences. ## Key Points * **Secure API Keys**: Never expose your private API key in client-side code. Use environment variables and server-side processing for all API interactions. * **Verify Webhook Signatures**: Always validate the `X-Signature` header in webhook requests to ensure the payload genuinely originated from Lemon Squeezy and hasn't been tampered with. * **Test in Sandbox**: Develop and test your integrations thoroughly using a Lemon Squeezy sandbox store before deploying to production. ## Quick Example ```bash npm install @lemonsqueezy/lemonsqueezy.js # or yarn add @lemonsqueezy/lemonsqueezy.js ```
skilldb get ecommerce-services-skills/LemonsqueezyFull skill: 237 linesYou are a Lemon Squeezy integration specialist who expertly sets up and manages digital product sales and subscriptions. You configure stores, define products, orchestrate checkout flows, process payments, and leverage webhooks for real-time event handling, ensuring global tax compliance and seamless customer experiences.
Core Philosophy
Lemon Squeezy's core philosophy is to simplify the complex world of selling digital products and managing subscriptions globally. It acts as a Merchant of Record, taking on the burden of sales tax, VAT, and GST calculation and remittance across various jurisdictions. This frees you from the intricate legal and financial overhead associated with international digital sales, allowing you to focus on product development and marketing.
The platform provides a comprehensive suite of tools, from storefronts and product management to robust subscription logic and affiliate programs. Its API-first design ensures that while you can use its hosted solutions out-of-the-box, you also have the flexibility to integrate deeply into custom applications, offering a bespoke experience while still benefiting from its underlying compliance and payment infrastructure. Choose Lemon Squeezy when you need a powerful, compliant, and developer-friendly solution for recurring revenue or one-time digital sales.
Setup
To integrate Lemon Squeezy, you first need an account and an API key. Obtain your API key from your Lemon Squeezy dashboard under Settings > API. You'll need a "Private API Key" for server-side interactions.
For Node.js applications, use the official Lemon Squeezy SDK:
Install
npm install @lemonsqueezy/lemonsqueezy.js
# or
yarn add @lemonsqueezy/lemonsqueezy.js
Configure
Initialize the SDK with your private API key. It's crucial to store your API key securely, preferably in environment variables.
// server.js or api-handler.js
import { LemonSqueezy } from '@lemonsqueezy/lemonsqueezy.js';
// For CommonJS: const { LemonSqueezy } = require('@lemonsqueezy/lemonsqueezy.js');
// Initialize the Lemon Squeezy client
const ls = new LemonSqueezy(process.env.LEMON_SQUEEZY_API_KEY);
export default ls; // Export for use in other modules
Key Techniques
1. Generating a Dynamic Checkout Link
Lemon Squeezy's hosted checkout pages are powerful. You can generate a checkout URL for any product with custom parameters like variants, discounts, and pre-filled customer details.
// Example: Generate a checkout link for a product with a specific variant
import ls from './ls-client'; // Assuming ls client is initialized and exported as above
async function createProductCheckout(productId, variantId, customerEmail = '') {
try {
const checkout = await ls.createCheckout({
storeId: process.env.LEMON_SQUEEZY_STORE_ID, // Your store ID
productId: productId,
variantId: variantId,
// Optional: Prefill customer details or apply a discount
checkoutOptions: {
embed: false, // Set to true for embeddable checkout
media: false,
buttonColor: '#36D199',
},
productOptions: {
name: 'My Custom Product Name', // Override product name on checkout
description: 'A customized description for this purchase',
// quantity: 1, // Optional: specify quantity
// If you need custom fields:
// custom: {
// userId: 'user_123',
// campaign: 'launch_promo',
// },
},
// You can also pass a `checkoutData` object to pre-fill customer info
checkoutData: {
email: customerEmail,
// taxNumber: 'GB123456789',
// billingAddress: { country: 'GB' },
}
});
// The checkout object contains a `data.attributes.url` for the checkout link
if (checkout.data && checkout.data.attributes && checkout.data.attributes.url) {
return checkout.data.attributes.url;
} else {
throw new Error('Could not retrieve checkout URL.');
}
} catch (error) {
console.error('Error creating checkout:', error.response ? error.response.data : error.message);
throw error;
}
}
// Usage example (e.g., in an Express route)
// app.get('/buy/:productId/:variantId', async (req, res) => {
// try {
// const { productId, variantId } = req.params;
// const checkoutUrl = await createProductCheckout(parseInt(productId), parseInt(variantId), req.user?.email);
// res.redirect(checkoutUrl);
// } catch (error) {
// res.status(500).send('Failed to create checkout.');
// }
// });
2. Handling Webhook Events
Webhooks are essential for reacting to events like successful purchases, subscription updates, or refunds. Lemon Squeezy sends POST requests to your configured webhook URL. Always verify the webhook signature.
// Example: Basic Express.js webhook handler
import express from 'express';
import bodyParser from 'body-parser';
import crypto from 'crypto';
const app = express();
// Raw body parser for signature verification
app.post('/webhook/lemonsqueezy', bodyParser.raw({ type: 'application/json' }), async (req, res) => {
const secret = process.env.LEMON_SQUEEZY_WEBHOOK_SECRET;
const hmac = crypto.createHHmac('sha256', secret);
const digest = Buffer.from(hmac.update(req.body).digest('hex'), 'utf8');
const signature = Buffer.from(req.get('X-Signature') || '', 'utf8');
if (!crypto.timingSafeEqual(digest, signature)) {
console.error('Webhook signature verification failed.');
return res.status(401).send('Invalid signature.');
}
const payload = JSON.parse(req.body.toString());
const eventName = payload.meta.event_name;
console.log(`Received Lemon Squeezy event: ${eventName}`);
try {
switch (eventName) {
case 'order_created':
// Handle new purchase: fulfill digital product, send welcome email
const order = payload.data;
console.log(`New order #${order.id} for ${order.attributes.user_email}.`);
// Example: Trigger product delivery
// await fulfillOrder(order.id, order.attributes.user_email);
break;
case 'subscription_created':
// Handle new subscription: grant access to premium features
const subscription = payload.data;
console.log(`New subscription #${subscription.id} for ${subscription.attributes.user_email}.`);
// Example: Update user's access level in your database
// await updateUserSubscriptionStatus(subscription.id, subscription.attributes.user_email, 'active');
break;
case 'subscription_updated':
// Handle changes like plan upgrades/downgrades, payment failures
console.log('Subscription updated:', payload.data.id, payload.data.attributes.status);
break;
case 'subscription_cancelled':
// Handle cancellation: revoke access after period ends
console.log('Subscription cancelled:', payload.data.id);
break;
// Add other event handlers as needed
default:
console.warn(`Unhandled Lemon Squeezy event: ${eventName}`);
}
res.status(200).send('Webhook received successfully.');
} catch (error) {
console.error('Error processing webhook:', error);
res.status(500).send('Internal server error.');
}
});
// app.listen(3000, () => console.log('Webhook server listening on port 3000'));
3. Fetching Store Data (Products, Orders)
You can retrieve various resources from your Lemon Squeezy store using the API. This is useful for building custom dashboards, product listings, or syncing data with your internal systems.
// Example: Fetching all products from your store
import ls from './ls-client'; // Assuming ls client is initialized and exported as above
async function getAllProducts() {
try {
const productsResponse = await ls.getProducts();
return productsResponse.data; // Array of product objects
} catch (error) {
console.error('Error fetching products:', error.response ? error.response.data : error.message);
throw error;
}
}
// Example: Fetching a specific order by ID
async function getOrderById(orderId) {
try {
const orderResponse = await ls.getOrder({ id: orderId });
return orderResponse.data; // Single order object
} catch (error) {
console.error(`Error fetching order ${orderId}:`, error.response ? error.response.data : error.message);
throw error;
}
}
// Usage example
// async function main() {
// const products = await getAllProducts();
// console.log('Products:', products.map(p => p.attributes.name));
//
// const order = await getOrderById(12345); // Replace with a real order ID
// console.log('Order details:', order);
// }
//
// main().catch(console.error);
Best Practices
- Secure API Keys: Never expose your private API key in client-side code. Use environment variables and server-side processing for all API interactions.
- Leverage Webhooks: For real-time updates and fulfilling digital products, always rely on webhooks instead of polling the API. This ensures your system reacts immediately to purchases, cancellations, and other crucial events.
- Verify Webhook Signatures: Always validate the
X-Signatureheader in webhook requests to ensure the payload genuinely originated from Lemon Squeezy and hasn't been tampered with. - Handle Idempotency: Design your webhook handlers to be idempotent. If the same webhook event is delivered multiple times (due to network issues, for example), your system should process it only once or gracefully handle duplicates.
- Robust Error Handling: Implement comprehensive
try/catchblocks around all API calls and webhook processing. Log errors and consider implementing retry mechanisms for transient API failures. - Use Embeddable Checkout: For a more integrated user experience, utilize Lemon Squeezy's embeddable checkout option. This keeps users on your site while leveraging Lemon Squeezy's payment and compliance infrastructure.
- Test in Sandbox: Develop and test your integrations thoroughly using a Lemon Squeezy sandbox store before deploying to production.
Anti-Patterns
Hardcoding API Keys. Storing your private API key directly in your codebase is a security risk. Use environment variables (process.env.LEMON_SQUEEZY_API_KEY) and never commit them to version control.
Polling for Updates. Regularly querying the Lemon Squeezy API for new orders or subscription changes instead of using webhooks. This wastes API quotas, adds latency, and creates unnecessary load on both your and Lemon Squeezy's servers. Rely on webhooks for immediate, event-driven updates.
Ignoring Webhook Signatures. Processing webhook payloads without verifying the X-Signature header. This leaves your system vulnerable to spoofed requests and potential data manipulation. Always validate the signature.
Mismanaging Product Variants. Defining a single product in Lemon Squeezy for every slight variation (e.g., "Product A - Small", "Product A - Medium"). Instead, use Lemon Squeezy's variant system to manage different options (size, color, etc.) under a single product, simplifying management and API interactions.
Bypassing Embeddable Checkout for Custom Forms. Trying to recreate the entire payment and checkout experience with custom forms and direct API calls instead of using the embeddable checkout. This reintroduces the complexity of payment processing, tax calculation, and PCI compliance that Lemon Squeezy is designed to abstract away. Leverage the hosted or embeddable checkout for maximum compliance and ease.
Install this skill directly: skilldb add ecommerce-services-skills
Related Skills
Bigcommerce
Integrate BigCommerce APIs for catalog management, order processing,
Commercejs
Integrate Commerce.js headless commerce SDK for product management,
Fourthwall
Fourthwall is a specialized e-commerce platform that empowers creators to design, launch, and sell custom physical merchandise directly to their audience. It streamlines the entire process from product creation and manufacturing to fulfillment and customer service, making it an ideal solution for content creators, streamers, and influencers looking to monetize their brand with high-quality physical goods without managing inventory or logistics.
Gumroad
Gumroad is an e-commerce platform designed for creators to sell digital products, memberships, and physical goods directly to their audience. It provides a simple storefront, payment processing, and delivery mechanisms, making it ideal for solopreneurs, artists, and educators who want to monetize their creations quickly and efficiently without complex technical setups.
Medusa
Build headless commerce backends with Medusa's modular architecture.
Paddle
Integrate Paddle as your Merchant of Record (MoR) to handle global payments, subscriptions, and tax compliance for SaaS and digital products. It simplifies international selling by taking on the legal and financial complexities, allowing you to focus on your core product.