Risk Acuity
Status:
stableCategory:compositeAdded:2026-06-03Last reviewed:2026-06-03
Summary
The "how urgent" readout — priority of risk against time.
/acuity/compute combines the subject's instrument findings with
de-identified situational descriptors (situation) and an injury
onset timestamp, and returns an acuity_index (0–100) plus a
priority_band. It answers "how soon should this case be acted on,"
which is distinct from CDRI's "how much
risk" and Magnitude's per-pattern
severities.
This endpoint replaces the retired /screen/acute surface.
The same readout is available inline from
/cdri/compute when
you pass situation/onset there; call /acuity/compute directly when
you want only the acuity block.
⚠ Not a clinical diagnosis
The acuity index is a triage-prioritization signal, not a diagnosis or a clinical urgency verdict. See the CDRI disclaimer.
Endpoint
| Field | Value |
|---|---|
| Method | POST |
| Path | /api/acuity/compute |
| Full URL | https://engine.tripod-health.com/api/acuity/compute |
| Authentication | API key (required) |
| Request body | application/json |
| Rate-limited | Yes |
Request
instruments + optional demographics behave exactly as on
/cdri/compute. Acuity adds two
inputs:
| Field | Type | Required | Description |
|---|---|---|---|
situation | object | Recommended | De-identified situational descriptors: age_bracket, injury_type, injury_region. Each must be an accepted value (see Accepted situation values); an off-list value returns 400 naming the field. |
onset | string | Recommended | Injury/onset timestamp (e.g. "2026-04-27"). The engine derives weeks-since-onset from it at the boundary and discards the raw date — only the duration flows downstream. |
as_of | string | No | Optional reference timestamp the duration is measured to. Defaults to now. Same de-identification handling as onset. |
{
"instruments": {
"oswestry": { "responses": { "item_1": 3, "item_2": 4, "item_3": 4, "item_4": 3, "item_5": 4, "item_6": 3, "item_7": 3, "item_8": 2, "item_9": 3, "item_10": 4 } },
"pain_scale": { "responses": { "item_1": 7 } }
},
"demographics": { "age_bracket": "45-54", "sex": "male", "occupation_class": "construction", "region": "OH" },
"situation": { "age_bracket": "45_54", "injury_type": "disc_herniation", "injury_region": "low_back" },
"onset": "2026-04-27"
}
situation.age_bracketuses underscores (45_54,65_plus), which is a different token set from the hyphenateddemographics.age_bracket(45-54). They are separate inputs; send the underscore form insidesituation.
De-identification of time
An onset date is a HIPAA Safe Harbor identifier; a duration is not.
The engine converts onset/as_of into weeks-since-onset at the
request boundary and never persists or logs the raw date. The rest of
the de-identification filter applies as on every endpoint — a
DOB-shaped value anywhere outside onset/as_of is still rejected with
400 DeIdentificationViolation.
Accepted situation values
situation values are validated against the active accepted-value
lists. An off-list value returns 400 ValidationError with the
offending field.
age_bracket (underscored): under_25, 25_34, 35_44, 45_54,
55_64, 65_plus.
injury_type: strain, sprain, contusion, laceration,
puncture, abrasion, fracture, dislocation, tendinopathy,
bursitis, disc_herniation, radiculopathy, nerve_compression,
crush, repetitive_strain, concussion, burn, amputation,
inflammation, nonspecific_pain.
injury_region: neck, mid_back, low_back, sacrum_coccyx,
shoulder, upper_arm, elbow, forearm, wrist, hand, fingers,
hip, thigh, knee, lower_leg, ankle, foot, toes, head,
face, chest_ribs, abdomen, pelvis, multiple_regions.
These lists are part of the engine's calibration and can be extended
over time; treat a 400 on a previously-unseen value as authoritative.
Response
Success — 200 OK
Live capture against production with ?recommend=rules (the body
above; a low-back disc herniation about five weeks post-onset). Real
engine output.
{
"composite_id": "acuity",
"acuity_index": 44.65,
"priority_band": "routine",
"components": {
"transition_risk": 0.837,
"situation_weight": 0.683,
"time_factor": 0.781
},
"weeks_since_onset": 5.31,
"time_known": true,
"matrix_version": "2026-06-02-first-pass",
"red_flags": [
{
"code": "complex_case_review",
"severity": "urgent",
"rule_id": "rec.escalation.multi_domain_catastrophic_top2",
"rule_version": "1.0.0",
"detail": "Phenotype 'multi_domain_catastrophic' appears in the top-two of the classifier's distribution.",
"triggers": {
"phenotype.top_name": "multi_domain_catastrophic",
"phenotype.second_name": "established_chronicity"
}
}
],
"confidence": {
"overall": 0.5766,
"tier": "medium",
"breakdown": {
"input_completeness": 0.5,
"imputation_variance": 1,
"model_certainty": 0.2554
}
},
"recommendations": {
"engine_version": "1.0.0",
"ruleset_version": "1.0.0",
"disclaimer": "The Trinity Engine is a decision-support tool. Output is not medical advice, not a diagnosis, not a prescription, and not a benefits determination. The calling organization is responsible for clinical governance and for the interpretation and use of these suggestions.",
"ai_summary": null,
"items": [ "... see /cdri/compute for the recommendation item shape ..." ],
"suppressed": [],
"cardinality_cap": null
},
"depth": "full",
"catalog_version": "0.13.0",
"request_id": "docs-acuity",
"timestamp": "2026-06-03T04:21:43.325271+00:00"
}
Response fields
| Field | Type | Description |
|---|---|---|
composite_id | string | Always "acuity". |
acuity_index | number | Priority of risk against time, 0.0–100.0. Higher = act sooner. |
priority_band | string | The band the index falls in: immediate, expedited, routine, or low. Branch on this rather than re-deriving from the index. |
components | object | The three diagnostic sub-signals behind the index: transition_risk (the subject's risk of transitioning to a worse trajectory), situation_weight (derived from the situational descriptors), time_factor (where the subject sits on the recovery timeline). Each 0.0–1.0. Diagnostic — display, do not re-compute the index from them. |
weeks_since_onset | number | null | The duration the engine derived from onset/as_of. null when no onset was supplied. |
time_known | boolean | true when a usable onset was supplied; false when the time factor fell back to a default. |
matrix_version | string | null | Opaque version tag for the active acuity configuration. Do not pin. |
red_flags | array | Safety escalations. Same shape as CDRI red flags. Independent of ?recommend=. |
confidence | object | Same shape as CDRI confidence. |
recommendations | object | null | Same shape and modes as CDRI recommendations. |
depth | string | Always "full". |
catalog_version | string | Catalog version served. |
request_id | string | Correlation ID. |
timestamp | string (ISO 8601 UTC) | Server time. |
Priority bands
| Band | Approx. acuity_index | Read it as |
|---|---|---|
immediate | ≥ 70 | Act now. |
expedited | 45–69 | Act soon; fast-track. |
routine | 20–44 | Standard pathway. |
low | < 20 | Monitor. |
The engine assigns priority_band for you; the cutoffs above are for
interpretation only and may be tuned over time.
Examples
curl
curl -sS -X POST "https://engine.tripod-health.com/api/acuity/compute?recommend=rules" \
-H "apikey: $ENGINE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"instruments": { "oswestry": { "responses": { "item_1": 3, "item_2": 4, "item_3": 4, "item_4": 3, "item_5": 4, "item_6": 3, "item_7": 3, "item_8": 2, "item_9": 3, "item_10": 4 } }, "pain_scale": { "responses": { "item_1": 7 } } },
"demographics": { "age_bracket": "45-54", "sex": "male", "occupation_class": "construction", "region": "OH" },
"situation": { "age_bracket": "45_54", "injury_type": "disc_herniation", "injury_region": "low_back" },
"onset": "2026-04-27"
}'
Python (requests)
# Uses the call() helper from quickstart.md.
result = call("POST", "/api/acuity/compute?recommend=rules", body)
print(f"acuity {result['acuity_index']} -> {result['priority_band']}")
print(f" weeks since onset: {result['weeks_since_onset']}")
Off-list situation value (400)
curl -sS -X POST "https://engine.tripod-health.com/api/acuity/compute" \
-H "apikey: $ENGINE_API_KEY" -H "Content-Type: application/json" \
-H "X-Request-ID: docs-acuity-bad-situation" \
-d '{"instruments":{"pain_scale":{"responses":{"item_1":5}}},"situation":{"age_bracket":"45_54","injury_type":"banana","injury_region":"low_back"},"onset":"2026-04-01"}' \
-w "\nHTTP %{http_code}\n"
Receive (400):
{
"timestamp": "2026-06-03T04:23:33.349Z",
"error": "ValidationError",
"message": "'banana' is not an accepted injury_type",
"field": "situation.injury_type",
"request_id": "docs-acuity-bad-situation"
}
Status codes
Same as /cdri/compute,
plus the situation-specific 400 ValidationError shown above.
Related
- composite-cdri-compute.md — the full composite; pass
situation/onsetthere to embed this block. - composite-magnitude-compute.md — the "how much" readout.
- composite-phenotype-classify.md — the "which pattern" readout.
Change history
| Date | Change |
|---|---|
| 2026-06-03 | Initial publication. Replaces the retired /screen/acute endpoint. |