> ## 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.

# Retail Rewards Dataset Guide

> End-to-end walkthrough of the retail rewards dataset — the most complete dataset pack with 10 offers, 6 channels, decisioning gates, contact policies, and three scoring algorithms (Scorecard, Bayesian, Thompson Bandit).

The retail rewards dataset is the **flagship dataset pack** for KaireonAI. It creates a complete decisioning environment modeled after a retail loyalty rewards program with 10 promotional offers across 6 channels, decisioning gates, contact policies, adaptive models, experiments, and a customer segment.

This guide walks you through loading the dataset, exploring what gets created, running recommendations, recording outcomes, and using adaptive models.

## What Gets Created

| Entity                    | Count | Details                                                                                                     |
| ------------------------- | ----- | ----------------------------------------------------------------------------------------------------------- |
| Data Schemas + DDL Tables | 3     | `retail_customers` (100 rows), `retail_offers` (10 rows), `retail_events` (500 rows)                        |
| Categories                | 3     | Acquisition (BOGO), Retention (Discount), Engagement (Informational)                                        |
| Channels                  | 6     | Web (banner), Email, Mobile (push), Social, Batch Email (file), Manual Outreach                             |
| Offers                    | 10    | 4 BOGO, 4 Discount, 2 Informational — priorities 55-85                                                      |
| Creatives                 | 60    | 10 offers x 6 channels — each with channel-specific content                                                 |
| Decisioning Gates         | 5     | Min Age 18, Min Income \$30k, Loyalty Members Only, Premium BOGO — High Spend, Senior Discount Gate         |
| Contact Policies          | 5     | Max 3/day, 24hr same-offer cooldown, 48hr post-conversion cooldown, max 10/week, BOGO vs Discount exclusion |
| Outcome Types             | 5     | impression, click, accept, convert, dismiss                                                                 |
| Algorithm Models          | 3     | Scorecard, Bayesian (Naive Bayes), Thompson Bandit                                                          |
| Experiment                | 1     | Scorecard vs Bayesian (80/20 split)                                                                         |
| Decision Flow             | 1     | Full pipeline with 7 stages                                                                                 |
| Segment                   | 1     | High-Income Members (income > \$70k, tenure > 365 days)                                                     |
| Interaction History       | 500   | 90-day window of synthetic interactions                                                                     |
| Interaction Summaries     | 500   | Materialized aggregates for contact policy enforcement                                                      |

## Step-by-Step Walkthrough

<Steps>
  ### Load the Retail Rewards Dataset

  ```bash theme={null}
  curl -X POST "http://localhost:3000/api/v1/seed-dataset/retail-rewards?force=true" \
    -H "Content-Type: application/json" \
    -H "X-Requested-With: XMLHttpRequest"
  ```

  <Accordion title="Expected Response (201 Created)">
    ```json theme={null}
    {
      "success": true,
      "dataset": "retail-rewards",
      "created": {
        "schemas": 3,
        "categories": 3,
        "subCategories": 3,
        "channels": 6,
        "offers": 10,
        "creatives": 60,
        "qualificationRules": 5,
        "contactPolicies": 5,
        "outcomeTypes": 5,
        "models": 3,
        "experiments": 1,
        "decisionFlows": 1,
        "segments": 1,
        "customerRows": 100,
        "offerRows": 10,
        "eventRows": 500,
        "interactionHistory": 500,
        "interactionSummaries": 500
      }
    }
    ```
  </Accordion>

  <Warning>
    The `?force=true` parameter removes any previously loaded dataset before seeding. Without it, you will get a 409 Conflict if data already exists.
  </Warning>

  ### Explore the Offers

  The dataset creates 10 offers across 3 categories. List them all:

  ```bash theme={null}
  curl "http://localhost:3000/api/v1/offers" \
    -H "X-Requested-With: XMLHttpRequest"
  ```

  <Accordion title="Expected Response — 10 Offers">
    ```json theme={null}
    [
      {
        "id": "uuid-...",
        "name": "Retail Rewards: Discount — 10 Day Low",
        "status": "active",
        "priority": 85,
        "category": "retention",
        "budget": { "monthlyBudget": 60000, "costPerUnit": 2 },
        "schedule": { "startDate": "2026-01-01", "endDate": "2026-12-31" },
        "creatives": [ "6 creatives, one per channel" ],
        "categoryRef": { "name": "Retail Rewards: Retention" },
        "subCategoryRef": { "name": "Retail Rewards: Discount" }
      }
    ]
    ```
  </Accordion>

  <Info>
    **Priority** (0-100) determines offer ranking. Score formula: `(priority / 100) x (creative.weight / 100) x fitMultiplier`. Higher priority offers score higher in the pipeline.
  </Info>

  ### Run a Recommendation

  Call the Recommend API with customer attributes to get personalized offers:

  <CodeGroup>
    ```bash Qualified Customer theme={null}
    curl -X POST "http://localhost:3000/api/v1/recommend" \
      -H "Content-Type: application/json" \
      -H "X-Requested-With: XMLHttpRequest" \
      -d '{
      "customerId": "cust_001",
      "limit": 5,
      "attributes": {
        "retail_customers.age": 30,
        "retail_customers.income": 65000
      }
    }'
    ```

    ```bash With Debug Trace theme={null}
    curl -X POST "http://localhost:3000/api/v1/recommend?debug=true" \
      -H "Content-Type: application/json" \
      -H "X-Requested-With: XMLHttpRequest" \
      -d '{
      "customerId": "cust_002",
      "limit": 3,
      "channel": "email",
      "attributes": {
        "retail_customers.age": 25,
        "retail_customers.income": 45000
      }
    }'
    ```

    ```bash Missing Attributes (Blocked) theme={null}
    curl -X POST "http://localhost:3000/api/v1/recommend?debug=true" \
      -H "Content-Type: application/json" \
      -H "X-Requested-With: XMLHttpRequest" \
      -d '{
      "customerId": "cust_003",
      "limit": 5
    }'
    ```
  </CodeGroup>

  <Accordion title="Response — Qualified Customer">
    ```json theme={null}
    {
      "interactionId": "a1b2c3d4-...",
      "customerId": "cust_001",
      "count": 5,
      "decisions": [
        {
          "creativeId": "creative-uuid-1",
          "creativeName": "Retail Rewards: Discount — 10 Day Low — Web",
          "offerId": "offer-uuid-1",
          "offerName": "Retail Rewards: Discount — 10 Day Low",
          "category": "retention",
          "channelType": "Banner",
          "channelName": "Retail Rewards: Web",
          "content": {
            "headline": "Save on Your Next Visit",
            "subline": "10% off any drink for 10 days",
            "cta": "Claim Offer",
            "imageUrl": "/images/retail-discount.jpg"
          },
          "score": 0.85,
          "rank": 1,
          "priority": 85
        }
      ]
    }
    ```
  </Accordion>

  <Warning>
    Attributes use **schema-prefixed dot notation** as literal keys, NOT nested objects. The qualification engine does `context.attributes["retail_customers.age"]` — so the key must match exactly:

    ```json theme={null}
    // CORRECT
    "attributes": { "retail_customers.age": 30 }

    // WRONG — will not match decisioning gates
    "attributes": { "age": 30 }
    ```
  </Warning>

  ### Record an Outcome

  After delivering an offer, record the customer's response via the Respond API:

  <CodeGroup>
    ```bash Record a Click theme={null}
    curl -X POST "http://localhost:3000/api/v1/respond" \
      -H "Content-Type: application/json" \
      -H "X-Requested-With: XMLHttpRequest" \
      -d '{
      "customerId": "cust_001",
      "creativeId": "<creative-uuid-from-decision>",
      "outcome": "click",
      "interactionId": "<interactionId-from-recommend-response>",
      "idempotencyKey": "click-cust001-creative123-20260304",
      "context": {
        "device": "mobile",
        "sessionId": "sess_abc123"
      }
    }'
    ```

    ```bash Record a Conversion theme={null}
    curl -X POST "http://localhost:3000/api/v1/respond" \
      -H "Content-Type: application/json" \
      -H "X-Requested-With: XMLHttpRequest" \
      -d '{
      "customerId": "cust_001",
      "creativeId": "<creative-uuid>",
      "outcome": "convert",
      "interactionId": "<interactionId>",
      "idempotencyKey": "convert-cust001-order-12345",
      "conversionValue": 47.50,
      "outcomeDetails": {
        "orderId": "order-12345",
        "productSku": "iced-beverage-large"
      }
    }'
    ```
  </CodeGroup>

  ### Train an Adaptive Model

  Trigger a manual training run for any of the 3 pre-loaded models:

  ```bash theme={null}
  curl -X POST "http://localhost:3000/api/v1/algorithm-models/<model-uuid>/train" \
    -H "X-Requested-With: XMLHttpRequest"
  ```

  <Accordion title="Training Response">
    ```json theme={null}
    {
      "modelId": "model-uuid",
      "modelType": "bayesian",
      "sampleCount": 500,
      "metrics": {
        "accuracy": 0.72,
        "precision": 0.68,
        "recall": 0.76,
        "f1": 0.72,
        "auc": 0.74,
        "trainedAt": "2026-03-04T15:10:00Z"
      },
      "status": "success"
    }
    ```
  </Accordion>

  ### Check the Experiment

  The pre-loaded experiment splits traffic 80/20 between Scorecard (champion) and Bayesian (challenger):

  ```bash theme={null}
  curl "http://localhost:3000/api/v1/experiments" \
    -H "X-Requested-With: XMLHttpRequest"
  ```
</Steps>

## Key Features Demonstrated

### Decisioning Gates

The dataset ships **5 decisioning gates**. The two global hard gates apply to every offer:

| Rule             | Type                 | Condition                          | Priority       |
| ---------------- | -------------------- | ---------------------------------- | -------------- |
| Min Age 18       | attribute\_condition | `retail_customers.age >= 18`       | 100 (Critical) |
| Min Income \$30k | attribute\_condition | `retail_customers.income >= 30000` | 90 (Critical)  |

Three more are offer-scoped: **Loyalty Members Only** (`membership_days >= 30`), **Premium BOGO — High Spend** (`income >= 70000`, on BOGO Hard only), and **Senior Discount Gate** (`age >= 35`, on Discount High only).

Missing attributes cause the rule to **fail closed** -- the customer is ineligible.

### Contact Policies

The dataset ships **5 contact policies**:

| Policy                        | Type              | Config                                                    |
| ----------------------------- | ----------------- | --------------------------------------------------------- |
| Max 3 per Day                 | frequency\_cap    | `maxPerDay: 3`                                            |
| 24hr Same-Offer Cooldown      | cooldown          | `cooldownHours: 24`                                       |
| 48hr Post-Conversion Cooldown | cooldown          | pauses all offers for 48h after a conversion              |
| Max 10 per Week Global        | frequency\_cap    | `maxFrequency: 10`, `periodDays: 7` (across all channels) |
| BOGO vs Discount Exclusion    | mutual\_exclusion | don't show both offer types in the same session           |

### Three Model Types

| Model           | Type              | How It Learns                                     | Best For                                |
| --------------- | ----------------- | ------------------------------------------------- | --------------------------------------- |
| Scorecard       | `scorecard`       | Rule-based (manual)                               | Transparent, explainable scoring        |
| Bayesian        | `bayesian`        | Auto-incremental, updates every 100 outcomes      | Adapts to changing preferences          |
| Thompson Bandit | `thompson_bandit` | Updates Beta(alpha, beta) per arm on each outcome | Exploration/exploitation for new offers |

### Decision Pipeline

The pipeline processes candidates through 7 stages:

1. **Inventory** -- Filters by schedule, flattens offers x creatives into candidates
2. **Qualification** -- Hard-gate rules (age, income, segment). Fail = removed
3. **Contact Policy** -- Frequency cap, cooldown, mutual exclusion
4. **Consent** -- Channel-level consent check
5. **Guardrails** -- Business constraint rules
6. **Scoring** -- Model-based or priority-weighted
7. **Ranking** -- Sort by score, apply limit, diversity constraints

### Batch Email via Segments

Use the pre-loaded High-Income Members segment for batch email campaigns:

```bash theme={null}
curl -X POST "http://localhost:3000/api/v1/simulate" \
  -H "Content-Type: application/json" \
  -H "X-Requested-With: XMLHttpRequest" \
  -d '{
  "segmentId": "<segment-uuid>",
  "sampleSize": 100,
  "channelFilter": "email"
}'
```

This runs the decision pipeline for the matching segment members (the High-Income Members segment is a subset of the 100 seeded customers) and returns per-customer decisions with email content (subject, body, CTA) ready for your ESP.

## What to Look For

* **Qualification blocking**: Request without attributes returns 0 decisions. The `debugTrace` shows which rules blocked each offer.
* **Contact policy enforcement**: After 3 recommendations in a day, the frequency cap blocks further contact. The 24hr cooldown prevents re-contact too soon.
* **Experiment routing**: The same customer always lands in the same experiment arm (deterministic hashing). 80% of customers get Scorecard scoring, 20% get Bayesian.
* **Adaptive learning**: After recording outcomes via `/respond`, Bayesian models auto-update every 100 outcomes. Thompson Bandit updates alpha/beta per outcome immediately.
* **Multi-channel creatives**: Each of the 10 offers has 6 creatives (web, email, mobile push, social, batch email, manual outreach) with channel-appropriate content.

## API Quick Reference

| Action                    | Method | Endpoint                              |
| ------------------------- | ------ | ------------------------------------- |
| Load sample data          | POST   | `/api/v1/seed-dataset/retail-rewards` |
| List offers               | GET    | `/api/v1/offers`                      |
| List channels             | GET    | `/api/v1/channels`                    |
| List creatives            | GET    | `/api/v1/creatives`                   |
| Get recommendations       | POST   | `/api/v1/recommend`                   |
| Record outcome            | POST   | `/api/v1/respond`                     |
| Query interaction history | GET    | `/api/v1/interaction-history`         |
| Run batch simulation      | POST   | `/api/v1/simulate`                    |
| Train model               | POST   | `/api/v1/algorithm-models/{id}/train` |
| Score customer            | POST   | `/api/v1/algorithm-models/{id}/score` |
| Create experiment         | POST   | `/api/v1/experiments`                 |
