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, language
  • categories, tags
  • accessLevel, requiredSubscriptions
  • status, author, featuredImage
  • metadata, videoMetadata, documentMetadata, courseMetadata
  • collectionId

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:

  1. Use externalId to track your content across systems
  2. Implement upsert logic using PUT with your externalId
  3. Set up webhooks to sync on content changes
  4. Use the batch import feature in the dashboard for initial sync