Loading documentation

Access required

Your account doesn't have access to the documentation. Contact your administrator.

Sign out
Skip to main content

Örebro Musculoskeletal Pain Screening

Status: stable Category: pain Added: 2026-04-20 Last reviewed: 2026-04-21

Summary

The Örebro Musculoskeletal Pain Screening Questionnaire (OMPSQ) is Trinity's canonical yellow-flag screen for musculoskeletal pain. A 21-item self-report instrument covering pain intensity, function, mood, and work expectations — designed to flag psychosocial risk of delayed recovery, not to diagnose pain itself. Its presence is typically what triggers deeper assessment downstream.

Resource identity

FieldValue
Categorypain
Resourceorebro
Instrument IDorebro
Rubric version1.0.0
Path prefix/api/pain/orebro

Operations

OperationMethodPathContract
QuestionsGET/api/pain/orebro/questionspatterns-questions.md
ScorePOST/api/pain/orebro/scorepatterns-score.md

Items

21 items, each on a 0–10 scale.

IDPrompt (paraphrased)
item_1Current pain intensity.
item_2Average pain in the last 3 months.
item_3Frequency of pain (never to always).
item_4Bother when trying to relax due to pain.
item_5Ability to walk.
item_6Ability to sleep normally.
item_7Ability to do usual activities.
item_8Ability to do light work for an hour.
item_9How anxious or tense you usually feel.
item_10Depressed or low mood.
item_11Perceived likelihood of working in 6 months.
item_12Expectation of returning to normal activities.
item_13Belief that increased pain indicates more damage.
item_14Belief that physical activity worsens pain.
item_15Avoidance of normal activities because of pain.
item_16Ability to self-manage the pain.
item_17Perceived fair chance of continuing to work.
item_18Support from co-workers / supervisor (reversed).
item_19Ability to control pain (reversed).
item_20Dedication to work duties (reversed).
item_21Fear-avoidance of physical activities.

Every item accepts integer values 0 through 10. Items marked "(reversed)" are worded so that higher numeric responses still contribute to a higher risk score under Trinity's scoring — no caller-side reversal is needed.

Authoritative item text comes from GET /api/pain/orebro/questions. The text above is paraphrased for documentation; render the live response, not this document.

Scoring

FieldValue
Methodweighted_sum with every weight equal to 1 (equivalent to a simple sum over the 21 items).
Score range0210. Realistic clinical scores concentrate well below the upper bound.

The finding.raw.method field in the /score response confirms the method actually applied.

Bands

BandRange (inclusive)Clinical meaning
low089Low psychosocial risk for delayed recovery.
medium90105Elevated risk; consider further assessment.
high106210High risk; further assessment indicated.

Thresholds follow widely-used OMPSQ cutoffs for distinguishing low versus elevated risk. Band names are scoring categories, not audience-facing display labels.

Required items

Every item (item_1 through item_21) is required. A /score call missing any required item returns 400 ValidationError with a missing_items array. See patterns-score.md.

Worked example

Every item answered with 5. For additional per-language scaffolding (retry handling, auth, error envelope), see quickstart.md; for the full shared /score contract see patterns-score.md.

Send:

POST /api/pain/orebro/score HTTP/1.1
Host: engine.tripod-health.com
apikey: $ENGINE_API_KEY
Content-Type: application/json
X-Request-ID: docs-orebro-score-basic

{
"responses": {
"item_1": 5, "item_2": 5, "item_3": 5, "item_4": 5, "item_5": 5,
"item_6": 5, "item_7": 5, "item_8": 5, "item_9": 5, "item_10": 5,
"item_11": 5, "item_12": 5, "item_13": 5, "item_14": 5, "item_15": 5,
"item_16": 5, "item_17": 5, "item_18": 5, "item_19": 5, "item_20": 5,
"item_21": 5
}
}

Receive (200 OK):

{
"instrument": "orebro",
"category": "pain",
"finding": {
"algorithm_id": "orebro",
"algorithm_version": "1.0.0",
"score": 105,
"band": "medium",
"raw": {
"rubric_version": "1.0.0",
"responded_items": 21
},
"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-orebro-score-basic",
"timestamp": "2026-04-21T23:14:52.684353+00:00"
}

Computation: the Örebro is a weighted sum; every item answered with 5 yields 105, which lands in the medium band (see the Bands table).

Calling in your language

curl

curl -sS -X POST "https://engine.tripod-health.com/api/pain/orebro/score" \
-H "apikey: $ENGINE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"responses":{"item_1":5,"item_2":5,"item_3":5,"item_4":5,"item_5":5,"item_6":5,"item_7":5,"item_8":5,"item_9":5,"item_10":5,"item_11":5,"item_12":5,"item_13":5,"item_14":5,"item_15":5,"item_16":5,"item_17":5,"item_18":5,"item_19":5,"item_20":5,"item_21":5}}'

Python (requests)

# Uses the call() helper from quickstart.md.
responses = {f"item_{i}": 5 for i in range(1, 22)}
result = call("POST", "/api/pain/orebro/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: 21 }, (_, i) => [`item_${i + 1}`, 5]),
);
const result = await call("POST", "/api/pain/orebro/score", { responses });
console.log(result.finding.score, result.finding.band);

TypeScript

// Uses the typed call<T>() helper from quickstart.md.
// ScoreResponse is the shared type from patterns-score.md.
const responses = Object.fromEntries(
Array.from({ length: 21 }, (_, i) => [`item_${i + 1}`, 5]),
);
const result = await call<ScoreResponse>(
"POST",
"/api/pain/orebro/score",
{ responses },
);

Go

// Uses the call() helper from quickstart.md.
responses := make(map[string]int, 21)
for i := 1; i <= 21; i++ {
responses[fmt.Sprintf("item_%d", i)] = 5
}
result, err := call("POST", "/api/pain/orebro/score",
map[string]any{"responses": responses}, 3)
if err != nil {
panic(err)
}
finding := result["finding"].(map[string]any)
fmt.Printf("orebro: %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 <= 21; i++) {
if (i > 1) body.append(",");
body.append("\"item_").append(i).append("\":5");
}
body.append("}}");
String result = call("POST", "/api/pain/orebro/score", body.toString(), 3);
System.out.println(result);

C# (.NET HttpClient)

// Uses the Call() helper from quickstart.md.
var responses = Enumerable.Range(1, 21)
.ToDictionary(i => $"item_{i}", _ => 5);
var result = await Call(HttpMethod.Post, "/api/pain/orebro/score",
new { responses });

var finding = result.GetProperty("finding");
Console.WriteLine($"orebro: {finding.GetProperty("score").GetDouble()} ({finding.GetProperty("band").GetString()})");

PowerShell

# Uses the Invoke-Engine helper from quickstart.md.
$responses = @{}
1..21 | ForEach-Object { $responses["item_$_"] = 5 }
$result = Invoke-Engine -Method Post -Path "/api/pain/orebro/score" -Body @{ responses = $responses }
"orebro: $($result.finding.score) ($($result.finding.band))"

Clinical interpretation

  • What it screens. Psychosocial risk of delayed recovery from musculoskeletal pain. The Örebro is a screening tool, not a diagnostic one. A high band flags "look further," not "this is chronic pain."
  • Who it is for. Typically used early after onset of a work-related or new musculoskeletal complaint, to stratify who needs structured psychosocial intervention.
  • What it is not. Not a measure of pain intensity alone (use pain_scale for that), not a diagnosis of depression or anxiety (use depression_screen / anxiety_screen for those), not a determination of work capacity.

Trinity returns a score and a band; any clinical decision built on top of it belongs to the caller.

Intended use

  • Early-onset screening for musculoskeletal complaints when the caller needs to decide whether to escalate to structured psychosocial assessment.
  • Feeding the CDRI composite as the canonical pain-domain yellow-flag signal.
  • Tracking change over time. A repeat Örebro weeks later can be compared to the first to see whether psychosocial risk is shifting; the score and band are stable contracts suitable for time-series.

Mistaken use

  • Do not use this for acute pain intensity. It is a multi-domain screen; the score conflates pain, function, mood, and expectations. Use pain_scale for a pure intensity measure.
  • Do not interpret high as a diagnosis. It flags risk of delayed recovery. The clinical follow-up (depression, kinesiophobia, etc.) is determined by the caller, potentially with other Trinity instruments.
  • Do not pre-reverse any items. Trinity scores every item in its native orientation; sending reversed values changes the result incorrectly.
  • Do not compare scores across rubric versions. A bump to version can change item weights or band cutoffs. Pin your comparison analyses to a single rubric version and refresh when it bumps.

Debugging

  1. Capture request_id. Present in every response body.
  2. 400 ValidationError with missing_items. Send all 21 items — all are required.
  3. Score seems too high or too low by exactly the score of one item. Confirm every id is in the response map; a missed item_N silently contributes 0 to the sum in the pipeline's internal math, but the strict /score gate catches this before scoring runs (raising ValidationError). If you still see an off-by-one-item score, double-check your client's body assembly.
  4. Band appears unknown in a response. The score fell outside every defined band range. Not possible under the current rubric (0–210 covers the whole range), but if you see it, report the request id.

Change history

DateChange
2026-04-20Initial publication.