> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# CDP predictive models: catalog, train, tier, and activate

> Turn the CDP's four built-in predictive models (churn propensity, conversion intent, lifetime value, engagement fatigue) from trained scores into activated audiences — read training reports, threshold CLV tiers, schedule re-activation, and close the loop end to end.

# CDP predictive models

The CDP fits real predictive models against your first-party history — not heuristic tags. Four built-in models score profiles for activation: churn propensity, conversion intent, lifetime value, and engagement fatigue. This guide covers the model catalog, the train → evaluate → score loop, CLV tiering onto the regression model's output, the per-model activation schedule, and one worked end-to-end run. It closes the loop opened by [CDP audiences](/guides/cdp-segments) — predictive scores become segments, and segments get activated.

The same surface backs the dashboard pages under **Audience → Predictive models**, **Audience → Propensity segments**, and **Audience → Churn risk**. The API and the UI drive the same models.

## 1. The built-in model catalog

`GET /api/v1/cdp/predictive-models` lists the available models with their kind, output unit, and feature set:

```bash theme={null}
curl https://api.orbit.devotel.io/api/v1/cdp/predictive-models \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

Four model keys, in one server-owned catalog:

| Model key            | Kind           | Output unit    | What it learns                                                                               |
| -------------------- | -------------- | -------------- | -------------------------------------------------------------------------------------------- |
| `churn_propensity`   | classification | probability    | P(active contact churns), fit on resolved lifecycle outcomes (churned vs still active).      |
| `conversion_intent`  | classification | probability    | P(lead converts), fit on converted stages (active/archived/churned) vs open leads.           |
| `lifetime_value`     | regression     | value in cents | Predicted value for contacts with no recorded value, learned from contacts that have one.    |
| `engagement_fatigue` | classification | probability    | P(subscribed contact opts out or disengages), fit on opted-out vs still-subscribed contacts. |

Classification models predict a probability; the regression model predicts a value in cents. The catalog response echoes each model's `kind`, `output_unit`, `algorithm` (L2-regularized logistic regression for classifiers, ridge regression for the regressor), and `feature_names`.

Every model trains over the same six first-party behavioral features — no external enrichment required:

* `tenure_days` — days since the contact was created.
* `recency_days` — days since last contact.
* `messages_sent` / `messages_received` — lifetime message counts.
* `events_30d` / `distinct_events_30d` — event volume and variety over the last 30 days.

Each model's training population and scoring population are fixed server-side predicates — resolved outcomes for training, the activation-worthy base for scoring — so a model never trains or scores on contacts you did not intend.

## 2. Train → evaluate → score

**Train** fits the model over your tenant's history and returns the report — algorithm, sample size, evaluation metrics, intercept, and per-feature coefficients:

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/cdp/predictive-models/lifetime_value/train \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

A trained classifier reports `auc`, `log_loss`, `accuracy`, and `positive_rate`; the regressor reports `r2`, `rmse`, and `mae`. Both echo `coefficients` as `{ feature, weight }` pairs — the standardized feature importances that tell you which signals drive the score (high `recency_days` weight on churn means "quiet contacts churn", for example). Training is read-only: the fit is computed on the fly and cached briefly so a follow-up `/score` reuses it.

When a fit is not meaningful yet, the response is a `422` with `status: "insufficient_data"` and a parsed-back reason — fewer than 50 labelled rows, a classifier with only one outcome class, or (for uplift) an arm too thin to isolate an effect. Let resolved lifecycle outcomes accumulate and retry.

**Score** applies the fit. Pass a `contact_id` to score one profile, or omit it to rank the model's scoring population and return the top-N:

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/cdp/predictive-models/lifetime_value/score \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "limit": 100 }'
```

The response ranks the population descending and echoes `population_scored` alongside the top `limit` rows — a classifier's `score` (probability) or the regressor's `predicted_value_cents`. If the model is not trained yet, the response is the cached `insufficient_data` report with a `422`, not a partial ranking.

Two support surfaces round out the loop: `GET /api/v1/cdp/predictive-models/:model/drift` monitors input/output distribution shift (PSI per feature plus the prediction score) against a configurable window, and `POST .../uplift/train` + `POST .../uplift/score` fit a per-campaign persuadable model over a control-holdout contrast. Reach for drift before trusting a stale ranking; reach for uplift when the question is "who is moveable", not "who is high-value".

## 3. Propensity tiers from the regression output

The `lifetime_value` model predicts a value in cents, and the nightly scorer also persists an `ltv_estimate_cents` per contact. Both feed the canonical value tiers the CDP uses everywhere:

* `vip` — 10,000 cents (\$100) and above.
* `high` — 2,500 cents (\$25) and above.
* `medium` — 500 cents (\$5) and above.
* `low` — everything below.

`GET /api/v1/cdp/clv/tiers` sizes your base across those four tiers — the "which tier is worth a segment?" read before you pick a threshold. `POST /api/v1/cdp/clv/segment/preview` then dry-runs a threshold (`op`: `gte` for the high-value audience, `lte` for a low-value re-engagement audience; `value_cents`: the cutoff) and returns a ranked sample with `cohort_size`, and `POST /api/v1/cdp/clv/segment` materializes the full matching cohort as a static segment:

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/cdp/clv/segment \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "op": "gte", "value_cents": 10000, "name": "VIP tier" }'
```

Thresholds reject a cohort over the materialization cap (500) with a `422` — tighten the cutoff or narrow with the segment-filters API. The same pattern applies to model output: score `lifetime_value`, read the ranked `predicted_value_cents`, and threshold that ranking in a segment filter — tiering is a read over the score, not a separate model.

## 4. Per-model activation schedule

One-click activation is useful once; a cadence keeps the audience current. Each model carries an operator-controlled schedule — enabled flag, cadence (`hourly` / `daily` / `weekly`), top-N bound, and segment-name template — stored durably per user so a follow-up re-activation does not need a manual click.

```bash theme={null}
# Read the current schedule intent
curl https://api.orbit.devotel.io/api/v1/me/predictive-activation-schedule \
  -H "X-API-Key: dv_live_sk_your_key_here"

# Replace it (full map on every settled change)
curl -X PUT https://api.orbit.devotel.io/api/v1/me/predictive-activation-schedule \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "schedule": {
      "lifetime_value": {
        "enabled": true,
        "cadence": "daily",
        "topN": 100,
        "nameTemplate": "Predicted LTV — daily top 100"
      }
    }
  }'
```

The GET returns the saved map (or `null` when nothing is saved yet); the PUT accepts only the models you changed and validates each entry before persisting. Model keys are closed to the four registry entries, `topN` is bounded 1–500, and `nameTemplate` keeps a human-readable label across re-activations.

The dashboard's per-model schedule card on **Audience → Predictive models** drives these two endpoints; the API reads back exactly what the card saved.

## 5. End-to-end: LTV top decile into a live segment

Train the value model, score the population, activate the top decile, and let a self-refreshing segment keep it current:

```bash theme={null}
# 1. Fit the model
curl -X POST https://api.orbit.devotel.io/api/v1/cdp/predictive-models/lifetime_value/train \
  -H "X-API-Key: dv_live_sk_your_key_here"

# 2. Score the population and preview the ranking
curl -X POST https://api.orbit.devotel.io/api/v1/cdp/predictive-models/lifetime_value/score \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "limit": 50 }'

# 3. Materialize the top decile as a segment
curl -X POST https://api.orbit.devotel.io/api/v1/cdp/predictive-models/lifetime_value/activate \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Predicted LTV — top decile", "limit": 100 }'

# 4. Schedule the cadence so the list stays current
curl -X PUT https://api.orbit.devotel.io/api/v1/me/predictive-activation-schedule \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "schedule": { "lifetime_value": { "enabled": true, "cadence": "daily", "topN": 100, "nameTemplate": "Predicted LTV — daily top 100" } } }'
```

The activate call returns `materialized: true`, the created `segment`, `member_count`, and `activation_ready: true` — target it from campaigns, ad-network sync, or export. If the scoring population is empty it returns `materialized: false` without persisting anything; if the model cannot be fit yet, it returns the cached `insufficient_data` report with a `422`.

## 6. Dashboard twin

The same endpoints back three dashboard pages under **Audience**:

* **Predictive models** — the catalog, train/score actions, drift monitor, and the per-model activation schedule card.
* **Propensity segments** — the CLV tier distribution and the threshold-gated value segment flow.
* **Churn risk** — the at-risk ranking and the retention segment flow on the `churn_propensity` model.

Nothing you can do in the UI is hidden from the API; the pages are a rendering of the same contracts.

## See also

* [CDP audiences](/guides/cdp-segments) — segments, computed traits, account scoring, and activation
* [Campaign end-to-end](/guides/campaign-end-to-end) — targeting the activated audience with a send
* [Segments API reference](/api-reference/segments) — filters, membership, exports, overlap
* [CDP API reference](/api-reference/endpoints/cdp) — the full predictive-models / CLV / drift endpoint contracts
