# 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:

```bash
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**:

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

**Response Schema**:

```typescript
{
  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**:

```json
{
  "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)**:

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

**Request Example (With Time Series)**:

```bash
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**:

```typescript
{
  // 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)**:

```json
{
  "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)**:

```json
{
  "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**:

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

**Response Schema**:

```typescript
{
  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**:

```json
{
  "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**:

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

**Response Schema**:

```typescript
{
  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**:

```json
{
  "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):

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

**Authentication Error** (401):

```json
{
  "error": "Unauthorized"
}
```

**Server Error** (500):

```json
{
  "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:

```bash
GET /api/stats?type=engagement
```

### Growth Chart

Get 90 days of user growth by week:

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

### Activity Heatmap

Get daily activity for the past month:

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

### Content Distribution Trends

Track content type growth over 6 months:

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

### Activation Funnel

Get engagement with time series to track activation trends:

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