This repository has no description
0

Configure Feed

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

stats usage api docs

+567
+567
.agent/logs/20260410_stats_api.md
··· 1 + # User Statistics API Documentation 2 + 3 + ## Overview 4 + 5 + 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. 6 + 7 + **Base URL**: `/api/stats` 8 + 9 + **Authentication**: All endpoints require API key authentication via Bearer token. 10 + 11 + --- 12 + 13 + ## Authentication 14 + 15 + Include your API key in the `Authorization` header: 16 + 17 + ```bash 18 + Authorization: Bearer YOUR_STATS_API_KEY 19 + ``` 20 + 21 + Set the API key via the `STATS_API_KEY` environment variable. 22 + 23 + --- 24 + 25 + ## Base Endpoint 26 + 27 + ``` 28 + GET /api/stats 29 + ``` 30 + 31 + All statistics are accessed through this single endpoint using the `type` query parameter to specify the stat type. 32 + 33 + --- 34 + 35 + ## Query Parameters 36 + 37 + | Parameter | Type | Required | Description | Valid Values | 38 + | ------------------- | ------- | -------- | ------------------------------------------ | ----------------------------------------------- | 39 + | `type` | string | Yes | Type of statistics to retrieve | `growth`, `engagement`, `activity`, `breakdown` | 40 + | `interval` | string | No | Time interval for aggregation | `day`, `week`, `month` (default: `day`) | 41 + | `limit` | number | No | Number of intervals to return | 1-365 (default: 30) | 42 + | `includeTimeSeries` | boolean | No | Include time series data (engagement only) | `true`, `false` (default: `false`) | 43 + 44 + --- 45 + 46 + ## Stat Types 47 + 48 + ### 1. Growth Statistics 49 + 50 + **Description**: Track user sign-ups over time with cumulative totals and period-over-period growth. 51 + 52 + **Query Parameters**: 53 + 54 + - `type=growth` (required) 55 + - `interval` (optional, default: `day`) 56 + - `limit` (optional, default: 30) 57 + 58 + **Request Example**: 59 + 60 + ```bash 61 + curl -X GET "http://localhost:3000/api/stats?type=growth&interval=day&limit=30" \ 62 + -H "Authorization: Bearer YOUR_STATS_API_KEY" 63 + ``` 64 + 65 + **Response Schema**: 66 + 67 + ```typescript 68 + { 69 + dataPoints: Array<{ 70 + date: string; // ISO date string 71 + totalUsers: number; // Cumulative total users up to this date 72 + newUsers: number; // New users added in this period 73 + }>; 74 + currentTotal: number; // Total users as of now 75 + periodStart: string; // ISO date string of first data point 76 + periodEnd: string; // ISO date string of last data point 77 + } 78 + ``` 79 + 80 + **Example Response**: 81 + 82 + ```json 83 + { 84 + "dataPoints": [ 85 + { 86 + "date": "2026-03-11T00:00:00.000Z", 87 + "totalUsers": 100, 88 + "newUsers": 15 89 + }, 90 + { 91 + "date": "2026-03-12T00:00:00.000Z", 92 + "totalUsers": 112, 93 + "newUsers": 12 94 + }, 95 + { 96 + "date": "2026-03-13T00:00:00.000Z", 97 + "totalUsers": 125, 98 + "newUsers": 13 99 + } 100 + ], 101 + "currentTotal": 125, 102 + "periodStart": "2026-03-11T00:00:00.000Z", 103 + "periodEnd": "2026-03-13T00:00:00.000Z" 104 + } 105 + ``` 106 + 107 + --- 108 + 109 + ### 2. Engagement Statistics 110 + 111 + **Description**: Track active vs inactive users with detailed content breakdown. Supports optional time series data. 112 + 113 + **Note**: Only counts URL cards (excludes NOTE and HIGHLIGHT cards). 114 + 115 + **Query Parameters**: 116 + 117 + - `type=engagement` (required) 118 + - `interval` (optional, default: `day`, used if `includeTimeSeries=true`) 119 + - `limit` (optional, default: 30, used if `includeTimeSeries=true`) 120 + - `includeTimeSeries` (optional, default: `false`) 121 + 122 + **Request Example (Snapshot)**: 123 + 124 + ```bash 125 + curl -X GET "http://localhost:3000/api/stats?type=engagement" \ 126 + -H "Authorization: Bearer YOUR_STATS_API_KEY" 127 + ``` 128 + 129 + **Request Example (With Time Series)**: 130 + 131 + ```bash 132 + curl -X GET "http://localhost:3000/api/stats?type=engagement&includeTimeSeries=true&interval=week&limit=12" \ 133 + -H "Authorization: Bearer YOUR_STATS_API_KEY" 134 + ``` 135 + 136 + **Response Schema**: 137 + 138 + ```typescript 139 + { 140 + // Snapshot data (always included) 141 + totalUsers: number; // Total registered users 142 + activeUsers: number; // Users who created any content 143 + inactiveUsers: number; // Users who signed in but created nothing 144 + 145 + // Activity breakdown 146 + usersWithCards: number; // Users who created URL cards 147 + usersWithCollections: number; // Users who created collections 148 + usersWithConnections: number; // Users who created connections 149 + usersWithFollows: number; // Users who followed targets 150 + usersWithContributions: number; // Users who added cards to others' collections 151 + 152 + // Engagement metrics 153 + activationRate: number; // activeUsers / totalUsers 154 + avgActionsPerActiveUser: number; // Average actions per active user 155 + 156 + // Optional time series data (only if includeTimeSeries=true) 157 + dataPoints?: Array<{ 158 + date: string; // ISO date string 159 + activeUsers: number; // Users activated in this period 160 + newlyActivatedUsers: number; // Previously inactive users who became active 161 + cumulativeActiveUsers: number; // Total active users up to this date 162 + }>; 163 + } 164 + ``` 165 + 166 + **Example Response (Snapshot)**: 167 + 168 + ```json 169 + { 170 + "totalUsers": 500, 171 + "activeUsers": 320, 172 + "inactiveUsers": 180, 173 + "usersWithCards": 280, 174 + "usersWithCollections": 150, 175 + "usersWithConnections": 90, 176 + "usersWithFollows": 200, 177 + "usersWithContributions": 45, 178 + "activationRate": 0.64, 179 + "avgActionsPerActiveUser": 12.5 180 + } 181 + ``` 182 + 183 + **Example Response (With Time Series)**: 184 + 185 + ```json 186 + { 187 + "totalUsers": 500, 188 + "activeUsers": 320, 189 + "inactiveUsers": 180, 190 + "usersWithCards": 280, 191 + "usersWithCollections": 150, 192 + "usersWithConnections": 90, 193 + "usersWithFollows": 200, 194 + "usersWithContributions": 45, 195 + "activationRate": 0.64, 196 + "avgActionsPerActiveUser": 12.5, 197 + "dataPoints": [ 198 + { 199 + "date": "2026-03-01T00:00:00.000Z", 200 + "activeUsers": 25, 201 + "newlyActivatedUsers": 25, 202 + "cumulativeActiveUsers": 275 203 + }, 204 + { 205 + "date": "2026-03-08T00:00:00.000Z", 206 + "activeUsers": 30, 207 + "newlyActivatedUsers": 30, 208 + "cumulativeActiveUsers": 305 209 + }, 210 + { 211 + "date": "2026-03-15T00:00:00.000Z", 212 + "activeUsers": 15, 213 + "newlyActivatedUsers": 15, 214 + "cumulativeActiveUsers": 320 215 + } 216 + ] 217 + } 218 + ``` 219 + 220 + --- 221 + 222 + ### 3. Activity Statistics 223 + 224 + **Description**: Track daily content creation volume across all content types. 225 + 226 + **Note**: Only counts URL cards (excludes NOTE and HIGHLIGHT cards). 227 + 228 + **Query Parameters**: 229 + 230 + - `type=activity` (required) 231 + - `interval` (optional, default: `day`) 232 + - `limit` (optional, default: 30) 233 + 234 + **Request Example**: 235 + 236 + ```bash 237 + curl -X GET "http://localhost:3000/api/stats?type=activity&interval=day&limit=7" \ 238 + -H "Authorization: Bearer YOUR_STATS_API_KEY" 239 + ``` 240 + 241 + **Response Schema**: 242 + 243 + ```typescript 244 + { 245 + dataPoints: Array<{ 246 + date: string; // ISO date string 247 + cardsCreated: number; // URL cards created in this period 248 + collectionsCreated: number; // Collections created in this period 249 + connectionsCreated: number; // Connections created in this period 250 + followsCreated: number; // Follows created in this period 251 + totalActions: number; // Sum of all above 252 + }>; 253 + totals: { 254 + cardsCreated: number; // Total across all periods 255 + collectionsCreated: number; // Total across all periods 256 + connectionsCreated: number; // Total across all periods 257 + followsCreated: number; // Total across all periods 258 + totalActions: number; // Sum of all totals 259 + } 260 + periodStart: string; // ISO date string of first data point 261 + periodEnd: string; // ISO date string of last data point 262 + } 263 + ``` 264 + 265 + **Example Response**: 266 + 267 + ```json 268 + { 269 + "dataPoints": [ 270 + { 271 + "date": "2026-04-08T00:00:00.000Z", 272 + "cardsCreated": 45, 273 + "collectionsCreated": 12, 274 + "connectionsCreated": 8, 275 + "followsCreated": 23, 276 + "totalActions": 88 277 + }, 278 + { 279 + "date": "2026-04-09T00:00:00.000Z", 280 + "cardsCreated": 52, 281 + "collectionsCreated": 15, 282 + "connectionsCreated": 10, 283 + "followsCreated": 28, 284 + "totalActions": 105 285 + }, 286 + { 287 + "date": "2026-04-10T00:00:00.000Z", 288 + "cardsCreated": 38, 289 + "collectionsCreated": 9, 290 + "connectionsCreated": 6, 291 + "followsCreated": 19, 292 + "totalActions": 72 293 + } 294 + ], 295 + "totals": { 296 + "cardsCreated": 135, 297 + "collectionsCreated": 36, 298 + "connectionsCreated": 24, 299 + "followsCreated": 70, 300 + "totalActions": 265 301 + }, 302 + "periodStart": "2026-04-08T00:00:00.000Z", 303 + "periodEnd": "2026-04-10T00:00:00.000Z" 304 + } 305 + ``` 306 + 307 + --- 308 + 309 + ### 4. Breakdown Statistics 310 + 311 + **Description**: Track content distribution by subtypes over time. Shows cumulative growth of different content categories. 312 + 313 + **Breakdowns**: 314 + 315 + - URL cards by `urlType` (article, video, tool, etc.) 316 + - Collections by `accessType` (OPEN, CLOSED) 317 + - Connections by `connectionType` (SUPPORTS, OPPOSES, unspecified) 318 + 319 + **Note**: Only counts URL cards (excludes NOTE and HIGHLIGHT cards). 320 + 321 + **Query Parameters**: 322 + 323 + - `type=breakdown` (required) 324 + - `interval` (optional, default: `day`) 325 + - `limit` (optional, default: 30) 326 + 327 + **Request Example**: 328 + 329 + ```bash 330 + curl -X GET "http://localhost:3000/api/stats?type=breakdown&interval=week&limit=4" \ 331 + -H "Authorization: Bearer YOUR_STATS_API_KEY" 332 + ``` 333 + 334 + **Response Schema**: 335 + 336 + ```typescript 337 + { 338 + dataPoints: Array<{ 339 + date: string; // ISO date string 340 + urlCards: { 341 + total: number; // Total URL cards at this date 342 + byType: Record<string, number>; // Breakdown by urlType 343 + }; 344 + collections: { 345 + total: number; // Total collections at this date 346 + byAccessType: Record<string, number>; // Breakdown by accessType 347 + }; 348 + connections: { 349 + total: number; // Total connections at this date 350 + byType: Record<string, number>; // Breakdown by connectionType 351 + }; 352 + }>; 353 + currentTotals: { 354 + urlCards: { 355 + total: number; // Current total URL cards 356 + byType: Record<string, number>; // Current breakdown by urlType 357 + } 358 + collections: { 359 + total: number; // Current total collections 360 + byAccessType: Record<string, number>; // Current breakdown by accessType 361 + } 362 + connections: { 363 + total: number; // Current total connections 364 + byType: Record<string, number>; // Current breakdown by connectionType 365 + } 366 + } 367 + periodStart: string; // ISO date string of first data point 368 + periodEnd: string; // ISO date string of last data point 369 + } 370 + ``` 371 + 372 + **Example Response**: 373 + 374 + ```json 375 + { 376 + "dataPoints": [ 377 + { 378 + "date": "2026-03-17T00:00:00.000Z", 379 + "urlCards": { 380 + "total": 450, 381 + "byType": { 382 + "article": 180, 383 + "video": 120, 384 + "tool": 90, 385 + "unspecified": 60 386 + } 387 + }, 388 + "collections": { 389 + "total": 85, 390 + "byAccessType": { 391 + "OPEN": 60, 392 + "CLOSED": 25 393 + } 394 + }, 395 + "connections": { 396 + "total": 120, 397 + "byType": { 398 + "SUPPORTS": 70, 399 + "OPPOSES": 30, 400 + "unspecified": 20 401 + } 402 + } 403 + }, 404 + { 405 + "date": "2026-03-24T00:00:00.000Z", 406 + "urlCards": { 407 + "total": 520, 408 + "byType": { 409 + "article": 210, 410 + "video": 140, 411 + "tool": 105, 412 + "unspecified": 65 413 + } 414 + }, 415 + "collections": { 416 + "total": 98, 417 + "byAccessType": { 418 + "OPEN": 72, 419 + "CLOSED": 26 420 + } 421 + }, 422 + "connections": { 423 + "total": 145, 424 + "byType": { 425 + "SUPPORTS": 85, 426 + "OPPOSES": 38, 427 + "unspecified": 22 428 + } 429 + } 430 + } 431 + ], 432 + "currentTotals": { 433 + "urlCards": { 434 + "total": 520, 435 + "byType": { 436 + "article": 210, 437 + "video": 140, 438 + "tool": 105, 439 + "unspecified": 65 440 + } 441 + }, 442 + "collections": { 443 + "total": 98, 444 + "byAccessType": { 445 + "OPEN": 72, 446 + "CLOSED": 26 447 + } 448 + }, 449 + "connections": { 450 + "total": 145, 451 + "byType": { 452 + "SUPPORTS": 85, 453 + "OPPOSES": 38, 454 + "unspecified": 22 455 + } 456 + } 457 + }, 458 + "periodStart": "2026-03-17T00:00:00.000Z", 459 + "periodEnd": "2026-03-24T00:00:00.000Z" 460 + } 461 + ``` 462 + 463 + --- 464 + 465 + ## Error Responses 466 + 467 + All endpoints return standard error responses: 468 + 469 + **Validation Error** (400): 470 + 471 + ```json 472 + { 473 + "error": "Stat type is required" 474 + } 475 + ``` 476 + 477 + **Authentication Error** (401): 478 + 479 + ```json 480 + { 481 + "error": "Unauthorized" 482 + } 483 + ``` 484 + 485 + **Server Error** (500): 486 + 487 + ```json 488 + { 489 + "error": "Failed to retrieve user stats: <error message>" 490 + } 491 + ``` 492 + 493 + --- 494 + 495 + ## Implementation Notes 496 + 497 + ### Card Counting 498 + 499 + - **Important**: All card counts refer exclusively to URL cards 500 + - NOTE cards and HIGHLIGHT cards are excluded from all statistics 501 + - This applies to: engagement stats, activity stats, and breakdown stats 502 + 503 + ### Time Intervals 504 + 505 + - `day`: Data aggregated by calendar day 506 + - `week`: Data aggregated by calendar week (starts Monday) 507 + - `month`: Data aggregated by calendar month 508 + 509 + ### Data Points Ordering 510 + 511 + - All time series data is returned in **chronological order** (oldest to newest) 512 + - This makes it easy to render charts and track trends over time 513 + 514 + ### Performance 515 + 516 + - Queries are optimized with indexes on relevant columns 517 + - Large date ranges (limit > 100) may take longer to compute 518 + - Breakdown stats execute three queries in parallel for better performance 519 + 520 + ### Null Handling 521 + 522 + - Null values in `urlType` and `connectionType` are mapped to `"unspecified"` 523 + - This ensures consistent data structure in breakdown responses 524 + 525 + --- 526 + 527 + ## Common Use Cases 528 + 529 + ### Dashboard Overview 530 + 531 + Get current engagement snapshot: 532 + 533 + ```bash 534 + GET /api/stats?type=engagement 535 + ``` 536 + 537 + ### Growth Chart 538 + 539 + Get 90 days of user growth by week: 540 + 541 + ```bash 542 + GET /api/stats?type=growth&interval=week&limit=13 543 + ``` 544 + 545 + ### Activity Heatmap 546 + 547 + Get daily activity for the past month: 548 + 549 + ```bash 550 + GET /api/stats?type=activity&interval=day&limit=30 551 + ``` 552 + 553 + ### Content Distribution Trends 554 + 555 + Track content type growth over 6 months: 556 + 557 + ```bash 558 + GET /api/stats?type=breakdown&interval=month&limit=6 559 + ``` 560 + 561 + ### Activation Funnel 562 + 563 + Get engagement with time series to track activation trends: 564 + 565 + ```bash 566 + GET /api/stats?type=engagement&includeTimeSeries=true&interval=week&limit=12 567 + ```