Billing (Lemon Squeezy)
Lemon Squeezy integration, subscriptions, and billing flows. This is the pack-billing-lemonsqueezy pack, one of the
three variants in the billing family. Pick it when you want a merchant of record: Lemon Squeezy is the seller, so it
collects and remits sales tax and VAT for you.
The product shape is the same as Billing (Stripe): a billing page with plan cards, a hosted checkout, a customer portal, signature-verified webhooks, and the admin revenue widgets. Only the provider behind it changes, which is what makes the three packs swappable.
What you need
- A Lemon Squeezy account and a store. Sign up at app.lemonsqueezy.com.
- Two subscription products (Pro and Premier in the pack's schema), each with a variant.
- Postgres and Valkey (subscription status is cached in Valkey, keyed by organization).
- Optionally Resend for receipt emails.
Credentials
From the Lemon Squeezy dashboard, grab:
- An API key (
LEMONSQUEEZY_API_KEY) from Settings > API. - Your store id (
LEMONSQUEEZY_STORE_ID) from Settings > Stores. - The variant ids of the two plans (
LEMONSQUEEZY_VARIANT_PRO,LEMONSQUEEZY_VARIANT_PREMIER). - A webhook signing secret (
LEMONSQUEEZY_WEBHOOK_SECRET), which you choose when you create the webhook below.
Lemon Squeezy has a test mode toggle in the dashboard. Keys and variant ids differ between test and live, so keep both sets and switch them together.
Webhook endpoint
The pack exposes the receiver at:
POST /checkout/webhookIn Settings > Webhooks, add an endpoint pointing at https://your-api-origin/checkout/webhook, set a signing secret,
and subscribe to the subscription events. The pack handles the whole subscription_* family: created, updated, plan
changed, paused and resumed, payment success, failed, and recovered, cancelled, and expired. Copy the secret into
LEMONSQUEEZY_WEBHOOK_SECRET.
There is no local forwarding CLI. For development, expose your backend through a tunnel and register that URL in test mode.
Environment variables
| Variable | Purpose |
|---|---|
LEMONSQUEEZY_API_KEY | API key |
LEMONSQUEEZY_STORE_ID | The store products belong to |
LEMONSQUEEZY_WEBHOOK_SECRET | Signing secret for the webhook endpoint |
LEMONSQUEEZY_VARIANT_PRO | Variant id for Pro |
LEMONSQUEEZY_VARIANT_PREMIER | Variant id for Premier |
RESEND_API_KEY | Optional. Enables receipt emails |
In the admin
On top of a starter, this pack adds a revenue row to the admin app dashboard, a
billing card and revenue card on the organization details page, and /admin/billing API routes.
Switching providers
Billing is a family slot. To move to Stripe or Polar later:
npx @hype-stack/cli compose --packs pack-billing-polarThe CLI replaces the files the two packs share, removes the Lemon Squeezy-only ones, and leaves your own code alone. Subscription state is cached per organization, so existing customers need to be re-subscribed on the new provider.
Related
- Billing (Stripe) for the shared checkout and portal flow
- Organizations for the tenant boundary billing attaches to
- Going to production for the webhook checklist
Every purchase and sponsorship funds my 8+ years of work on open source given freely to the community. It keeps the lights on, funds new packs, and keeps the ecosystem alive. Even a small tier means a lot. Thank you!
