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:
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:
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:
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:
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:
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:
Response:
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¶
- Use
/all_warehousefor production - 8-10x faster - Add date filters when possible - reduces data scanned
- Cache responses (5-15 minute TTL recommended)
- Use specific metrics endpoints for single-metric queries
- Monitor
performance_ms- alert if > 100ms
Data Accuracy¶
- Remember event filtering - Only
event='<prefix>_api'is included - Check
data_sourcefield - Confirms warehouse vs legacy - Validate totals - Compare with
/all_legacyperiodically - Monitor ETL status - Ensure warehouse is up-to-date
Integration¶
- Migrate gradually - Switch clients one by one
- Keep
/all_legacyas fallback - During migration period - Test thoroughly - Validate all filter combinations
- 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.