Backend API for LemonDash — a free mobile dashboard for Lemon Squeezy sellers. Track your MRR, revenue, orders, and subscriptions in real time with push notifications on every sale.
- Express + TypeScript — API server
- Prisma + SQLite — Database & ORM
- Expo Push API — Push notifications (with FCM fallback)
- Zod — Request validation
- Pino — Structured logging
- Railway — Deployment
- Encrypted storage of Lemon Squeezy API tokens (AES-256-GCM)
- Automatic webhook creation on user's LS store
- Real-time push notifications on sales, renewals, refunds
- Smart webhook deduplication (LS sends multiple events per action)
- Analytics: Revenue, MRR, Orders, Subscriptions with date aggregation
- In-memory caching with configurable TTL
- Rate limiting per endpoint
- Multi-device support
- Node.js >= 18
- npm
# Clone and install
cd backend
npm install
# Create environment file
cp .env.example .env
# Generate encryption key and add it to .env
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# Push database schema
npm run db:push
# Start development server
npm run devThe server starts on http://localhost:4000.
| Variable | Required | Default | Description |
|---|---|---|---|
ENCRYPTION_KEY |
Yes | — | 64-char hex string for AES-256-GCM encryption |
BACKEND_URL |
Yes | — | Public URL (used for webhook registration) |
DATABASE_URL |
No | file:./dev.db |
SQLite connection string |
FIREBASE_SERVICE_ACCOUNT |
No | ./firebase-sa.json |
Path to Firebase service account JSON (optional FCM fallback) |
PORT |
No | 4000 |
Server port |
NODE_ENV |
No | development |
development / production |
CORS_ORIGINS |
No | http://localhost:8081 |
Comma-separated allowed origins |
Push notifications are sent via the Expo Push API — no Firebase setup required. Firebase is an optional fallback for raw FCM tokens.
| Method | Endpoint | Description |
|---|---|---|
| POST | /auth/register |
Register device with LS API token |
| POST | /auth/verify |
Verify stored API token |
| DELETE | /auth/device |
Disconnect device & clean up webhook |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/dashboard |
MRR, revenue, sales today, active subs, recent orders |
| GET | /api/orders |
Paginated orders (?page=1&perPage=20&status=paid) |
| GET | /api/subscriptions |
Paginated subscriptions (?status=active) |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/analytics |
Charts data (?metric=revenue&period=30d) |
Metrics: revenue, mrr, orders, subscriptions
Periods: 7d, 30d, 90d, 12m
| Method | Endpoint | Description |
|---|---|---|
| POST | /webhooks/lemon |
Receives Lemon Squeezy webhook events |
Handles: order_created, order_refunded, subscription_created, subscription_updated, subscription_expired, subscription_payment_success
| Method | Endpoint | Description |
|---|---|---|
| POST | /notifications/register |
Register FCM/Expo push token |
| POST | /notifications/test |
Send a test push notification |
| Method | Endpoint | Description |
|---|---|---|
| GET | /health |
Server status & uptime |
Two models managed by Prisma:
Device — registered app instances
- Encrypted Lemon Squeezy API token (AES-256-GCM)
- FCM push token
- Webhook ID and secret per store
- Premium status
WebhookEvent — audit log of all received webhooks
- Store ID, event name, full payload, timestamp
Run npm run db:studio to browse the database visually.
Mobile App Backend Lemon Squeezy
| | |
|-- POST /auth/register ---->| |
| (LS API key) |-- verify key ------------->|
| |<- store info --------------|
| |-- create webhook --------->|
|<- deviceToken -------------| |
| | |
|-- GET /api/dashboard ----->|-- fetch orders/subs ------>|
|<- MRR, revenue, etc. -----|<- data --------------------|
| | |
| |<---- webhook event --------|
|<---- push notification ----| (order_created, etc.) |
Configured for Railway with railway.json. Any platform that supports Node.js works.
# Build for production
npm run build
# Start production server
npm startThe start script automatically runs database migrations before starting the server.
| Script | Description |
|---|---|
npm run dev |
Start dev server with hot reload |
npm run build |
Compile TypeScript + generate Prisma client |
npm start |
Production start (migrate + run) |
npm run db:push |
Sync Prisma schema to database |
npm run db:migrate |
Create a new migration |
npm run db:studio |
Open Prisma Studio GUI |
MIT