Half-Life Suggestions
Research-backed half-life defaults for engagement scoring rules. Use these endpoints to inspect which rules are eligible for a recommended half-life and to bulk-apply the values.
For the user-facing concept, see the Half-Life Decay guide.
GET /scoring/half-life-suggestions
Return the list of rules in the active Organizational Unit that have no half-life configured and have a research-backed default available.
Query Parameters
| Parameter | Required | Type | Description |
|---|---|---|---|
dimension | No | string | One of engagement or all. Default all. Profile, account, and deal rules are not event-sourced and return 400 if specified. |
Response
Status: 200 OK
{
"eligible_count": 3,
"rules": [
{
"rule_id": "rule-123",
"ruleset_id": "ruleset-abc",
"dimension": "engagement",
"event_type": "page_view",
"current_half_life_days": null,
"suggested_half_life_days": 14,
"source": "paper-section-3"
},
{
"rule_id": "rule-124",
"ruleset_id": "ruleset-abc",
"dimension": "engagement",
"event_type": "demo_request",
"current_half_life_days": null,
"suggested_half_life_days": 90,
"source": "paper-section-3"
},
{
"rule_id": "rule-125",
"ruleset_id": "ruleset-abc",
"dimension": "engagement",
"event_type": "email_click",
"current_half_life_days": null,
"suggested_half_life_days": 28,
"source": "paper-section-3"
}
]
}
Response Fields
| Field | Type | Description |
|---|---|---|
eligible_count | integer | Number of rules eligible for a suggestion. The UI uses this to label the bulk-apply button. |
rules[].rule_id | string | Rule identifier; pass this to the apply endpoint. |
rules[].ruleset_id | string | Ruleset that owns the rule. |
rules[].dimension | string | engagement or deal. |
rules[].event_type | string | The event type the rule scores. |
rules[].current_half_life_days | integer or null | The rule's current half-life. Always null for eligible rules; included for symmetry with the apply response. |
rules[].suggested_half_life_days | integer | The research-backed default. |
rules[].source | string | Citation tag for the recommendation. |
Example
curl -X GET "https://api.kenbun.io/scoring/half-life-suggestions?dimension=engagement" \
-H "Authorization: Bearer <token>"
Common Errors
| Status | Meaning | Solution |
|---|---|---|
| 400 | Invalid or non-event-sourced dimension | Use engagement or all. Profile, account, and deal dimensions are not event-sourced and return 400. |
| 401 | Unauthorized | Verify your credentials and active OU context. |
POST /scoring/half-life-suggestions/apply
Bulk-apply research-backed half-life defaults to a list of rules. Each rule update is independent; a transient failure on one rule does not roll back the others. Every applied rule is audit-logged.
Request Body
| Field | Required | Type | Description |
|---|---|---|---|
rule_ids | Yes | string[] | Rule identifiers to apply suggestions to. Typically the rule_id values from the GET response. |
{
"rule_ids": ["rule-123", "rule-124", "rule-125"]
}
Response
Status: 200 OK
{
"applied_count": 2,
"skipped_count": 1,
"outcomes": [
{
"rule_id": "rule-123",
"status": "applied",
"applied_half_life_days": 14
},
{
"rule_id": "rule-124",
"status": "applied",
"applied_half_life_days": 90
},
{
"rule_id": "rule-125",
"status": "skipped",
"skip_reason": "already_configured"
}
]
}
Response Fields
| Field | Type | Description |
|---|---|---|
applied_count | integer | Number of rules updated. |
skipped_count | integer | Number of rules left unchanged, with a reason. |
outcomes[].rule_id | string | The rule the outcome refers to. |
outcomes[].status | string | applied or skipped. |
outcomes[].applied_half_life_days | integer | Present when status is applied. The new half-life now stored on the rule. |
outcomes[].skip_reason | string | Present when status is skipped. See the table below. |
Skip Reasons
| Reason | Meaning |
|---|---|
already_configured | Rule already has a non-null half_life_days. Existing values are never overwritten. |
no_research_default | Event type is not in the practitioner table, or rule does not score events. |
dimension_not_event_sourced | Rule belongs to a profile, account, or deal ruleset. These dimensions evaluate current attribute values and do not decay. |
not_found | Rule does not exist or belongs to a different OU. |
lookup_error | Transient lookup error. Retry the rule individually. |
update_error | Transient write error. Retry the rule individually. |
Example
curl -X POST "https://api.kenbun.io/scoring/half-life-suggestions/apply" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"rule_ids": ["rule-123", "rule-124", "rule-125"]}'
Common Errors
| Status | Meaning | Solution |
|---|---|---|
| 400 | Empty rule_ids or invalid JSON | Provide a non-empty array of rule identifiers. |
| 401 | Unauthorized | Verify your credentials and active OU context. |
Audit Trail
Every applied rule writes a per-rule audit log entry that records the user who triggered the change and the value that was set. The audit log is also written for the request as a whole, so a single bulk-apply produces both a summary entry and one detail entry per rule.
Related Endpoints
- Engagement Rules: set
half_life_daysdirectly on a single rule - Engagement Rule by ID: update or clear
half_life_dayson an existing rule - Engagement Rulesets: set
score_floor_pct(signal floor) for a ruleset
See Also
- Half-Life Decay guide: concepts, the curve, and best practices
- Decay Rules guide: flat per-day point reduction rules