This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

semble / .agent / logs / 20260410_stats_api.md
14 kB

User Statistics API Documentation#

Overview#

The User Statistics API provides comprehensive analytics about user growth, engagement, activity, and content distribution. All statistics support flexible time intervals and are optimized for dashboard visualizations.

Base URL: /api/stats

Authentication: All endpoints require API key authentication via Bearer token.


Authentication#

Include your API key in the Authorization header:

Authorization: Bearer YOUR_STATS_API_KEY

Set the API key via the STATS_API_KEY environment variable.


Base Endpoint#

GET /api/stats

All statistics are accessed through this single endpoint using the type query parameter to specify the stat type.


Query Parameters#

Parameter Type Required Description Valid Values
type string Yes Type of statistics to retrieve growth, engagement, activity, breakdown
interval string No Time interval for aggregation day, week, month (default: day)
limit number No Number of intervals to return 1-365 (default: 30)
includeTimeSeries boolean No Include time series data (engagement only) true, false (default: false)

Stat Types#

1. Growth Statistics#

Description: Track user sign-ups over time with cumulative totals and period-over-period growth.

Query Parameters:

  • type=growth (required)
  • interval (optional, default: day)
  • limit (optional, default: 30)

Request Example:

curl -X GET "http://localhost:3000/api/stats?type=growth&interval=day&limit=30" \
  -H "Authorization: Bearer YOUR_STATS_API_KEY"

Response Schema:

{
  dataPoints: Array<{
    date: string; // ISO date string
    totalUsers: number; // Cumulative total users up to this date
    newUsers: number; // New users added in this period
  }>;
  currentTotal: number; // Total users as of now
  periodStart: string; // ISO date string of first data point
  periodEnd: string; // ISO date string of last data point
}

Example Response:

{
  "dataPoints": [
    {
      "date": "2026-03-11T00:00:00.000Z",
      "totalUsers": 100,
      "newUsers": 15
    },
    {
      "date": "2026-03-12T00:00:00.000Z",
      "totalUsers": 112,
      "newUsers": 12
    },
    {
      "date": "2026-03-13T00:00:00.000Z",
      "totalUsers": 125,
      "newUsers": 13
    }
  ],
  "currentTotal": 125,
  "periodStart": "2026-03-11T00:00:00.000Z",
  "periodEnd": "2026-03-13T00:00:00.000Z"
}

2. Engagement Statistics#

Description: Track active vs inactive users with detailed content breakdown. Supports optional time series data.

Note: Only counts URL cards (excludes NOTE and HIGHLIGHT cards).

Query Parameters:

  • type=engagement (required)
  • interval (optional, default: day, used if includeTimeSeries=true)
  • limit (optional, default: 30, used if includeTimeSeries=true)
  • includeTimeSeries (optional, default: false)

Request Example (Snapshot):

curl -X GET "http://localhost:3000/api/stats?type=engagement" \
  -H "Authorization: Bearer YOUR_STATS_API_KEY"

Request Example (With Time Series):

curl -X GET "http://localhost:3000/api/stats?type=engagement&includeTimeSeries=true&interval=week&limit=12" \
  -H "Authorization: Bearer YOUR_STATS_API_KEY"

Response Schema:

{
  // Snapshot data (always included)
  totalUsers: number;                    // Total registered users
  activeUsers: number;                   // Users who created any content
  inactiveUsers: number;                 // Users who signed in but created nothing

  // Activity breakdown
  usersWithCards: number;                // Users who created URL cards
  usersWithCollections: number;          // Users who created collections
  usersWithConnections: number;          // Users who created connections
  usersWithFollows: number;              // Users who followed targets
  usersWithContributions: number;        // Users who added cards to others' collections

  // Engagement metrics
  activationRate: number;                // activeUsers / totalUsers
  avgActionsPerActiveUser: number;       // Average actions per active user

  // Optional time series data (only if includeTimeSeries=true)
  dataPoints?: Array<{
    date: string;                        // ISO date string
    activeUsers: number;                 // Users activated in this period
    newlyActivatedUsers: number;         // Previously inactive users who became active
    cumulativeActiveUsers: number;       // Total active users up to this date
  }>;
}

Example Response (Snapshot):

{
  "totalUsers": 500,
  "activeUsers": 320,
  "inactiveUsers": 180,
  "usersWithCards": 280,
  "usersWithCollections": 150,
  "usersWithConnections": 90,
  "usersWithFollows": 200,
  "usersWithContributions": 45,
  "activationRate": 0.64,
  "avgActionsPerActiveUser": 12.5
}

Example Response (With Time Series):

{
  "totalUsers": 500,
  "activeUsers": 320,
  "inactiveUsers": 180,
  "usersWithCards": 280,
  "usersWithCollections": 150,
  "usersWithConnections": 90,
  "usersWithFollows": 200,
  "usersWithContributions": 45,
  "activationRate": 0.64,
  "avgActionsPerActiveUser": 12.5,
  "dataPoints": [
    {
      "date": "2026-03-01T00:00:00.000Z",
      "activeUsers": 25,
      "newlyActivatedUsers": 25,
      "cumulativeActiveUsers": 275
    },
    {
      "date": "2026-03-08T00:00:00.000Z",
      "activeUsers": 30,
      "newlyActivatedUsers": 30,
      "cumulativeActiveUsers": 305
    },
    {
      "date": "2026-03-15T00:00:00.000Z",
      "activeUsers": 15,
      "newlyActivatedUsers": 15,
      "cumulativeActiveUsers": 320
    }
  ]
}

3. Activity Statistics#

Description: Track daily content creation volume across all content types.

Note: Only counts URL cards (excludes NOTE and HIGHLIGHT cards).

Query Parameters:

  • type=activity (required)
  • interval (optional, default: day)
  • limit (optional, default: 30)

Request Example:

curl -X GET "http://localhost:3000/api/stats?type=activity&interval=day&limit=7" \
  -H "Authorization: Bearer YOUR_STATS_API_KEY"

Response Schema:

{
  dataPoints: Array<{
    date: string; // ISO date string
    cardsCreated: number; // URL cards created in this period
    collectionsCreated: number; // Collections created in this period
    connectionsCreated: number; // Connections created in this period
    followsCreated: number; // Follows created in this period
    totalActions: number; // Sum of all above
  }>;
  totals: {
    cardsCreated: number; // Total across all periods
    collectionsCreated: number; // Total across all periods
    connectionsCreated: number; // Total across all periods
    followsCreated: number; // Total across all periods
    totalActions: number; // Sum of all totals
  }
  periodStart: string; // ISO date string of first data point
  periodEnd: string; // ISO date string of last data point
}

Example Response:

{
  "dataPoints": [
    {
      "date": "2026-04-08T00:00:00.000Z",
      "cardsCreated": 45,
      "collectionsCreated": 12,
      "connectionsCreated": 8,
      "followsCreated": 23,
      "totalActions": 88
    },
    {
      "date": "2026-04-09T00:00:00.000Z",
      "cardsCreated": 52,
      "collectionsCreated": 15,
      "connectionsCreated": 10,
      "followsCreated": 28,
      "totalActions": 105
    },
    {
      "date": "2026-04-10T00:00:00.000Z",
      "cardsCreated": 38,
      "collectionsCreated": 9,
      "connectionsCreated": 6,
      "followsCreated": 19,
      "totalActions": 72
    }
  ],
  "totals": {
    "cardsCreated": 135,
    "collectionsCreated": 36,
    "connectionsCreated": 24,
    "followsCreated": 70,
    "totalActions": 265
  },
  "periodStart": "2026-04-08T00:00:00.000Z",
  "periodEnd": "2026-04-10T00:00:00.000Z"
}

4. Breakdown Statistics#

Description: Track content distribution by subtypes over time. Shows cumulative growth of different content categories.

Breakdowns:

  • URL cards by urlType (article, video, tool, etc.)
  • Collections by accessType (OPEN, CLOSED)
  • Connections by connectionType (SUPPORTS, OPPOSES, unspecified)

Note: Only counts URL cards (excludes NOTE and HIGHLIGHT cards).

Query Parameters:

  • type=breakdown (required)
  • interval (optional, default: day)
  • limit (optional, default: 30)

Request Example:

curl -X GET "http://localhost:3000/api/stats?type=breakdown&interval=week&limit=4" \
  -H "Authorization: Bearer YOUR_STATS_API_KEY"

Response Schema:

{
  dataPoints: Array<{
    date: string; // ISO date string
    urlCards: {
      total: number; // Total URL cards at this date
      byType: Record<string, number>; // Breakdown by urlType
    };
    collections: {
      total: number; // Total collections at this date
      byAccessType: Record<string, number>; // Breakdown by accessType
    };
    connections: {
      total: number; // Total connections at this date
      byType: Record<string, number>; // Breakdown by connectionType
    };
  }>;
  currentTotals: {
    urlCards: {
      total: number; // Current total URL cards
      byType: Record<string, number>; // Current breakdown by urlType
    }
    collections: {
      total: number; // Current total collections
      byAccessType: Record<string, number>; // Current breakdown by accessType
    }
    connections: {
      total: number; // Current total connections
      byType: Record<string, number>; // Current breakdown by connectionType
    }
  }
  periodStart: string; // ISO date string of first data point
  periodEnd: string; // ISO date string of last data point
}

Example Response:

{
  "dataPoints": [
    {
      "date": "2026-03-17T00:00:00.000Z",
      "urlCards": {
        "total": 450,
        "byType": {
          "article": 180,
          "video": 120,
          "tool": 90,
          "unspecified": 60
        }
      },
      "collections": {
        "total": 85,
        "byAccessType": {
          "OPEN": 60,
          "CLOSED": 25
        }
      },
      "connections": {
        "total": 120,
        "byType": {
          "SUPPORTS": 70,
          "OPPOSES": 30,
          "unspecified": 20
        }
      }
    },
    {
      "date": "2026-03-24T00:00:00.000Z",
      "urlCards": {
        "total": 520,
        "byType": {
          "article": 210,
          "video": 140,
          "tool": 105,
          "unspecified": 65
        }
      },
      "collections": {
        "total": 98,
        "byAccessType": {
          "OPEN": 72,
          "CLOSED": 26
        }
      },
      "connections": {
        "total": 145,
        "byType": {
          "SUPPORTS": 85,
          "OPPOSES": 38,
          "unspecified": 22
        }
      }
    }
  ],
  "currentTotals": {
    "urlCards": {
      "total": 520,
      "byType": {
        "article": 210,
        "video": 140,
        "tool": 105,
        "unspecified": 65
      }
    },
    "collections": {
      "total": 98,
      "byAccessType": {
        "OPEN": 72,
        "CLOSED": 26
      }
    },
    "connections": {
      "total": 145,
      "byType": {
        "SUPPORTS": 85,
        "OPPOSES": 38,
        "unspecified": 22
      }
    }
  },
  "periodStart": "2026-03-17T00:00:00.000Z",
  "periodEnd": "2026-03-24T00:00:00.000Z"
}

Error Responses#

All endpoints return standard error responses:

Validation Error (400):

{
  "error": "Stat type is required"
}

Authentication Error (401):

{
  "error": "Unauthorized"
}

Server Error (500):

{
  "error": "Failed to retrieve user stats: <error message>"
}

Implementation Notes#

Card Counting#

  • Important: All card counts refer exclusively to URL cards
  • NOTE cards and HIGHLIGHT cards are excluded from all statistics
  • This applies to: engagement stats, activity stats, and breakdown stats

Time Intervals#

  • day: Data aggregated by calendar day
  • week: Data aggregated by calendar week (starts Monday)
  • month: Data aggregated by calendar month

Data Points Ordering#

  • All time series data is returned in chronological order (oldest to newest)
  • This makes it easy to render charts and track trends over time

Performance#

  • Queries are optimized with indexes on relevant columns
  • Large date ranges (limit > 100) may take longer to compute
  • Breakdown stats execute three queries in parallel for better performance

Null Handling#

  • Null values in urlType and connectionType are mapped to "unspecified"
  • This ensures consistent data structure in breakdown responses

Common Use Cases#

Dashboard Overview#

Get current engagement snapshot:

GET /api/stats?type=engagement

Growth Chart#

Get 90 days of user growth by week:

GET /api/stats?type=growth&interval=week&limit=13

Activity Heatmap#

Get daily activity for the past month:

GET /api/stats?type=activity&interval=day&limit=30

Track content type growth over 6 months:

GET /api/stats?type=breakdown&interval=month&limit=6

Activation Funnel#

Get engagement with time series to track activation trends:

GET /api/stats?type=engagement&includeTimeSeries=true&interval=week&limit=12