Subscriptions

Gate content based on user subscriptions for granular access control.

Overview

The subscription system enables:

  • Granular Access Control - Gate content by specific subscriptions, not just membership tiers
  • Flexible Configuration - Use template subscriptions or create custom ones
  • Access Rules - Define subscription inheritance (e.g., "all_access" includes all subscriptions)
  • Privacy-First - User subscription data lives in your Firebase project

How It Works

User Signs In → Firebase Auth → SDK Request with Token → Access Check → Content Delivered
  1. User authenticates with Firebase in your app
  2. App sends Firebase token with SDK requests
  3. Fig1 verifies token and reads subscription claims
  4. Content access is granted based on user's subscriptions

Prerequisites

Configuring Subscriptions

Enable Subscriptions

  1. Go to Firebase & Subscriptions in the Fig1 dashboard
  2. Navigate to the Subscriptions tab
  3. Enable the subscriptions toggle

Template Subscriptions

Fig1 provides templates for common use cases:

| Template | Slug | Category | |----------|------|----------| | Premium Content | premium_content | Tier | | Course Access | course_access | Course | | Early Access | early_access | Feature | | Ad-Free Experience | ad_free | Feature | | Community Access | community_access | Feature | | All Access Pass | all_access | Bundle |

Custom Subscriptions

Create subscriptions specific to your content:

  1. Click Add Custom Subscription
  2. Enter:
    • Name: Display name (e.g., "Boxing Fundamentals")
    • Slug: URL-safe identifier (e.g., boxing_fundamentals)
    • Description: What this subscription includes
  3. Click Add

Access Rules

Define subscription inheritance where one subscription grants access to others:

{
  "subscriptionSlug": "all_access",
  "grantsAccessTo": ["boxing_fundamentals", "cardio_basics", "strength_training"]
}

Users with all_access can access content requiring any of the granted subscriptions.

Gating Content

Setting Access Level

When creating content, set:

  1. Access Level: subscription
  2. Required Subscriptions: Array of subscription slugs

Via SDK

await fetch('https://app.fig1.ai/api/sdk/content', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Fig1-API-Key': 'your-api-key'
  },
  body: JSON.stringify({
    externalId: 'boxing-combos-101',
    type: 'article',
    title: 'Advanced Boxing Combinations',
    content: '<p>Learn professional combinations...</p>',
    accessLevel: 'subscription',
    requiredSubscriptions: ['boxing_fundamentals']
  })
});

Access Logic

  • User needs at least ONE of the required subscriptions
  • Access rules are checked for inherited access
  • Unauthenticated users cannot access subscription content

Granting Subscriptions

Subscriptions are stored in Firebase custom claims.

Via Fig1 Dashboard

  1. Go to Users in the sidebar
  2. Search for a user by email
  3. Click Edit
  4. Check/uncheck subscriptions
  5. Optionally set an expiry date
  6. Click Save

Via Your Backend

Use Firebase Admin SDK:

import * as admin from 'firebase-admin';

// Grant subscriptions
await admin.auth().setCustomUserClaims(userId, {
  subscriptions: ['boxing_fundamentals', 'premium_content'],
  membershipExpiry: '2025-12-31T00:00:00Z'
});

Via Payment Integration

// After successful payment (e.g., Stripe webhook)
async function grantSubscription(userId: string, subscriptionSlug: string) {
  const user = await admin.auth().getUser(userId);
  const currentClaims = user.customClaims || {};
  const currentSubs = currentClaims.subscriptions || [];

  await admin.auth().setCustomUserClaims(userId, {
    ...currentClaims,
    subscriptions: [...new Set([...currentSubs, subscriptionSlug])]
  });
}

Checking Access

Get User's Subscriptions

const response = await fetch('https://app.fig1.ai/api/sdk/user/subscriptions', {
  headers: {
    'X-Fig1-API-Key': 'your-api-key',
    'Authorization': `Bearer ${firebaseToken}`
  }
});

const data = await response.json();
// {
//   subscriptions: ['boxing_fundamentals', 'premium_content'],
//   availableSubscriptions: [{ slug: 'boxing_fundamentals', name: 'Boxing Fundamentals' }]
// }

List Content with Access Status

const response = await fetch(
  'https://app.fig1.ai/api/sdk/content?includeRestricted=true',
  {
    headers: {
      'X-Fig1-API-Key': 'your-api-key',
      'Authorization': `Bearer ${firebaseToken}`
    }
  }
);

const data = await response.json();

data.data.forEach(item => {
  if (item._access.granted) {
    // User can access this content
    showAccessibleContent(item);
  } else {
    // Show locked preview
    showLockedContent(item, item._access.requiredSubscriptions);
  }
});

Handle Access Denied

const content = await fetch('https://app.fig1.ai/api/sdk/content/boxing-combos-101', {
  headers: {
    'X-Fig1-API-Key': 'your-api-key',
    'Authorization': `Bearer ${firebaseToken}`
  }
});

if (content.status === 403) {
  const error = await content.json();
  showUpgradePrompt(error.requiredSubscriptions);
}

Best Practices

Subscription Design

  1. Use Clear Names - "Boxing Fundamentals" not "BF001"
  2. Group Logically - Use categories (tier, course, feature, bundle)
  3. Plan for Bundles - Create an "all access" tier that includes everything
  4. Keep Slugs Stable - Don't change slugs after users have them

User Experience

  1. Show Available Subscriptions - Use the availableSubscriptions response
  2. Token Refresh - Call getIdToken(true) after subscription changes
  3. Handle 403 Gracefully - Show upgrade prompts, not error messages
  4. Cache Carefully - User subscriptions can change

API Reference

Content Access Levels

| Level | Description | Requirements | |-------|-------------|--------------| | public | Anyone can access | None | | authenticated | Signed-in users only | Firebase token | | premium | Premium tier users | Premium/Pro membership | | subscription | Subscription holders | Specific subscription(s) |

Content Response Fields

{
  "_access": {
    "level": "subscription",
    "requiredSubscriptions": ["boxing_fundamentals"],
    "granted": boolean,
    "reason": string | null  // Only when granted=false
  }
}

Troubleshooting

User Has Subscription But Can't Access Content

  1. Token Not Refreshed - Have user sign out/in or call getIdToken(true)
  2. Slug Mismatch - Ensure requiredSubscriptions matches exactly
  3. Expiry Passed - Check if membershipExpiry has passed

Subscriptions Not Appearing

  1. Firebase Not Configured - Complete Firebase setup first
  2. Subscriptions Not Enabled - Enable the toggle
  3. No Templates Selected - Select at least one template or create custom

Next Steps