Environment Variables
All Payment Variables
| Variable | Required | Provider | Description |
|---|---|---|---|
PAYMENT_PROVIDER | Yes | Both | "stripe" or "lemonsqueezy" |
STRIPE_SECRET_KEY | If Stripe | Stripe | Secret key from Stripe dashboard (sk_live_... or sk_test_...) |
STRIPE_WEBHOOK_SECRET | If Stripe | Stripe | Webhook signing secret from Stripe (whsec_...) |
STRIPE_PUBLISHABLE_KEY | No | Stripe | Publishable key for frontend (pk_live_... or pk_test_...) — safe to expose |
LEMONSQUEEZY_API_KEY | If LemonSqueezy | LemonSqueezy | API key from LemonSqueezy settings |
LEMONSQUEEZY_WEBHOOK_SECRET | If LemonSqueezy | LemonSqueezy | Webhook signing secret from LemonSqueezy |
LEMONSQUEEZY_STORE_ID | If LemonSqueezy | LemonSqueezy | Numeric store ID from LemonSqueezy dashboard |
Complete .env Block
Copy this into your .env file and fill in your credentials:
# Payments
PAYMENT_PROVIDER=
# Stripe — https://dashboard.stripe.com/apikeys
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=
STRIPE_PUBLISHABLE_KEY=
# LemonSqueezy — https://app.lemonsqueezy.com/settings/api
LEMONSQUEEZY_API_KEY=
LEMONSQUEEZY_WEBHOOK_SECRET=
LEMONSQUEEZY_STORE_ID=
Variable Notes
PAYMENT_PROVIDER
Determines which adapter is used. Valid values: stripe or lemonsqueezy.
To switch providers, just update this variable and restart your server. No code changes needed.
PAYMENT_PROVIDER=stripe
STRIPE_SECRET_KEY
Your secret API key from Stripe. Never expose this. Keep it in .env only.
Find it at dashboard.stripe.com/apikeys.
Test key (development): starts with sk_test_
Live key (production): starts with sk_live_
STRIPE_SECRET_KEY=sk_test_51234...
STRIPE_WEBHOOK_SECRET
The signing secret for webhook verification. Found in Stripe webhook settings.
Get it from dashboard.stripe.com/webhooks — look for the endpoint URL ending in /payments/webhook and copy the signing secret.
STRIPE_WEBHOOK_SECRET=whsec_test_12345...
STRIPE_PUBLISHABLE_KEY
Your public API key. Safe to expose in frontend code.
This key is never used server-side. Include it in .env for reference only. The server only reads the secret key.
If you're using Stripe.js on the frontend, you'll need this key there, but the backend payments module doesn't use it.
STRIPE_PUBLISHABLE_KEY=pk_test_abcd...
LEMONSQUEEZY_API_KEY
Your LemonSqueezy API key for making authenticated requests to their API.
Get it from app.lemonsqueezy.com/settings/api.
LEMONSQUEEZY_API_KEY=your_api_key_here
LEMONSQUEEZY_WEBHOOK_SECRET
The signing secret for LemonSqueezy webhook verification. Created when you set up a webhook in LemonSqueezy.
LEMONSQUEEZY_WEBHOOK_SECRET=your_webhook_secret
LEMONSQUEEZY_STORE_ID
Your numeric store ID from LemonSqueezy.
Find it in the URL: app.lemonsqueezy.com/stores/THIS_NUMBER
Numeric only. No letters or special characters.
LEMONSQUEEZY_STORE_ID=12345
Optional vs Required
All payment variables are optional in the Zod schema. If you don't use payments, missing payment vars won't crash your server.
However, if you set PAYMENT_PROVIDER=stripe, then STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET become required at runtime. Missing them will cause an error when the module initializes.
Error Reference
If you see these errors, check the corresponding fix:
| Error | Meaning | Fix |
|---|---|---|
PROVIDER_NOT_CONFIGURED | PAYMENT_PROVIDER is not set | Add PAYMENT_PROVIDER=stripe or lemonsqueezy to .env |
STRIPE_CONFIG_MISSING | Missing Stripe credentials for selected provider | Check STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET in .env |
LEMONSQUEEZY_CONFIG_MISSING | Missing LemonSqueezy credentials for selected provider | Check LEMONSQUEEZY_API_KEY, LEMONSQUEEZY_WEBHOOK_SECRET, LEMONSQUEEZY_STORE_ID in .env |
WEBHOOK_SIGNATURE_INVALID | Webhook signature verification failed | Check that STRIPE_WEBHOOK_SECRET or LEMONSQUEEZY_WEBHOOK_SECRET matches your provider settings. Also verify the raw body middleware is registered before express.json(). |
INVALID_PROVIDER_VALUE | PAYMENT_PROVIDER is not stripe or lemonsqueezy | Fix the spelling or case of PAYMENT_PROVIDER |
Development vs Production
Development
Use test keys while building:
- Stripe:
sk_test_... - LemonSqueezy: test API key (check your LemonSqueezy account for test mode)
Test keys never charge real payment methods.
Production
Switch to live keys:
- Stripe:
sk_live_... - LemonSqueezy: live API key
Double-check:
PAYMENT_PROVIDERis correct- Webhook URLs are set to your production domain
- Webhook secrets are production secrets, not test secrets
- All required vars are present