Content API
Manage content items that your AI can reference and deliver to users.
GET /api/sdk/content
Retrieve content items with optional access filtering.
Query Parameters
| Parameter | Type | Description |
|-----------|------|-------------|
| type | string | Filter by content type (article, product, faq, etc.) |
| status | string | Filter by status (draft, published, archived) |
| limit | number | Max items to return (default: 50, max: 100) |
| offset | number | Pagination offset |
| search | string | Search in title |
| accessLevel | string | Filter by access level (public, authenticated, premium, subscription) |
| collectionId | string | Filter by collection ID |
| expand | boolean | Expand reference fields to full objects (up to 3 levels deep) |
| includeRestricted | boolean | Include content user can't access, with _access field (default: false) |
| sort | string | Sort by field: publishedAt, sortOrder, createdAt, title (default: publishedAt) |
| sortDir | string | Sort direction: asc or desc (default: desc) |
| includeSortOrder | boolean | Add _sortOrder field with compound group-position format (default: false) |
Example Request
curl -X GET "https://app.fig1.ai/api/sdk/content?type=article&status=published&limit=10" \
-H "X-Fig1-API-Key: fig1_sdk_abc123"
Response
{
"success": true,
"data": [
{
"_id": "content_abc123",
"type": "article",
"contentTypeId": "type_xyz789",
"title": "Getting Started Guide",
"excerpt": "Learn how to get started with our platform...",
"slug": "getting-started",
"url": "/guides/getting-started",
"categories": ["guides", "beginner"],
"tags": ["tutorial", "onboarding"],
"status": "published",
"accessLevel": "public",
"featuredImage": "https://cdn.example.com/image.jpg",
"customFields": {},
"sortOrder": 0,
"publishedAt": "2024-01-15T10:00:00Z"
}
],
"pagination": {
"total": 45,
"limit": 10,
"offset": 0,
"hasMore": true
}
}
Access Filtering
By default, the API only returns content the user can access. Use includeRestricted=true to see all content with access status.
Without Authentication (API Key Only)
Only returns public content.
With Firebase Token
Returns content based on user's membership tier and subscriptions.
Access Status Response
When using includeRestricted=true:
curl -X GET "https://app.fig1.ai/api/sdk/content?includeRestricted=true" \
-H "X-Fig1-API-Key: fig1_sdk_abc123" \
-H "Authorization: Bearer <firebase_token>"
{
"success": true,
"data": [
{
"_id": "content_abc123",
"title": "Public Article",
"accessLevel": "public",
"_access": {
"level": "public",
"granted": true,
"reason": null
}
},
{
"_id": "content_def456",
"title": "Premium Boxing Technique",
"accessLevel": "subscription",
"requiredSubscriptions": ["boxing_fundamentals"],
"_access": {
"level": "subscription",
"requiredSubscriptions": ["boxing_fundamentals"],
"granted": false,
"reason": "Subscription required: boxing_fundamentals"
}
}
],
"pagination": { ... },
"_accessSummary": {
"totalItems": 50,
"accessibleItems": 35,
"restrictedItems": 15,
"includeRestricted": true
}
}
Expanding References
When using custom content types with reference fields, add expand=true to get full nested objects instead of IDs:
curl -X GET "https://app.fig1.ai/api/sdk/content?type=course&expand=true" \
-H "X-Fig1-API-Key: fig1_sdk_abc123"
Without expand=true, reference fields return IDs:
{
"customFields": {
"lessons": ["65abc123", "65abc456"]
}
}
With expand=true, reference fields return full objects (up to 3 levels deep):
{
"customFields": {
"lessons": [
{ "_id": "65abc123", "title": "Lesson 1", "sortOrder": 0, "customFields": { ... } },
{ "_id": "65abc456", "title": "Lesson 2", "sortOrder": 1, "customFields": { ... } }
]
}
}
Note: When expanding reference arrays, each item automatically gets a sortOrder field set to its position in the array (0, 1, 2, etc.), making it easy to maintain display order in your app.
Sorting and Sort Order
Use sort and sortDir to control result ordering:
curl -X GET "https://app.fig1.ai/api/sdk/content?type=exercise&sort=sortOrder&sortDir=asc" \
-H "X-Fig1-API-Key: fig1_sdk_abc123"
Compound Sort Order (includeSortOrder)
When content is organized into groups (via built-in categories or reference-based categories), use includeSortOrder=true to get a _sortOrder field that encodes both group and position:
curl -X GET "https://app.fig1.ai/api/sdk/content?type=exercise&includeSortOrder=true" \
-H "X-Fig1-API-Key: fig1_sdk_abc123"
Response includes _sortOrder in format {groupOrder}-{itemOrder}:
{
"success": true,
"data": [
{
"_id": "exercise_abc",
"title": "Jab Drill",
"sortOrder": 5,
"_sortOrder": "001-005"
},
{
"_id": "exercise_def",
"title": "Cross Drill",
"sortOrder": 3,
"_sortOrder": "002-003"
}
]
}
The _sortOrder field is useful for:
- Displaying grouped content in flat lists
- Maintaining consistent ordering across different views
- Sorting content that spans multiple groups
Note: When using expand=true with nested content, the nested items use simple sortOrder (0, 1, 2) based on array position since grouping is implicit in the parent structure.
GET /api/sdk/content/:id
Get a single content item by ID. Access is checked based on user's authentication.
Headers
| Header | Required | Description |
|--------|----------|-------------|
| X-Fig1-API-Key | Yes | Your API key |
| Authorization | No | Bearer token for accessing restricted content |
Example Request
curl -X GET "https://app.fig1.ai/api/sdk/content/content_abc123" \
-H "X-Fig1-API-Key: fig1_sdk_abc123" \
-H "Authorization: Bearer <firebase_token>"
Success Response
{
"success": true,
"data": {
"_id": "content_abc123",
"title": "Advanced Boxing Combinations",
"accessLevel": "subscription",
"requiredSubscriptions": ["boxing_fundamentals"],
...
},
"access": {
"level": "subscription",
"requiredSubscriptions": ["boxing_fundamentals"],
"userHasAccess": true,
"userSubscriptions": ["boxing_fundamentals", "premium_content"]
},
"user": {
"uid": "firebase-user-id",
"membershipTier": "premium",
"subscriptions": ["boxing_fundamentals", "premium_content"]
}
}
Access Denied Response (403)
{
"success": false,
"error": "Subscription required: boxing_fundamentals",
"accessLevel": "subscription",
"requiredSubscriptions": ["boxing_fundamentals"],
"userTier": "free",
"userSubscriptions": [],
"isAuthenticated": true
}
POST /api/sdk/content
Create a new content item.
Request Body
{
externalId: string; // Your unique ID
type: string; // Content type (article, product, faq, video, etc. or custom type)
title: string;
content?: string; // Full content (HTML or markdown)
excerpt?: string; // Short summary
slug?: string; // URL-friendly identifier
url?: string; // Original URL
language?: string; // ISO language code (default: 'en')
categories?: string[];
tags?: string[];
accessLevel?: 'public' | 'authenticated' | 'premium' | 'subscription';
requiredSubscriptions?: string[]; // Required when accessLevel is 'subscription'
status?: 'draft' | 'published' | 'archived';
author?: string;
featuredImage?: string;
customFields?: Record<string, any>; // Fields defined in your content type
metadata?: Record<string, any>; // Additional custom metadata
}
Example - Public Content
curl -X POST https://app.fig1.ai/api/sdk/content \
-H "Content-Type: application/json" \
-H "X-Fig1-API-Key: fig1_sdk_abc123" \
-d '{
"externalId": "blog-123",
"type": "article",
"title": "10 Tips for Better Sleep",
"content": "<p>Getting quality sleep is essential...</p>",
"excerpt": "Improve your sleep with these science-backed tips.",
"categories": ["health", "lifestyle"],
"status": "published",
"accessLevel": "public"
}'
Example - Subscription-Gated Content
curl -X POST https://app.fig1.ai/api/sdk/content \
-H "Content-Type: application/json" \
-H "X-Fig1-API-Key: fig1_sdk_abc123" \
-d '{
"externalId": "boxing-combos-101",
"type": "article",
"title": "Advanced Boxing Combinations",
"content": "<p>Master these professional techniques...</p>",
"accessLevel": "subscription",
"requiredSubscriptions": ["boxing_fundamentals"],
"status": "published"
}'
PUT /api/sdk/content/:id
Update an existing content item.
curl -X PUT https://app.fig1.ai/api/sdk/content/content_abc123 \
-H "Content-Type: application/json" \
-H "X-Fig1-API-Key: fig1_sdk_abc123" \
-d '{
"title": "Updated Title",
"accessLevel": "subscription",
"requiredSubscriptions": ["boxing_fundamentals", "premium_content"]
}'
Updatable Fields
title,content,excerpt,slug,url,languagecategories,tagsaccessLevel,requiredSubscriptionsstatus,author,featuredImagemetadata,videoMetadata,documentMetadata,courseMetadatacollectionId
DELETE /api/sdk/content/:id
Delete a content item.
curl -X DELETE https://app.fig1.ai/api/sdk/content/content_abc123 \
-H "X-Fig1-API-Key: fig1_sdk_abc123"
Content Types
| Type | Description | Common Fields |
|------|-------------|---------------|
| article | Blog posts, news | content, author, publishedAt |
| product | E-commerce products | price, sku, inventory |
| faq | Questions & answers | question, answer |
| video | Video content | duration, streamUrl, thumbnailUrl |
| document | PDFs, docs | pageCount, fileSize, format |
| course | Educational content | lessons, duration, difficulty |
Access Levels
| Level | Description | Who Can Access |
|-------|-------------|----------------|
| public | No restrictions | Everyone |
| authenticated | Login required | Any authenticated user |
| premium | Premium membership | Premium or Pro tier users |
| subscription | Specific subscription | Users with required subscription(s) |
Subscription Access Logic
When accessLevel: 'subscription':
- User must be authenticated
- User must have at least ONE of the
requiredSubscriptions - Access rules may grant inherited access (e.g., "all_access" grants all)
Type-Specific Metadata
Video Metadata
{
type: 'video',
videoMetadata: {
duration: 3600, // seconds
streamUrl: 'https://...',
thumbnailUrl: 'https://...',
resolution: '1080p'
}
}
Document Metadata
{
type: 'document',
documentMetadata: {
pageCount: 25,
fileSize: 2048000, // bytes
format: 'pdf'
}
}
Course Metadata
{
type: 'course',
courseMetadata: {
lessons: 12,
totalDuration: 7200, // seconds
difficulty: 'intermediate',
prerequisites: ['course-101']
}
}
Syncing Content
For bulk content synchronization:
- Use
externalIdto track your content across systems - Implement upsert logic using PUT with your externalId
- Set up webhooks to sync on content changes
- Use the batch import feature in the dashboard for initial sync