Skip to content

Analytics API Endpoints Reference

Overview

The Analytics API provides comprehensive metrics, data enrichment, and analytics capabilities for admin dashboards and chat log management.

Base URL: http://localhost:9090/api/v1/analytics

Version: 0.2.0 (with warehouse support)


Quick Reference

Analytics Endpoints (Warehouse-Backed)

Endpoint Method Description Performance
/all_warehouse GET NEW All analytics (warehouse) 30-50ms ⚡
/all GET All analytics (original) 300-500ms
/all_legacy GET All analytics (legacy copy) 300-500ms
/metrics/topic_counts GET Topic distribution 50-150ms
/metrics/total_interactions GET Total interaction count 20-50ms
/metrics/model_counts GET Model usage counts 50-150ms
/questions GET Unique questions 100-300ms
/answers GET Unique answers 100-300ms
/get_cats GET Available CATs < 10ms

Endpoint Details

GET /all_warehouse (New in v0.1.16)

High-performance warehouse-backed analytics endpoint - 8-10x faster than /all

Description:
Queries the analytics warehouse ({prefix}_analytics database) instead of raw logs for dramatically improved performance. Returns identical data structure to /all but with 8-10x speedup.

Query Parameters:

Parameter Type Required Description Example
catname string ✅ Yes CAT name to query craigh
startDate string ❌ No Start date (YYYY-MM-DD, inclusive) 2026-01-01
endDate string ❌ No End date (YYYY-MM-DD, exclusive) 2026-12-31
model string|array ❌ No Filter by model name(s) gpt-4o or ["gpt-4o", "claude-3"]
persona string|array ❌ No Filter by persona name(s) doctor or ["doctor", "nurse"]
topic string|array ❌ No Filter by topic label(s) Medical or ["Medical", "Academic"]
questionid string|array ❌ No Filter by question ID(s) 507f1f77bcf86cd799439011
answerid string|array ❌ No Filter by answer ID(s) 507f1f77bcf86cd799439012

Request Example:

# All data
curl "http://localhost:9090/api/v1/analytics/all_warehouse?catname=craigh"

# With date range
curl "http://localhost:9090/api/v1/analytics/all_warehouse?catname=craigh&startDate=2026-01-01&endDate=2026-12-31"

# With filters
curl "http://localhost:9090/api/v1/analytics/all_warehouse?catname=craigh&model=gpt-4o&topic=Medical"

# Multiple filters
curl "http://localhost:9090/api/v1/analytics/all_warehouse?catname=craigh&model=gpt-4o&model=claude-3&topic=Medical"

Response Structure:

{
  "total_interactions": 1143,
  "topic_counts": [
    {
      "topic": "Medical Terminology",
      "count": 158,
      "percentage": 13.82
    },
    {
      "topic": "Medical Conditions",
      "count": 127,
      "percentage": 11.11
    }
  ],
  "model_counts": [
    {
      "membership": "gpt-4o",
      "count": 856
    },
    {
      "membership": "gpt-4-turbo",
      "count": 287
    }
  ],
  "persona_counts": [
    {
      "persona": "doctor",
      "count": 456
    },
    {
      "persona": "default_value",
      "count": 687
    }
  ],
  "questions": [
    {
      "id": "507f1f77bcf86cd799439011",
      "question": "What is hypertension?",
      "count": 15
    }
  ],
  "answers": [
    {
      "id": "507f1f77bcf86cd799439012",
      "answers": "Hypertension is high blood pressure...",
      "count": 15
    }
  ],
  "performance_ms": 43.72,
  "data_source": "warehouse"
}

Response Fields:

Field Type Description
total_interactions int Total count of interactions (all filters applied)
topic_counts array Topic distribution (excludes topic filter)
model_counts array Model usage (excludes model filter)
persona_counts array Persona distribution (excludes persona filter)
questions array Unique questions with counts (excludes question filter)
answers array Unique answers with counts (excludes answer filter)
performance_ms float Server-side query execution time
data_source string Always "warehouse" for this endpoint

Selective Filtering Pattern:

Each aggregation excludes its own filter to show available options: - Filter by topic=Medical → topic_counts shows ALL topics (not just Medical) - Filter by model=gpt-4o → model_counts shows ALL models (not just gpt-4o) - total_interactions always includes ALL filters

Performance: - Typical: 30-50ms - With filters: 40-60ms - Complex queries: 50-100ms

Data Source: {prefix}_analytics.fact_interaction collection

Error Responses:

// Invalid cat name
{
  "error": "ANALYTICS-ERR-0-WAREHOUSE",
  "status": 500,
  "message": "Cat 'invalid' not found in configuration"
}

// Invalid date format
{
  "error": "ANALYTICS-ERR-0-WAREHOUSE",
  "status": 500,
  "message": "Invalid startDate format. Expected YYYY-MM-DD: ..."
}

// Invalid date range
{
  "error": "ANALYTICS-ERR-0-WAREHOUSE",
  "status": 500,
  "message": "startDate must be before endDate"
}

GET /all (Original Endpoint)

Original endpoint - queries raw logs directly (backward compatible)

Description:
Returns all analytics data in a single request. This is the original endpoint that queries MongoDB logs directly. Preserved for backward compatibility - all existing clients continue to work unchanged.

Query Parameters: Same as /all_warehouse

Response Structure: Same as /all_warehouse (minus performance_ms and data_source)

Performance: - Typical: 300-500ms - With filters: 400-600ms - Complex queries: 500-1000ms

Data Source: {prefix}_cat_data.logs collection

When to use: - Existing clients (backward compatibility) - Fallback if warehouse data is stale - Validation/comparison testing


GET /all_legacy

Legacy endpoint - copy of original /all for comparison testing

Description:
Identical to /all but with a different route name. Created for A/B testing and performance comparison. Can be removed after migration to warehouse is complete.

Query Parameters: Same as /all_warehouse

Response Structure: Same as /all (with data_source: "legacy")

Performance: Same as /all (300-500ms)

When to use: - Performance comparison testing - Migration validation - A/B testing with production traffic


GET /metrics/topic_counts

Get topic distribution for a CAT

Query Parameters:

Parameter Type Required Description
catname string ✅ Yes CAT name
startDate string ❌ No Start date (YYYY-MM-DD)
endDate string ❌ No End date (YYYY-MM-DD)

Request:

curl "http://localhost:9090/api/v1/analytics/metrics/topic_counts?catname=craigh"

Response:

{
  "topic_counts": [
    {
      "topic": "Medical Terminology",
      "count": 158,
      "percentage": 13.82
    },
    {
      "topic": "Medical Conditions",
      "count": 127,
      "percentage": 11.11
    }
  ]
}

Performance: 50-150ms


GET /metrics/total_interactions

Get total interaction count for a CAT

Query Parameters:

Parameter Type Required Description
catname string ✅ Yes CAT name
startDate string ❌ No Start date (YYYY-MM-DD)
endDate string ❌ No End date (YYYY-MM-DD)

Request:

curl "http://localhost:9090/api/v1/analytics/metrics/total_interactions?catname=craigh&startDate=2026-01-01&endDate=2026-12-31"

Response:

{
  "total_interactions": 1143
}

Performance: 20-50ms


GET /metrics/model_counts

Get model usage distribution

Query Parameters:

Parameter Type Required Description
catname string ✅ Yes CAT name
startDate string ❌ No Start date (YYYY-MM-DD)
endDate string ❌ No End date (YYYY-MM-DD)

Request:

curl "http://localhost:9090/api/v1/analytics/metrics/model_counts?catname=craigh"

Response:

{
  "model_counts": [
    {
      "membership": "gpt-4o",
      "count": 856
    },
    {
      "membership": "gpt-4-turbo",
      "count": 287
    }
  ]
}

Performance: 50-150ms


GET /questions

Get unique questions with counts

Query Parameters:

Parameter Type Required Description
catname string ✅ Yes CAT name
startDate string ❌ No Start date (YYYY-MM-DD)
endDate string ❌ No End date (YYYY-MM-DD)

Request:

curl "http://localhost:9090/api/v1/analytics/questions?catname=craigh"

Response:

{
  "questions": [
    {
      "id": "507f1f77bcf86cd799439011",
      "question": "What is hypertension?",
      "count": 15
    },
    {
      "id": "507f1f77bcf86cd799439012",
      "question": "What causes diabetes?",
      "count": 12
    }
  ]
}

Performance: 100-300ms


GET /answers

Get unique answers with counts

Query Parameters:

Parameter Type Required Description
catname string ✅ Yes CAT name
startDate string ❌ No Start date (YYYY-MM-DD)
endDate string ❌ No End date (YYYY-MM-DD)

Request:

curl "http://localhost:9090/api/v1/analytics/answers?catname=craigh"

Response:

{
  "answers": [
    {
      "id": "507f1f77bcf86cd799439012",
      "answers": "Hypertension is high blood pressure...",
      "count": 15
    },
    {
      "id": "507f1f77bcf86cd799439013",
      "answers": "Diabetes is a metabolic disorder...",
      "count": 12
    }
  ]
}

Performance: 100-300ms


GET /get_cats

Get list of available CATs

Query Parameters: None

Request:

curl "http://localhost:9090/api/v1/analytics/get_cats"

Response:

{
  "cats": ["craigh", "advisoruat", "testcat"]
}

Performance: < 10ms


Common Patterns

Date Filtering

All endpoints support optional date filtering:

# All data (no dates)
curl "http://localhost:9090/api/v1/analytics/all_warehouse?catname=craigh"

# Specific date range
curl "http://localhost:9090/api/v1/analytics/all_warehouse?catname=craigh&startDate=2026-01-01&endDate=2026-12-31"

# Open-ended (from date)
curl "http://localhost:9090/api/v1/analytics/all_warehouse?catname=craigh&startDate=2026-01-01"

# Open-ended (until date)
curl "http://localhost:9090/api/v1/analytics/all_warehouse?catname=craigh&endDate=2026-12-31"

Date format: YYYY-MM-DD
startDate: Inclusive (≥)
endDate: Exclusive (<)

Multiple Filters

Filters can be combined:

# Single model
curl "http://localhost:9090/api/v1/analytics/all_warehouse?catname=craigh&model=gpt-4o"

# Multiple models (array)
curl "http://localhost:9090/api/v1/analytics/all_warehouse?catname=craigh&model=gpt-4o&model=claude-3"

# Combined filters
curl "http://localhost:9090/api/v1/analytics/all_warehouse?catname=craigh&model=gpt-4o&topic=Medical&startDate=2026-01-01"

Selective Filtering

Each facet excludes its own filter to show available options:

# Filter by topic=Medical
# Response includes:
# - total_interactions: Only Medical topics
# - topic_counts: ALL topics (not just Medical) ← Selective exclusion
# - model_counts: ALL models (filtered by Medical topic)
# - persona_counts: ALL personas (filtered by Medical topic)

curl "http://localhost:9090/api/v1/analytics/all_warehouse?catname=craigh&topic=Medical"

This allows UIs to show "breakdown by X" while filtering by Y.


Error Handling

Common Errors

Invalid CAT name:

{
  "error": "ANALYTICS-ERR-0-WAREHOUSE",
  "status": 500,
  "message": "Cat 'invalid' not found in configuration"
}

Invalid date format:

{
  "error": "ANALYTICS-ERR-0-WAREHOUSE",
  "status": 500,
  "message": "Invalid startDate format. Expected YYYY-MM-DD: time data '2026-13-45' does not match format '%Y-%m-%d'"
}

Invalid date range:

{
  "error": "ANALYTICS-ERR-0-WAREHOUSE",
  "status": 500,
  "message": "startDate must be before endDate"
}

Missing required parameter:

{
  "detail": [
    {
      "loc": ["query", "catname"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}

HTTP Status Codes

Code Meaning Common Causes
200 Success Request completed successfully
400 Bad Request Invalid parameter format
422 Validation Error Missing required parameter
500 Internal Server Error CAT not found, database error, etc.

Migration Guide

From /all to /all_warehouse

Before:

fetch('/api/v1/analytics/all?catname=craigh')
  .then(res => res.json())
  .then(data => {
    console.log('Total:', data.total_interactions);
    console.log('Topics:', data.topic_counts);
  });

After:

fetch('/api/v1/analytics/all_warehouse?catname=craigh')
  .then(res => res.json())
  .then(data => {
    console.log('Total:', data.total_interactions);  // Same structure!
    console.log('Topics:', data.topic_counts);        // Same structure!
    console.log('Performance:', data.performance_ms); // Bonus: performance metric
    console.log('Source:', data.data_source);         // Bonus: data source indicator
  });

Changes: - ✅ URL: /all → /all_warehouse - ✅ Response structure: Identical (plus performance_ms and data_source) - ✅ Parameters: Identical - ✅ Behavior: Identical (8-10x faster!)

No breaking changes! Just update the URL.


Testing

Compare Endpoints

# Terminal 1: Start API server
pants run src/apis/analytics/integration:api_tester -- craigh

# Terminal 2: Compare performance
PANTS_CONCURRENT=True pants run src/pipelines/analytics_etl/scripts:compare_endpoints -- craigh

Manual Testing

# Test basic query
time curl "http://localhost:9090/api/v1/analytics/all_warehouse?catname=craigh" | jq .

# Test with filters
curl "http://localhost:9090/api/v1/analytics/all_warehouse?catname=craigh&model=gpt-4o&startDate=2026-01-01" | jq '.total_interactions, .performance_ms'

# Compare endpoints
curl -s "http://localhost:9090/api/v1/analytics/all_legacy?catname=craigh" | jq '.total_interactions'
curl -s "http://localhost:9090/api/v1/analytics/all_warehouse?catname=craigh" | jq '.total_interactions, .performance_ms'

Best Practices

Performance

  1. Use /all_warehouse for production - 8-10x faster
  2. Add date filters when possible - reduces data scanned
  3. Cache responses (5-15 minute TTL recommended)
  4. Use specific metrics endpoints for single-metric queries
  5. Monitor performance_ms - alert if > 100ms

Data Accuracy

  1. Remember event filtering - Only event='<prefix>_api' is included
  2. Check data_source field - Confirms warehouse vs legacy
  3. Validate totals - Compare with /all_legacy periodically
  4. Monitor ETL status - Ensure warehouse is up-to-date

Integration

  1. Migrate gradually - Switch clients one by one
  2. Keep /all_legacy as fallback - During migration period
  3. Test thoroughly - Validate all filter combinations
  4. Monitor errors - Watch for validation failures

Support

Documentation: - Warehouse Operations Guide - Performance Comparison - ETL Design

Commands:

# Start API server
pants run src/apis/analytics/integration:api_tester -- <catname>

# Compare endpoints
PANTS_CONCURRENT=True pants run src/apis/analytics/scripts:compare_endpoints -- <catname>

# Check warehouse status
pants run src/pipelines/analytics_etl/scripts:check_warehouse_status -- <catname>


Questions? Check the operations guide or performance comparison docs linked above.