Documentation Index
Fetch the complete documentation index at: https://docs.kaireonai.com/llms.txt
Use this file to discover all available pages before exploring further.
The Dashboard Data API provides pre-aggregated analytics for the platform’s monitoring dashboards. Data is aggregated via SQL to avoid loading large result sets.
GET /api/v1/dashboard-data
Retrieve dashboard data by type.
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|
type | string | No | summary | Data type to retrieve (see table below) |
days | integer | No | 7 | Lookback window in days (1-365), used by time-based types |
modelId | string | No | — | Algorithm model ID (only for model_metrics_trend) |
groupBy | string | No | channel for offer_performance_grouped, null for score_distribution | Grouping dimension. Accepts channel, category, or segment for offer_performance_grouped; channel, offer, or category for score_distribution |
filterId | string | No | — | Filter by dimension ID (only for score_distribution) |
segmentId | string | No | — | Restrict the result to customers in the given segment. Accepted by acceptance_rate, offer_performance, offer_performance_grouped, channel_effectiveness, daily_trend, revenue_trend, selection_frequency, and why_not_ranked. Returns {"data": [], "warning": "..."} when the segment does not exist or the segment view has not been materialized yet. |
channelId | string | No | — | Restrict selection_frequency to decisions made on a specific channel. |
categoryId | string | No | — | Restrict selection_frequency to offers in a specific category. |
decisionFlowId | string | No | — | Restrict selection_frequency to decisions produced by a specific decision flow. |
offerId | string | Required for why_not_ranked | — | Target offer for the why-not analysis. |
baselineDays | integer | No | same as days | For anomaly_candidates — the length of the prior-period window compared against the current window. |
Data Types
| Type | Description |
|---|
summary | High-level counts: active offers, channels, experiments, journeys, triggers, pending approvals |
acceptance_rate | Acceptance rate per offer (impressions vs positive outcomes) over days window |
offer_performance | Top 20 active offers with impressions, conversions, revenue, and conversion rate |
channel_effectiveness | Impressions, conversions, and effectiveness rate per channel |
budget_burn | Budget allocation utilization: allocated, spent, remaining, burn rate |
funnel | Offer funnel stages: total offers, active, with creatives, total creatives |
attribution_summary | Attribution results grouped by model with conversion counts and total value |
daily_trend | 7-day trend of impressions and conversions |
model_metrics_trend | AUC trend and feature importance from algorithm models (accepts modelId) |
latency_trend | 7-day p50/p99 latency percentiles from run execution data |
offer_performance_grouped | Offer performance grouped by channel or category (accepts groupBy) |
revenue_trend | Daily revenue trend from interaction summaries over days window |
policy_impact | Active suppressions grouped by policy type with counts |
score_distribution | Propensity score histogram from decision traces (accepts groupBy and filterId) |
degraded_scoring | Count of degraded scoring events (fallback scoring used due to model errors or timeouts) |
selection_frequency | Per-offer eligible / scored / selected counts, selection rate, average rank, and rank distribution over the window |
anomaly_candidates | Core-metric anomalies (acceptance rate, revenue, degraded scoring rate) vs a prior-period baseline — stateless; no alert firing |
why_not_ranked | For a target offerId, breakdown of how often the offer was eligible but not selected and the top reasons |
Response — summary
{
"activeOffers": 15,
"activeChannels": 4,
"activeExperiments": 2,
"totalJourneys": 3,
"activeTriggers": 5,
"pendingApprovals": 1
}
Response — acceptance_rate
{
"data": [
{
"offerId": "off_001",
"offerName": "Premium Card Upgrade",
"impressions": 1250,
"positive": 87,
"negative": 45,
"acceptanceRate": 0.0696
}
],
"total": 15,
"period": {
"days": 7,
"since": "2026-03-23T00:00:00.000Z"
}
}
{
"data": [
{
"offerId": "off_001",
"name": "Premium Card Upgrade",
"priority": 90,
"creativeCount": 3,
"impressions": 1250,
"conversions": 87,
"revenue": 4350.00,
"conversionRate": "7.0"
}
]
}
Response — channel_effectiveness
{
"data": [
{
"channelId": "ch_001",
"channelName": "Marketing Email",
"impressions": 5000,
"conversions": 350,
"effectiveness": "7.0"
}
]
}
Response — budget_burn
{
"data": [
{
"offerId": "off_001",
"allocated": 10000,
"spent": 4500,
"remaining": 5500,
"burnRate": "45.0"
}
]
}
Response — funnel
{
"stages": [
{ "label": "Total Offers", "count": 25 },
{ "label": "Active Offers", "count": 15 },
{ "label": "With Creatives", "count": 12 },
{ "label": "Creatives", "count": 34 }
]
}
Response — attribution_summary
{
"data": [
{
"model": "last_touch",
"conversions": 150,
"totalValue": 45000.00,
"avgValue": 300.00
}
],
"totalConversions": 150
}
Response — daily_trend
{
"data": [
{ "name": "Mar 24", "impressions": 340, "conversions": 22 },
{ "name": "Mar 25", "impressions": 420, "conversions": 31 },
{ "name": "Mar 26", "impressions": 380, "conversions": 28 }
]
}
Response — model_metrics_trend
{
"aucTrend": [
{ "name": "Mar 15", "auc": 0.82 },
{ "name": "Mar 16", "auc": 0.84 }
],
"featureImportance": [
{ "name": "tenure_months", "value": 0.32 },
{ "name": "monthly_spend", "value": 0.28 }
],
"modelCount": 2,
"modelName": "Propensity to Buy"
}
Response — latency_trend
{
"data": [
{ "name": "Mon", "p50": 45, "p99": 220 },
{ "name": "Tue", "p50": 42, "p99": 195 }
],
"hasRealData": true
}
{
"groups": [
{
"groupName": "Marketing Email",
"groupId": "ch_001",
"offers": [
{
"offerId": "off_001",
"name": "Premium Card Upgrade",
"impressions": 1250,
"conversions": 87,
"revenue": 4350.00,
"conversionRate": "7.0"
}
]
}
],
"groupBy": "channel"
}
Response — revenue_trend
{
"data": [
{ "name": "Mar 1", "revenue": 1200.50 },
{ "name": "Mar 2", "revenue": 980.00 }
],
"hasRealData": true
}
Response — policy_impact
{
"data": [
{ "policyType": "frequency_cap", "count": 45 },
{ "policyType": "cooldown", "count": 12 }
],
"totalActive": 57
}
Response — score_distribution
{
"data": [
{ "name": "0.0-0.1", "count": 15 },
{ "name": "0.1-0.2", "count": 22 },
{ "name": "0.2-0.3", "count": 38 },
{ "name": "0.3-0.4", "count": 45 },
{ "name": "0.4-0.5", "count": 52 },
{ "name": "0.5-0.6", "count": 67 },
{ "name": "0.6-0.7", "count": 48 },
{ "name": "0.7-0.8", "count": 35 },
{ "name": "0.8-0.9", "count": 20 },
{ "name": "0.9-1.0", "count": 8 }
],
"totalScores": 350,
"hasRealData": true,
"groupBy": null,
"dimensionBuckets": [
{
"name": "ch_001",
"dimName": "Marketing Email",
"count": 200,
"avgScore": 0.542
}
]
}
The score_distribution type accepts groupBy values of channel, offer, or category to break down scores by dimension. Use filterId to show only scores for a specific dimension value.
Response — degraded_scoring
{
"degradedCount": 3,
"totalCount": 1250,
"days": 7,
"hasData": true
}
Returns the count of recommend calls where the scoring engine fell back to degraded mode (e.g., model timeout, missing data). totalCount is the total number of scored requests in the period.
Response — selection_frequency
{
"data": [
{
"offerId": "off_premium_card",
"offerName": "Premium Card Upgrade",
"eligibleCount": 340,
"scoredCount": 340,
"selectedCount": 48,
"selectionRate": 0.141,
"avgRank": 2.3,
"rankDistribution": [48, 112, 85, 42, 30, 15, 6, 2, 0, 0]
}
],
"totalTraces": 412,
"period": { "days": 7, "since": "2026-03-23T00:00:00.000Z" }
}
Aggregates DecisionTrace.scoringResults[] and selectedOffers[] across the window. The trace sample is capped at 10,000 rows per call for latency. rankDistribution is a 10-element array covering ranks 1..10; ranks beyond 10 are not tracked. Supports optional channelId, categoryId, decisionFlowId, and segmentId filters.
Example:
curl -H "X-API-Key: $API_KEY" -H "X-Tenant-Id: $TENANT_ID" \
"https://playground.kaireonai.com/api/v1/dashboard-data?type=selection_frequency&days=14&segmentId=seg_vip"
Response — anomaly_candidates
{
"data": [
{
"metric": "acceptance_rate",
"dimension": "offer",
"dimensionKey": "off_premium_card",
"dimensionName": "Premium Card Upgrade",
"baseline": 0.102,
"current": 0.184,
"deltaPct": 80.4,
"zscore": 4.3,
"severity": "critical"
}
],
"period": {
"currentDays": 7,
"baselineDays": 7,
"since": "2026-03-23T00:00:00.000Z"
}
}
Severity is classified by the larger of the z-score magnitude and the absolute percent change: info at |z| >= 2 or |%| >= 15, warning at |z| >= 3 or |%| >= 30, critical at |z| >= 4 or |%| >= 50. Metrics covered: acceptance_rate (overall, per-offer, per-channel), revenue (per-offer), and degraded_scoring_rate (overall). This endpoint is stateless — it does not fire alerts; it surfaces candidates that a scheduler in a later phase may escalate.
Example:
curl -H "X-API-Key: $API_KEY" -H "X-Tenant-Id: $TENANT_ID" \
"https://playground.kaireonai.com/api/v1/dashboard-data?type=anomaly_candidates&days=7&baselineDays=7"
Response — why_not_ranked
{
"offerId": "off_premium_card",
"offerName": "Premium Card Upgrade",
"timesEligible": 340,
"timesSelected": 48,
"missRate": 0.859,
"missReasons": {
"scoredTooLow": 220,
"filteredByContactPolicy": 45,
"filteredByQualification": 27,
"beatenBy": [
{ "offerId": "off_gold_plus", "offerName": "Gold Plus", "count": 102 },
{ "offerId": "off_starter", "offerName": "Starter Card", "count": 48 }
]
},
"rankDistribution": [48, 112, 85, 42, 30, 15, 6, 2, 0, 0],
"avgScore": 0.432,
"period": { "days": 7, "since": "2026-03-23T00:00:00.000Z" },
"sampleSize": 412,
"sampleCap": 1000
}
For a given target offer, walks the most recent traces (capped at sampleCap) and attributes every miss to one of: contact-policy block, qualification rejection, or scored-but-outranked. When the offer was scored but not selected, the winning offer in that decision is counted toward the beatenBy list (top 5). The offerId query parameter is required; optional segmentId narrows the analysis to customers in that segment.
Example:
curl -H "X-API-Key: $API_KEY" -H "X-Tenant-Id: $TENANT_ID" \
"https://playground.kaireonai.com/api/v1/dashboard-data?type=why_not_ranked&offerId=off_premium_card&days=14"
acceptance_rate, offer_performance, offer_performance_grouped, channel_effectiveness, daily_trend, and revenue_trend all accept an optional segmentId query parameter. When provided, the underlying aggregation is restricted to interactions from customers in the segment’s materialized view.
offer_performance_grouped&groupBy=segment fans the result out by active segment instead of channel/category; each offer row is decorated with segmentId and segmentName.
If the segment is unknown or its view has not been materialized yet, the endpoint returns {"data": [], "warning": "..."} instead of an error, so dashboards can render a friendly notice.
Error codes
| Code | Reason |
|---|
400 | Unknown type value. |
403 | Insufficient role permissions. |
Role requirements
| Method | Minimum role |
|---|
| GET | viewer |