Skip to main content

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

ParameterTypeRequiredDefaultDescription
typestringNosummaryData type to retrieve (see table below)
daysintegerNo7Lookback window in days (1-365), used by time-based types
modelIdstringNoAlgorithm model ID (only for model_metrics_trend)
groupBystringNochannel for offer_performance_grouped, null for score_distributionGrouping dimension. Accepts channel, category, or segment for offer_performance_grouped; channel, offer, or category for score_distribution
filterIdstringNoFilter by dimension ID (only for score_distribution)
segmentIdstringNoRestrict 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.
channelIdstringNoRestrict selection_frequency to decisions made on a specific channel.
categoryIdstringNoRestrict selection_frequency to offers in a specific category.
decisionFlowIdstringNoRestrict selection_frequency to decisions produced by a specific decision flow.
offerIdstringRequired for why_not_rankedTarget offer for the why-not analysis.
baselineDaysintegerNosame as daysFor anomaly_candidates — the length of the prior-period window compared against the current window.

Data Types

TypeDescription
summaryHigh-level counts: active offers, channels, experiments, journeys, triggers, pending approvals
acceptance_rateAcceptance rate per offer (impressions vs positive outcomes) over days window
offer_performanceTop 20 active offers with impressions, conversions, revenue, and conversion rate
channel_effectivenessImpressions, conversions, and effectiveness rate per channel
budget_burnBudget allocation utilization: allocated, spent, remaining, burn rate
funnelOffer funnel stages: total offers, active, with creatives, total creatives
attribution_summaryAttribution results grouped by model with conversion counts and total value
daily_trend7-day trend of impressions and conversions
model_metrics_trendAUC trend and feature importance from algorithm models (accepts modelId)
latency_trend7-day p50/p99 latency percentiles from run execution data
offer_performance_groupedOffer performance grouped by channel or category (accepts groupBy)
revenue_trendDaily revenue trend from interaction summaries over days window
policy_impactActive suppressions grouped by policy type with counts
score_distributionPropensity score histogram from decision traces (accepts groupBy and filterId)
degraded_scoringCount of degraded scoring events (fallback scoring used due to model errors or timeouts)
selection_frequencyPer-offer eligible / scored / selected counts, selection rate, average rank, and rank distribution over the window
anomaly_candidatesCore-metric anomalies (acceptance rate, revenue, degraded scoring rate) vs a prior-period baseline — stateless; no alert firing
why_not_rankedFor 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"
  }
}

Response — offer_performance

{
  "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
}

Response — offer_performance_grouped

{
  "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"

Segment dimension on existing performance endpoints

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

CodeReason
400Unknown type value.
403Insufficient role permissions.

Role requirements

MethodMinimum role
GETviewer