Propensity segments
Propensity segments are saved segments whose membership comes from a predictive model’s ranking rather than from filter rules. Instead of “contacts where lifecycle_stage equals customer,” the segment is “the top of the rankings the churn model or value model computed.” You score a population with a trained model, the scores rank, and the top of that ranking becomes the saved audience. The same surface backs the dashboard pages under Audience → Propensity segments and Audience → Churn risk. The API and the UI drive the same workflows.1. How propensity segments differ from static segments
A static segment (a rule-based segment or a once-materialized list) says “membership was decided at the moment we saved.” A propensity segment says “membership was decided by a model’s ranking.” The difference matters for both what the segment contains and how it stays current:- Origin of membership. A rule-based segment’s members match filter predicates. A propensity segment’s members are the contacts the trained model ranked highest — the top-N of the scoring population.
- What the segment answers. A rule-based segment answers “who matches this condition?” A propensity segment answers “who is most likely to churn?” or “who is predicted to be worth the most?” — questions no field predicate alone can answer.
- Staleness profile. A rule-based segment with
auto_refresh = truere-evaluates its filter on a schedule; its membership drifts only when the underlying attributes change. A propensity segment’s snapshot drifts when the model’s scores drift — re-training or re-scoring the model can reorder the ranking even if no contact attribute changed.
auto_refresh = false). Renewal is driven from the model side — the activation schedule or a manual re-activate re-materializes the current ranking, which is the propensity surface’s equivalent of “recompute this segment.”
2. Prerequisites
Before you create a propensity segment, the model that produces the score must be trained and its scoring population must be non-empty:- A trained predictive model. Train
churn_propensityorlifetime_valuefirst viaPOST /api/v1/cdp/predictive-models/:model/train. An untrained model replies422withstatus: "insufficient_data"on both/scoreand/activate, and the dashboard’s propensity surfaces show the same “not enough history” inline alert — the predictive models guide covers what counts as enough history for each model. - A non-empty scoring population. Each model scores a fixed server-side predicate — still-active contacts for churn, contacts without a recorded value for CLV. If the predicate matches no one, the score and activate calls return
materialized: falsewithout persisting anything.
3. Create a propensity segment from a model output
Activation is one call. Pass the server-owned model key; the server re-scores the population and materializes the top-N as a new static segment:limit(optional, 1–500) — how many contacts from the top of the ranking to save. Omit it to save the whole ranked population.name(optional) — the saved segment’s name. A readable name matters here because the segment will surface in the segments list and the campaign / journey audience pickers under this exact label.
materialized: true, the created segment, member_count, and activation_ready: true. The segment is immediately visible in GET /api/v1/contacts/segments and targetable by campaigns. Use the lifetime_value key the same way to save a high-value cohort:
4. Read membership and the score histogram
Before you save the top-N, preview the ranking. A barescore call (no contact_id) returns the top-N plus population_scored, so you can size the audience before materializing it:
count (rows returned) against population_scored (total ranked) — that second number is the denominator the top-N limit is a slice of. Each returned row carries the model’s score (score for a classifier, predicted_value_cents for the value model) per contact, which you read as the ranking histogram: the distribution of scores across the returned top-N tells you whether the top tier is meaningfully separated from the tail or whether the ranking is compressed.
Once a segment is materialized, read its membership the same way as any other segment — GET /api/v1/contacts/segments/:id/members returns the saved contact list, and the segment carries the prediction that produced it as a static label rather than a live score.
5. Use the segment in a campaign or activation
The saved propensity segment is a normal segment in the segments list — it appears in the campaign and journey audience pickers, can be exported through audience export, and can be synced through reverse ETL to a warehouse. Target it exactly as you would a rule-based segment:GET /api/v1/contacts/:id/scores) that gate automations read when they condition on a contact’s risk or value band.
6. Refresh cadence
A materialized propensity segment is a frozen snapshot until someone re-materializes it. Renewal happens on the model side, not the segment side:- Scheduled re-activation. The per-model activation schedule (
PUT /api/v1/me/predictive-activation-schedule) re-scores the model on an hourly / daily / weekly cadence and re-saves the top-N to a stable segment name. This is the propensity-surface equivalent ofauto_refreshon a rule-based segment. The predictive models guide covers the schedule contract. - Manual re-activation. POST
/activateagain with a new name. The new snapshot sits alongside the old one in the segments list — you see “At-risk — top 100” and “At-risk — top 100 (2026-08-31)” as separate named segments, and you can diff their membership. - The underlying scores also refresh on their own cadence. The nightly scorer rewrites the persisted per-contact score fields (
propensity_score,ltv_estimate_cents) every tick. A segment materialized today reflects tonight’s ranking only when you re-activate; the scores the nightly job writes do not retroactively edit the frozen segment’s membership.
GET /api/v1/cdp/predictive-models/:model/drift) before trusting a segment materialized against an old fit — when the drift report shows the input distribution has moved, refresh the fit before you refresh the segment.
7. Failure modes
- Model not trained. A
422withstatus: "insufficient_data"on score or activate means the fit could not be computed — fewer than 50 labelled rows, or a classifier with only one outcome class. Train the model once history lands, then retry. - Empty scoring population. An activate call that returns
materialized: false(HTTP 200) means the model’s scoring predicate matched no one. The segment was not created; nothing to delete. Check that the predicate’s base (still-active contacts, or contacts with no recorded value) actually has members — a fresh workspace often has none. - Empty histogram / low population_scored. A score call that returns
count: 0or a smallpopulation_scoredagainst your expected base is the same predicate-empty condition at the preview stage. The top-N cannot exceed the ranked population, so a top-100 on a population-scored 12 saves 12 contacts. - Stale fit behind the scores. Long gaps between train and activate mean the ranking the segment was built on is an old fit. The drift endpoint surfaces this; re-train, then re-activate.
- Segment exists but is empty in a picker. A segment saved earlier can look fine by name and still send to no one if the snapshot is stale relative to where the scores have drifted — re-activate with a current fit rather than editing the segment by hand.
Dashboard twin
The same endpoints back two dashboard pages under Audience:- Propensity segments — the ranking preview, the top-N bound, the tier badges (high / growth / emerging on value, high / medium / low on churn), and the one-click activation button.
- Churn risk — a dedicated home for the churn model’s at-risk ranking with the same save-as-segment flow.
See also
- CDP predictive models — the model catalog, train/score/activate contract, and the per-model activation schedule
- CDP audiences — rule-based segments, computed traits, and account scoring
- Audience export — exporting a materialized segment
- Campaign end-to-end — targeting the saved propensity segment
- Segments API reference — the saved segment’s contract (membership, exports, overlap)