Skip to content

Subscription Packages

Package configuration defines the pricing tiers and feature limits for TendSocial subscriptions.

API Endpoints

GET /public/packages

Public endpoint - Returns active packages for pricing page and onboarding.

typescript
// Response
[{
  id: string,
  name: string,             // "Starter", "Professional", "Agency"
  description: string,
  price: number,            // Monthly price in currency
  interval: "month" | "year",
  currency: "USD",
  maxUsers: number,
  maxAiPosts: number,
  displayFeatures: string[],// Features for pricing UI
  salePrice: number | null, // Discounted price if on sale
  saleStartsAt: Date | null,
  saleEndsAt: Date | null,
  variantId: string | null, // Lemon Squeezy variant
  isActive: boolean,
  isPopular: boolean        // Highlight on pricing page
}]

GET /admin/packages

Admin only - Returns all packages including inactive.

POST /admin/packages

Create or update a package (upsert pattern).

typescript
// Request
{
  id?: string,              // Provide to update, omit to create
  name: string,
  description?: string,
  price: number,
  interval: "month" | "year",
  currency: "USD",
  maxUsers: number,
  maxAiPosts: number,
  displayFeatures: string[],
  salePrice?: number,
  saleStartsAt?: string,    // ISO date
  saleEndsAt?: string,
  variantId?: string,
  isActive: boolean,
  isPopular: boolean
}

DELETE /admin/packages/:id

Permanently delete a package.

Feature Limits

Each package defines limits that are enforced at runtime:

LimitDescription
maxUsersTeam members allowed
maxAiPostsAI generations per month
maxSocialAccountsConnected platforms
maxCampaignsActive campaigns

Sale Pricing

Packages support time-limited sale pricing:

typescript
{
  price: 29.00,           // Regular price
  salePrice: 19.00,       // Sale price
  saleStartsAt: "2024-11-25",
  saleEndsAt: "2024-11-30"
}

Frontend should check if sale is active and display sale price accordingly.

Lemon Squeezy Integration

The variantId field links packages to Lemon Squeezy variants for checkout.

Setup:

  1. Create products/variants in Lemon Squeezy dashboard
  2. Copy variant IDs
  3. Update packages via admin API
  4. Checkout flow uses variantId for payment

Database Schema

prisma
model PackageConfig {
  id              String    @id @default(cuid())
  name            String
  description     String?
  price           Decimal   @db.Decimal(10, 2)
  interval        String    @default("month")
  currency        String    @default("USD")
  maxUsers        Int       @default(1)
  maxAiPosts      Int       @default(50)
  displayFeatures String[]
  salePrice       Decimal?  @db.Decimal(10, 2)
  saleStartsAt    DateTime?
  saleEndsAt      DateTime?
  variantId       String?
  isActive        Boolean   @default(true)
  isPopular       Boolean   @default(false)
}

TendSocial Documentation