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.

GET /api/v1/decision-traces

List decision traces with offset-based pagination. Traces are only recorded when tracing is enabled in tenant settings and the request passes the sample rate check.

Query Parameters

ParameterTypeDefaultDescription
customerIdstringFilter traces for a specific customer
requestIdstringFilter by request/interaction ID
limitinteger50Max results (max 200)
offsetinteger0Pagination offset

Response

{
  "traces": [
    {
      "id": "trace_001",
      "customerId": "CUST001",
      "requestId": "550e8400-e29b-41d4-a716-446655440000",
      "decisionFlowKey": "default-flow",
      "pipeline": [
        { "stage": "qualification", "candidates": 47, "passed": 32, "durationMs": 12 },
        { "stage": "contact_policy", "candidates": 32, "passed": 28, "durationMs": 8 },
        { "stage": "scoring", "candidates": 28, "durationMs": 15 },
        { "stage": "ranking", "topScore": 0.872, "durationMs": 2 },
        { "stage": "arbitration", "method": "priority_weighted", "durationMs": 3 }
      ],
      "result": {
        "count": 5,
        "topOffer": { "offerId": "offer_001", "score": 0.872 }
      },
      "totalDurationMs": 42,
      "createdAt": "2026-03-16T14:30:00.000Z"
    }
  ],
  "total": 1250,
  "limit": 50,
  "offset": 0
}

GET /api/v1/decision-traces/

Get a single decision trace with full pipeline detail.

Response

Returns the complete trace object with all pipeline stages, scoring details, and result.

Enabling Decision Traces

Decision traces are controlled by two tenant settings:
SettingDescription
decisionTraceEnabledMaster toggle for trace recording
decisionTraceSampleRateSampling rate (0.0 - 1.0). Set to 1.0 to trace every request
Configure these via the Settings API or the platform UI under Settings.
At high traffic volumes, set the sample rate below 1.0 to avoid excessive storage. A 10% sample rate (0.1) typically provides sufficient forensic coverage.

JSON Field Shapes

Each trace persists four JSON arrays that capture the forensic detail of the decision. Downstream aggregators (the selection_frequency, anomaly_candidates, and why_not_ranked endpoints in Dashboard Data) expect the following shapes on newly-written rows. Older rows written before a field was added are still readable — fields default to null in the aggregation queries.

scoringResults

Best-first list of offers that reached the scoring stage.
[
  { "offerId": "off_premium_card", "score": 0.89, "rank": 1 },
  { "offerId": "off_gold_plus", "score": 0.71, "rank": 2 }
]

selectedOffers

The final ranked result returned to the caller, in delivery order.
[
  { "offerId": "off_premium_card", "score": 0.89, "rank": 1 },
  { "offerId": "off_gold_plus", "score": 0.71, "rank": 2 }
]

qualificationResults

One row per offer that the qualification stage evaluated. passed=false indicates a rejection; ruleId identifies the rule that evaluated.
[
  { "offerId": "off_premium_card", "passed": true, "reason": "passed" },
  { "offerId": "off_restricted", "passed": false, "reason": "segment_mismatch", "ruleId": "rule_42" }
]

contactPolicyResults

One row per offer that the contact-policy stage evaluated. blocked=true indicates the policy suppressed the offer for this customer.
[
  { "offerId": "off_premium_card", "blocked": false, "reason": "passed" },
  { "offerId": "off_weekly_promo", "blocked": true, "reason": "frequency_cap", "policyId": "pol_email_daily_cap" }
]

POST /api/v1/decisions//narrative

Generate an LLM-written natural-language explanation of a single decision trace. The feature is opt-in per tenant — see LLM Explanations.

Request Body

{
  "mode": "regulator",
  "noCache": false
}
FieldTypeDefaultDescription
mode"regulator" | "agent" | "customer""regulator"Audience for the explanation. Changes tone, length, and format.
noCachebooleanfalseWhen true, bypass the cache and force a fresh LLM call.

Response

{
  "narrative": "The system recommended offer_premium_card for customer CUST001 because ...",
  "mode": "regulator",
  "model": "claude-sonnet-4-7",
  "cached": false,
  "tokens": { "input": 1420, "output": 310 },
  "createdAt": "2026-04-18T21:04:18.000Z"
}
FieldTypeDescription
narrativestringThe generated explanation. Prose for regulator and customer modes, structured JSON for agent mode.
modestringEchoes the requested mode.
modelstringIdentifier of the LLM used.
cachedbooleantrue if the result was served from Redis.
tokens.input / tokens.outputnumberLLM token counts when reported by the provider.
createdAtISO-8601 stringCreation timestamp of the narrative (cached or fresh).

Auth, Limits, and Tenancy

  • Requires tenant authentication (session or API key).
  • Rate limited to 20 requests / minute / tenant. Exceeding returns 429.
  • Tenant opt-in required: tenantSettings.aiAnalyzerSettings.llmExplanationsEnabled = true. Otherwise returns 403 with "LLM explanations are not enabled for this tenant.".
  • The decision trace must belong to the authenticated tenant or the response is 404.

Audit Log (regulator mode)

When mode = "regulator", a row is appended to AuditLog:
{
  "tenantId": "tenant_abc",
  "action": "generate_narrative",
  "entityType": "decision_trace",
  "entityId": "trace_001",
  "entityName": "regulator narrative",
  "changes": {
    "mode": "regulator",
    "model": "claude-sonnet-4-7",
    "cached": false,
    "narrativePreview": "..."
  }
}

Caching

Results are cached in Redis for 7 days under the composite key (tenantId × decisionTraceId × mode × model × inputsHash). Repeating the same request returns cached: true instantly.

POST /api/v1/decisions//shap

Return exact per-feature TreeSHAP contributions for a recorded decision’s gradient_boosted scoring step. Designed for EU AI Act Article 13/22 audit workflows: the response is a mathematically-grounded, additivity-verified breakdown of every feature’s effect on the raw margin (logit space). Unlike the LLM narrative endpoint, this returns raw numbers — deterministic, cacheable, and auditable independent of any LLM availability. Pair the two when you need both prose and numerics in a regulator export.

Request Body

{
  "modelId": "mdl_premium_card_gbm",
  "offerId": "off_premium_card",
  "attributes": {
    "recent_transaction_count": 12,
    "tenure_months": 36,
    "average_balance": 15400,
    "segment_index": 2
  },
  "round": 6
}
FieldTypeDefaultDescription
modelIdstringrequiredThe AlgorithmModel.id used to score the trace. Must be tenant-owned and modelType = "gradient_boosted".
offerIdstringoptionalThe candidate offer the SHAP is being computed for. Echoed in the audit log.
attributesobjectrequiredThe customer/offer/context attributes passed to the scorer at decision time. Required because raw attributes are not persisted on the trace (PII minimization).
roundinteger6Decimal places for output (0 = raw doubles).

Response

{
  "decisionTraceId": "trace_001",
  "modelId": "mdl_premium_card_gbm",
  "modelName": "Premium Card GBM",
  "offerId": "off_premium_card",
  "shapValues": {
    "recent_transaction_count": 1.314,
    "tenure_months": 0.428,
    "average_balance": -0.211,
    "segment_index": 0.083
  },
  "baseline": -0.602,
  "rawMargin": 1.012,
  "additivityResidual": 0.0,
  "featureCount": 4
}
FieldTypeDescription
shapValuesobjectPer-feature Shapley contributions in raw-margin (logit) space.
baselinenumberCover-weighted expected raw-margin across the ensemble.
rawMarginnumberThe chosen leaf-value sum for these attributes. sigmoid(rawMargin) = score.
additivityResidualnumber`rawMargin − baseline − Σ shapValues`. Should be ≈ 0; non-zero indicates a malformed model.
featureCountnumberNumber of features that received a non-zero contribution.

Additivity guarantee

For any input x:
sum(shapValues) + baseline = rawMargin
score(x)                   = sigmoid(rawMargin)
This identity is built into the algorithm (Lundberg, Erion, Lee 2018, Algorithm 2 — path-dependent variant). The endpoint reports additivityResidual so consumers can verify the invariant on-wire.

Probability-space approximation

SHAP values are reported in raw-margin space — the only space where the additivity identity holds. To approximate a feature’s effect on the probability, use:
delta_p_i ≈ sigmoid(baseline + shap_i) − sigmoid(baseline)
This is monotone with shap_i but not strictly additive in probability space. UI surfaces typically show both: the raw φ for compliance, and a sigmoid-mapped delta for human-readable display.

Auth, Limits, and Tenancy

  • Requires tenant authentication (session or API key).
  • Rate limited to 30 requests / minute / tenant.
  • Tenant opt-in required: tenantSettings.aiAnalyzerSettings.llmExplanationsEnabled = true (same flag as the narrative endpoint).
  • The decision trace, the model, and the request must all belong to the same tenant. Cross-tenant lookup returns 404.
  • Returns 400 if the model’s modelType is not gradient_boosted or if it has no trained trees.

Audit Log

Every successful call writes:
{
  "tenantId": "tenant_abc",
  "action": "compute_shap",
  "entityType": "decision_trace",
  "entityId": "trace_001",
  "entityName": "shap for Premium Card GBM / off_premium_card",
  "changes": {
    "modelId": "mdl_premium_card_gbm",
    "modelName": "Premium Card GBM",
    "offerId": "off_premium_card",
    "featureCount": 4,
    "baseline": -0.602,
    "rawMargin": 1.012,
    "additivityResidual": 0.0
  }
}
This ensures DSAR exports and regulator queries can trace which decisions have had SHAP attributions computed and when.

Roles

EndpointAllowed Roles
GET /decision-tracesadmin, editor, viewer
GET /decision-traces/{id}admin, editor, viewer
POST /decisions/{id}/narrativeadmin, editor, viewer (tenant-scoped)
POST /decisions/{id}/shapadmin, editor, viewer (tenant-scoped)
See also: LLM Explanations | Dashboards | Decision Flows