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
- User authenticates with Firebase in your app
- App sends Firebase token with SDK requests
- Fig1 verifies token and reads subscription claims
- Content access is granted based on user's subscriptions
Prerequisites
- Firebase configured for your site
- API key for SDK access
Configuring Subscriptions
Enable Subscriptions
- Go to Firebase & Subscriptions in the Fig1 dashboard
- Navigate to the Subscriptions tab
- 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:
- Click Add Custom Subscription
- Enter:
- Name: Display name (e.g., "Boxing Fundamentals")
- Slug: URL-safe identifier (e.g.,
boxing_fundamentals) - Description: What this subscription includes
- 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:
- Access Level:
subscription - 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
- Go to Users in the sidebar
- Search for a user by email
- Click Edit
- Check/uncheck subscriptions
- Optionally set an expiry date
- 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
- Use Clear Names - "Boxing Fundamentals" not "BF001"
- Group Logically - Use categories (tier, course, feature, bundle)
- Plan for Bundles - Create an "all access" tier that includes everything
- Keep Slugs Stable - Don't change slugs after users have them
User Experience
- Show Available Subscriptions - Use the
availableSubscriptionsresponse - Token Refresh - Call
getIdToken(true)after subscription changes - Handle 403 Gracefully - Show upgrade prompts, not error messages
- 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
- Token Not Refreshed - Have user sign out/in or call
getIdToken(true) - Slug Mismatch - Ensure
requiredSubscriptionsmatches exactly - Expiry Passed - Check if
membershipExpiryhas passed
Subscriptions Not Appearing
- Firebase Not Configured - Complete Firebase setup first
- Subscriptions Not Enabled - Enable the toggle
- No Templates Selected - Select at least one template or create custom