Neck Disability Index
Status:
stableCategory:functionAdded:2026-04-20Last reviewed:2026-04-21
Summary
The Neck Disability Index (NDI) is Trinity's cervical-specific
functional disability measure. Ten items, each scored 0–5,
producing a total of 0–100 after a ×2 weight per item. Higher
score means more disability.
Structurally similar to oswestry
(lumbar), but with different item content and a different scoring
formula. They are not interchangeable.
Resource identity
| Field | Value |
|---|---|
| Category | function |
| Resource | neck_disability |
| Instrument ID | neck_disability |
| Rubric version | 1.0.0 |
| Path prefix | /api/function/neck_disability |
Operations
| Operation | Method | Path | Contract |
|---|---|---|---|
| Questions | GET | /api/function/neck_disability/questions | patterns-questions.md |
| Score | POST | /api/function/neck_disability/score | patterns-score.md |
Items
Ten items, each on a 0–5 scale.
| ID | Prompt (paraphrased) |
|---|---|
item_1 | Pain intensity. |
item_2 | Personal care (washing, dressing). |
item_3 | Lifting. |
item_4 | Reading. |
item_5 | Headaches. |
item_6 | Concentration. |
item_7 | Work. |
item_8 | Driving. |
item_9 | Sleeping. |
item_10 | Recreation. |
Answer choices per item:
| Value | Label |
|---|---|
0 | No pain / no limitation |
1 | Very mild |
2 | Moderate |
3 | Fairly severe |
4 | Very severe |
5 | Worst imaginable / unable |
Scoring
| Field | Value |
|---|---|
| Method | weighted_sum with every weight set to 2. Equivalent to (sum of 0–5 responses) × 2. |
| Score range | 0 – 100. |
The weighted_sum method with uniform weight of 2 produces the
same result as the published NDI convention of
(sum × 2) = percentage disability, for a 0–100% output.
Bands
| Band | Range (inclusive) | Clinical meaning |
|---|---|---|
none | 0 – 8 | No / minimal disability. |
mild | 10 – 28 | Mild disability. |
moderate | 30 – 48 | Moderate disability. |
severe | 50 – 68 | Severe disability. |
complete | 70 – 100 | Complete disability. |
Band ranges are designed around the (sum × 2) output. Because the
multiplier is 2, scores are always even integers (0, 2, 4,
..., 100), so the "gaps" at 9, 29, 49, 69 between bands
are unreachable in practice.
Required items
All ten items are required for a strict /score call.
Worked example
Every item answered with 3 ("fairly severe"). See
quickstart.md for per-language scaffolding and
patterns-score.md for the shared /score
contract.
Send:
POST /api/function/neck_disability/score HTTP/1.1
Host: engine.tripod-health.com
apikey: $ENGINE_API_KEY
Content-Type: application/json
X-Request-ID: docs-neck_disability-score-basic
{
"responses": {
"item_1": 3, "item_2": 3, "item_3": 3, "item_4": 3, "item_5": 3,
"item_6": 3, "item_7": 3, "item_8": 3, "item_9": 3, "item_10": 3
}
}
Receive (200 OK):
{
"instrument": "neck_disability",
"category": "function",
"finding": {
"algorithm_id": "neck_disability",
"algorithm_version": "1.0.0",
"score": 60,
"band": "severe",
"raw": {
"rubric_version": "1.0.0",
"responded_items": 10
},
"context": null,
"imputed": false,
"sd": null,
"prior_source": null
},
"confidence": {
"overall": 1,
"tier": "high",
"breakdown": {
"input_completeness": 1,
"imputation_variance": null,
"model_certainty": null
}
},
"recommendations": null,
"depth": "basic",
"catalog_version": "0.13.0",
"request_id": "docs-neck_disability-score-basic",
"timestamp": "2026-04-21T23:14:56.756123+00:00"
}
Computation: weighted sum — sum(3 × 2 for i in 1..10) = 60, lands in
the severe band (50–68). Every item at 0 yields 0 (none);
every item at 5 yields 100 (complete).
Calling in your language
curl
curl -sS -X POST "https://engine.tripod-health.com/api/function/neck_disability/score" \
-H "apikey: $ENGINE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"responses":{"item_1":3,"item_2":3,"item_3":3,"item_4":3,"item_5":3,"item_6":3,"item_7":3,"item_8":3,"item_9":3,"item_10":3}}'
Python (requests)
# Uses the call() helper from quickstart.md.
responses = {f"item_{i}": 3 for i in range(1, 11)}
result = call("POST", "/api/function/neck_disability/score", {"responses": responses})
print(result["finding"]["score"], result["finding"]["band"])
Node.js (native fetch)
// Uses the call() helper from quickstart.md.
const responses = Object.fromEntries(
Array.from({ length: 10 }, (_, i) => [`item_${i + 1}`, 3]),
);
const result = await call("POST", "/api/function/neck_disability/score", { responses });
console.log(result.finding.score, result.finding.band);
TypeScript
// Uses the typed call<T>() helper from quickstart.md.
const responses = Object.fromEntries(
Array.from({ length: 10 }, (_, i) => [`item_${i + 1}`, 3]),
);
const result = await call<ScoreResponse>(
"POST",
"/api/function/neck_disability/score",
{ responses },
);
Go
// Uses the call() helper from quickstart.md.
responses := make(map[string]int, 10)
for i := 1; i <= 10; i++ {
responses[fmt.Sprintf("item_%d", i)] = 3
}
result, err := call("POST", "/api/function/neck_disability/score",
map[string]any{"responses": responses}, 3)
if err != nil {
panic(err)
}
finding := result["finding"].(map[string]any)
fmt.Printf("neck_disability: %v (%v)\n", finding["score"], finding["band"])
Java
// Uses the call() helper from quickstart.md.
StringBuilder body = new StringBuilder("{\"responses\":{");
for (int i = 1; i <= 10; i++) {
if (i > 1) body.append(",");
body.append("\"item_").append(i).append("\":3");
}
body.append("}}");
String result = call("POST", "/api/function/neck_disability/score", body.toString(), 3);
System.out.println(result);
C# (.NET HttpClient)
// Uses the Call() helper from quickstart.md.
var responses = Enumerable.Range(1, 10)
.ToDictionary(i => $"item_{i}", _ => 3);
var result = await Call(HttpMethod.Post,
"/api/function/neck_disability/score",
new { responses });
var finding = result.GetProperty("finding");
Console.WriteLine($"neck_disability: {finding.GetProperty("score").GetDouble()} ({finding.GetProperty("band").GetString()})");
PowerShell
# Uses the Invoke-Engine helper from quickstart.md.
$responses = @{}
1..10 | ForEach-Object { $responses["item_$_"] = 3 }
$result = Invoke-Engine -Method Post -Path "/api/function/neck_disability/score" -Body @{ responses = $responses }
"neck_disability: $($result.finding.score) ($($result.finding.band))"
Clinical interpretation
- What it measures. Self-reported functional disability attributed to neck pain, across ten activities of daily living.
- Higher is worse. Disability increases with score.
- Percentage scale. Trinity's output is already on a
0–100scale; no further normalization is needed. - Comparison to ODI. NDI and ODI share the ten-item structure
and
0–100output, but ask about different body regions and have different band cutoffs. A subject who scores50%on ODI and50%on NDI has different clinical implications depending on the condition.
Intended use
- Cervical outcome tracking for neck pain, whiplash, or cervical-radicular conditions.
- Baseline vs. follow-up after interventions targeting the neck.
- Feeding the CDRI composite as the cervical function signal.
Mistaken use
- Do not use this for lumbar or upper-extremity complaints. Use
oswestryorquick_dashinstead. - Do not confuse NDI and ODI numerically. They produce similar
0–100outputs but with different band cutoffs and different item content.50%on ODI is not equivalent to50%on NDI. - Do not apply a
×2conversion client-side. Trinity does it. A double-applied conversion pushes the score above100.
Debugging
- Capture
request_id. Present in every response body. - Score is exactly half of what you expected. You likely
pre-multiplied by
2on the client; drop the client-side multiplier. - Score is exactly double what you expected. You may be
interpreting the raw sum (
0–50) as the score; Trinity returns the×2conversion. Check thefinding.raw.methodfield on the response — it saysweighted_sum, and the weights are2per item. 400 ValidationErrorwithmissing_items. Send all ten items.
Related
- patterns-questions.md, patterns-score.md — shared contracts.
- instruments-oswestry.md — ODI; lumbar analog. Same shape, different content.
- instruments-quick_dash.md — upper-extremity function.
- instruments-lower_extremity_function.md — LEFS; lower-extremity function.
- composite-cdri-compute.md — composite.
Change history
| Date | Change |
|---|---|
| 2026-04-20 | Initial publication. |