Skip to main content

Clinical concepts

This document explains the domain model behind the API: assessment types, how scores work, the result-snapshot pattern, the shareable code system, and the controlled vocabularies (enums) you'll send and receive.

Disclaimer. The platform measures digital biomarkers of hand function. Outputs such as the arthritis pattern/progression are not a medical diagnosis. The canonical patient-facing disclaimer is exported from @digits/shared as ARTHRITIS_DISCLAIMER.

Assessment types

TypeEndpointWhat it measures
ROMPOST /assessments/romRange of motion of the wrist and finger joints (degrees) via camera + MediaPipe.
DexterityPOST /assessments/dexterityFinger-tapping speed, accuracy, and consistency. Persisted internally as FINGER_TAPPING.
PainPOST /assessments/pain-v2Self-reported pain by hand location, plus medications and management strategies.
ArthritisPOST /assessments/arthritisComposite arthritis-risk evaluation from a questionnaire + joint symptoms + (optionally) ROM/pain sources.

The stored assessmentType for dexterity is FINGER_TAPPING; read endpoints normalize it to DEXTERITY for clients. Similarly THUMB_MOVEMENTS normalizes to THUMB.

Where the scoring happens

ROM and dexterity raw kinematics are computed from camera landmarks. The biomechanics endpoints proxy frame data to a Python service for angle extraction; the assessment submission endpoints persist the already-scored results. Arthritis composite scoring is performed client-side and submitted whole — the API stores the breakdown but does not recompute it. Shared scoring helpers live in @digits/shared (scoring/handScore.ts).

Scores

  • Most scores are 0–100, higher is better (overallScore, wristScore, fingerScore, speedScore, consistencyScore, touchPrecision, arthritis sub-scores, compositeScore, healthScore).
  • Pain severity is 0–10, higher is worse (per pain level labels).
  • ROM wrist angles are in degrees. Reference ranges used by the API when scoring wrist sub-joints: extension 0–70°, flexion 0–80°.
  • Trend (provider list) is derived by comparing the two most recent daily scores: > +2improving, < −2declining, else stable. A patient needsAttention when declining or when the latest score < 40.

The result-snapshot pattern

Every shareable assessment creates an AssessmentRecord carrying a resultSnapshot — a denormalized JSON blob with the headline numbers for that assessment type. This is what GET /lookup/:code and report bundling read, so results render without loading the full child tables. GET /assessments/:id/results additionally returns the full normalized results tree (hand/joint/finger rows).

Typical snapshot keys by type:

TypeSnapshot keys
ROMoverallScore, wristScore, fingerScore, extensionDeg, flexionDeg, lightingQuality
DexterityoverallScore, speedScore, touchPrecision/accuracyScore, consistencyScore, cycleCount, totalTouches, sequencesCompleted, timeTo10Sequences, averageFrequency, sequenceAccuracy
PainoverallScore (derived 100·(1 − maxSeverity/10)), mode, maxSeverity, painType, timeOfDay, entries[], strategies[], medications[], comments
ArthritiscompositeScore, progressionLevel, patternType, romDeficitScore, painBurdenScore, functionalScore, stiffnessScore, affectedJointCount, clinicalFlags[]

Shareable codes

Every assessment and report gets a 6-character code drawn from ABCDEFGHJKMNPQRSTUVWXYZ23456789 — ambiguous characters (0/O, 1/I/L) are excluded so codes are easy to read aloud and type. Codes are:

  • Case-insensitive and accepted with or without the middle dash: XHE7JRxhe-7jrXHE-7JR. formattedCode is the dashed form for display.
  • Expiring after 90 days when anonymous; permanent once claimed by an authenticated user.
  • The lookup key for public retrieval, claiming, emailing, and report bundling.

Lighting quality

Camera assessments record a three-state lightingQuality (GOOD / FAIR / POOR) plus optional lightingMetrics (meanY, stdY) so results can be interpreted in context of capture conditions.

Enums

These controlled vocabularies are defined as Zod enums in @digits/shared and re-exported by @digits/clinical-sdk. Send the enum value (the uppercase token), not the label.

Hand / digits / locations

  • Hand: LEFT, RIGHT (ROM/dexterity); BOTH is also valid for pain/arthritis.
  • HandDigit: THUMB, INDEX, MIDDLE, RING, LITTLE.
  • DigitLocation: TIP, DIP, PIP, MCP, CMC, PALM, DORSAL.

Pain

  • PainType: SHARP, DULL_ACHING, BURNING, THROBBING, TINGLING_NUMBNESS, STIFFNESS, SWELLING.
  • PainTimeOfDay: MORNING, AFTERNOON, EVENING, NIGHT, CONSTANT.
  • PainAssessmentMode: QUICK, DETAILED.
  • PainAreaType: DIGIT_JOINT, PALM, DORSAL, WRIST.
  • ManagementStrategy: ELEVATION, REST, ICE, COMPRESSION, SPLINTING, OTHER.
  • Pain severity (0–10): 0 No pain · 1 Minimal · 2 Mild · 3 Uncomfortable · 4 Moderate · 5 Distracting · 6 Distressing · 7 Unmanageable · 8 Intense · 9 Severe · 10 Worst possible.

Arthritis

  • MorningStiffnessDuration: NONE, UNDER_15_MIN, MIN_15_TO_30, MIN_30_TO_60, OVER_60_MIN.
  • DifficultyLevel: NONE, MILD, MODERATE, SEVERE, UNABLE (scored 100/75/50/25/0).
  • FunctionalTask: GRIPPING, PINCHING, TURNING_KEY, OPENING_JAR, WRITING, BUTTONING, CUTTING_FOOD, CARRYING, WRINGING, TYPING.
  • SymptomOnset: GRADUAL_MONTHS, GRADUAL_YEARS, SUDDEN_WEEKS, FLARE_UPS.
  • SymptomSymmetry: LEFT_ONLY, RIGHT_ONLY, BOTH_SYMMETRIC, BOTH_ASYMMETRIC.
  • ArthritisPattern: UNDETERMINED, OA_PATTERN, RA_PATTERN, MIXED.
  • Progression level (0–4): 0 No Concerns · 1 Minimal · 2 Moderate · 3 Significant · 4 Severe.

Journal

  • entryType: PRE_ASSESSMENT, POST_ASSESSMENT, AD_HOC_CHECK_IN, INITIAL_INTAKE.

Data domains (database)

Backed by PostgreSQL via Prisma (apps/api/prisma/schema.prisma, ~60 tables, BigInt PKs):

  • Identityusers, user_roles (Auth0 link via auth0Sub), contacts (patients).
  • Assessmentsrom_assessment_result, dexterity_assessment_result, pain_assessment_session, arthritis_evaluation, each with hand/joint/finger child rows.
  • Recordsassessment_records (the shareable code + snapshot layer).
  • Reportsreports (bundled, with view counts and AI explanation).
  • Journalhand_journal_entries.
  • Billingsubscriptions (Stripe-backed, tiers CORE/PLUS).