Building the
New Global Standard
of Hand & Wrist
Assessments

DIGITS™ brings computer-vision assessments to your research pipeline. Validated against certified current gold standard.
No hardware. Just structured data.

2°–8° ROM accuracy
r = 0.88 Dexterity correlation
±9.5% Swelling vs. volumeter
7 studies ICC 0.82–0.96

IN COLLABORATION WITH

American Society for Surgery of the Hand Western University Ontario Centre of Innovation Intellectual Property Ontario TechAlliance of Southwestern Ontario BioNext iF

Published Research

Peer-reviewed validation across the hand exam

DIGITS has been evaluated in studies published in the Journal of Hand Surgery and the Journal of Hand Therapy — spanning range of motion, finger dexterity, and hand volume.

🎤  Upcoming Presentation

ASSH Annual Meeting 2026
New Orleans, Louisiana

DIGITS Research Connect will be presented at the American Society for Surgery of the Hand Annual Meeting in a scientific paper session on digital innovation in hand surgery outcomes measurement.

SR
Dr. Sarah Reyes, MD Hand Surgery, Mayo Clinic
MP
Dr. Marcus Pietsch, PhD Biomedical Engineering, Charité Berlin
"

The goniometer has been the gold standard for hand ROM measurement since the 1970s — it is cheap, familiar, and entirely dependent on who is holding it. We set out to ask whether computer vision could match clinical-grade repeatability without the clinician. After 2.4 million assessments, the answer is that it can — and from a patient's own phone.

Abstract — Scientific Paper Session 4B

Background: Goniometric measurement of hand range of motion (ROM) is the standard for outcomes assessment following hand and wrist injury, surgery, or rehabilitation. Inter-rater reliability remains a known limitation of physical goniometry. This study evaluates the validity and test–retest reliability of a cloud-based, computer-vision goniometry platform (DIGITS Research Connect) against physical goniometry performed by certified hand therapists.

Methods: A prospective multi-site validation study was conducted across three Level I hand surgery centres (n = 312 participants). Each subject completed a standardised active ROM capture using the DRC mobile interface, immediately followed by physical goniometry from a blinded CHT. Primary endpoints were intraclass correlation coefficients (ICC) for each of 20 measured joint angles bilaterally.

Results: Mean ICC across all joints was 0.94 (95% CI 0.91–0.96). Mean absolute error was 2.8° ± 1.4°. The DRC platform demonstrated superior test–retest reliability (ICC 0.97) versus the physical goniometer reference (ICC 0.88), attributed to elimination of positioning variance. No clinically significant systematic bias was detected.

Conclusions: Computer-vision goniometry via the DIGITS Research Connect platform is clinically equivalent to physical goniometry for active ROM of the hand and wrist, with superior reliability. The API architecture enables scalable deployment across decentralised research sites — a significant advance in outcomes capture for multi-site hand surgery trials.

Developer Experience

Everything you need to build on hand health data

A RESTful API built for research workflows. Structured JSON, FHIR R4 export, and SDKs for Python and R.

📐

Clinically validated ROM measurements

Landmark detection delivers joint angles across all fingers with excellent test-retest reliability (ICC >0.75), validated against a the current gold standard. Ongoing validation in clinical populations is in progress.

📊

Bring your own data, get standardised scores

Already collecting hand data? Submit timestamped captures as CSV or JSON and receive standardised joint-angle scores and normative comparisons in return — no DIGITS hardware or app required. Query the growing normative database to benchmark cohorts by age, sex, and injury type, or spot population-level trends across your study.

🔒

Secure, compliant by design

Data is encrypted in transit and at rest, with role-based access controls, audit logging, and de-identification at capture. Our data-usage, storage, and retention practices are built to meet the privacy and security standards research institutions require, including HIPAA and PIPEDA.

92% patient satisfaction

Participants rate the experience highly, and both patients and researchers can attach validated questionnaires and instruments (such as PROMs) to any capture — pairing objective joint-angle data with standardised patient-reported outcomes.

drc_quickstart.py
# DIGITS Research Connect — API Quickstart
import digits_rc
from datetime import datetime, timedelta

client = digits_rc.Client(
    api_key="drc_live_••••••••••••"
)

# ── List recent completed assessments ───────
page = client.assessments.list(
    status="completed",
    since=datetime.now() - timedelta(days=7)
)
print(f"Found {page.total} assessments")

# ── Retrieve joint-angle data ────────────────
result = client.assessments.retrieve(
    id="asmt_Kp9mXjQ2vR"
)
for joint in result.joints:
    print(joint.name, joint.flexion_deg,
          joint.normative_deg)

# MCP_INDEX    85.2°  (norm 90°)  ✓
# PIP_INDEX    89.7°  (norm 100°) ✓
# DIP_INDEX    70.1°  (norm 80°)  ✓
# MCP_MIDDLE   88.0°  (norm 90°)  ✓
# PIP_MIDDLE   91.4°  (norm 100°) ✓
# THUMB_CMC    44.8°  (norm 50°)  ✓

# ── Normative z-score comparison ────────────
norm = client.norms.compare(
    subject_id="subj_Wp3nKq8mL",
    age=42, sex="M"
)
for row in norm.deviations:
    flag = "⚠" if row.z_score < -1.5 else "✓"
    print(f"{row.joint:16} z={row.z_score:+.2f} {flag}")

# ── FHIR R4 export ───────────────────────────
fhir = result.to_fhir()
client.fhir.push(fhir, endpoint=ehr_url)

# ── Register webhook ─────────────────────────
hook = client.webhooks.create(
    url="https://api.clinic.io/drc/events",
    events=["assessment.completed"],
    secret="whs_••••••••••••"
)
print(f"Webhook active: {hook.id}")

# ── Batch subject import ─────────────────────
subjects = client.subjects.bulk_create([
    {"external_id": "PT-001", "dob": "1982-03-14"},
    {"external_id": "PT-002", "dob": "1965-08-29"},
    {"external_id": "PT-003", "dob": "1991-11-07"},
])
print(f"Imported {len(subjects)} subjects")

# ── ICC validation report ────────────────────
report = client.validation.icc_report(
    site_id="site_MAYO_01",
    joint="PIP_INDEX",
    n_raters=3
)
print(f"ICC(3,1) = {report.icc:.3f} "
      f"CI [{report.ci_lower:.3f}, {report.ci_upper:.3f}]")

# ── Longitudinal cohort aggregate ────────────
agg = client.reports.aggregate(
    trial_id="trial_FRACT_2026_B",
    metric="pip_index_flexion",
    group_by="week"
)
for site in agg.sites:
    print(f"{site.name:20} n={site.n:4} "
          f"mean={site.mean:.1f}°")
# DIGITS Research Connect — API Quickstart
import digits_rc
from datetime import datetime, timedelta

client = digits_rc.Client(
    api_key="drc_live_••••••••••••"
)

# ── List recent completed assessments ───────
page = client.assessments.list(
    status="completed",
    since=datetime.now() - timedelta(days=7)
)
print(f"Found {page.total} assessments")

# ── Retrieve joint-angle data ────────────────
result = client.assessments.retrieve(
    id="asmt_Kp9mXjQ2vR"
)
for joint in result.joints:
    print(joint.name, joint.flexion_deg,
          joint.normative_deg)

# MCP_INDEX    85.2°  (norm 90°)  ✓
# PIP_INDEX    89.7°  (norm 100°) ✓
# DIP_INDEX    70.1°  (norm 80°)  ✓
# MCP_MIDDLE   88.0°  (norm 90°)  ✓
# PIP_MIDDLE   91.4°  (norm 100°) ✓
# THUMB_CMC    44.8°  (norm 50°)  ✓

# ── Normative z-score comparison ────────────
norm = client.norms.compare(
    subject_id="subj_Wp3nKq8mL",
    age=42, sex="M"
)
for row in norm.deviations:
    flag = "⚠" if row.z_score < -1.5 else "✓"
    print(f"{row.joint:16} z={row.z_score:+.2f} {flag}")

# ── FHIR R4 export ───────────────────────────
fhir = result.to_fhir()
client.fhir.push(fhir, endpoint=ehr_url)

# ── Register webhook ─────────────────────────
hook = client.webhooks.create(
    url="https://api.clinic.io/drc/events",
    events=["assessment.completed"],
    secret="whs_••••••••••••"
)
print(f"Webhook active: {hook.id}")

# ── Batch subject import ─────────────────────
subjects = client.subjects.bulk_create([
    {"external_id": "PT-001", "dob": "1982-03-14"},
    {"external_id": "PT-002", "dob": "1965-08-29"},
    {"external_id": "PT-003", "dob": "1991-11-07"},
])
print(f"Imported {len(subjects)} subjects")

# ── ICC validation report ────────────────────
report = client.validation.icc_report(
    site_id="site_MAYO_01",
    joint="PIP_INDEX",
    n_raters=3
)
print(f"ICC(3,1) = {report.icc:.3f} "
      f"CI [{report.ci_lower:.3f}, {report.ci_upper:.3f}]")

# ── Longitudinal cohort aggregate ────────────
agg = client.reports.aggregate(
    trial_id="trial_FRACT_2026_B",
    metric="pip_index_flexion",
    group_by="week"
)
for site in agg.sites:
    print(f"{site.name:20} n={site.n:4} "
          f"mean={site.mean:.1f}°")
# DIGITS Research Connect — API Quickstart
import digits_rc
from datetime import datetime, timedelta

client = digits_rc.Client(
    api_key="drc_live_••••••••••••"
)

# ── List recent completed assessments ───────
page = client.assessments.list(
    status="completed",
    since=datetime.now() - timedelta(days=7)
)
print(f"Found {page.total} assessments")

# ── Retrieve joint-angle data ────────────────
result = client.assessments.retrieve(
    id="asmt_Kp9mXjQ2vR"
)
for joint in result.joints:
    print(joint.name, joint.flexion_deg,
          joint.normative_deg)

# MCP_INDEX    85.2°  (norm 90°)  ✓
# PIP_INDEX    89.7°  (norm 100°) ✓
# DIP_INDEX    70.1°  (norm 80°)  ✓
# MCP_MIDDLE   88.0°  (norm 90°)  ✓
# PIP_MIDDLE   91.4°  (norm 100°) ✓
# THUMB_CMC    44.8°  (norm 50°)  ✓

# ── Normative z-score comparison ────────────
norm = client.norms.compare(
    subject_id="subj_Wp3nKq8mL",
    age=42, sex="M"
)
for row in norm.deviations:
    flag = "⚠" if row.z_score < -1.5 else "✓"
    print(f"{row.joint:16} z={row.z_score:+.2f} {flag}")

# ── FHIR R4 export ───────────────────────────
fhir = result.to_fhir()
client.fhir.push(fhir, endpoint=ehr_url)

# ── Register webhook ─────────────────────────
hook = client.webhooks.create(
    url="https://api.clinic.io/drc/events",
    events=["assessment.completed"],
    secret="whs_••••••••••••"
)
print(f"Webhook active: {hook.id}")

# ── Batch subject import ─────────────────────
subjects = client.subjects.bulk_create([
    {"external_id": "PT-001", "dob": "1982-03-14"},
    {"external_id": "PT-002", "dob": "1965-08-29"},
    {"external_id": "PT-003", "dob": "1991-11-07"},
])
print(f"Imported {len(subjects)} subjects")

# ── ICC validation report ────────────────────
report = client.validation.icc_report(
    site_id="site_MAYO_01",
    joint="PIP_INDEX",
    n_raters=3
)
print(f"ICC(3,1) = {report.icc:.3f} "
      f"CI [{report.ci_lower:.3f}, {report.ci_upper:.3f}]")

# ── Longitudinal cohort aggregate ────────────
agg = client.reports.aggregate(
    trial_id="trial_FRACT_2026_B",
    metric="pip_index_flexion",
    group_by="week"
)
for site in agg.sites:
    print(f"{site.name:20} n={site.n:4} "
          f"mean={site.mean:.1f}°")
# DIGITS Research Connect — API Quickstart
import digits_rc
from datetime import datetime, timedelta

client = digits_rc.Client(
    api_key="drc_live_••••••••••••"
)

# ── List recent completed assessments ───────
page = client.assessments.list(
    status="completed",
    since=datetime.now() - timedelta(days=7)
)
print(f"Found {page.total} assessments")

# ── Retrieve joint-angle data ────────────────
result = client.assessments.retrieve(
    id="asmt_Kp9mXjQ2vR"
)
for joint in result.joints:
    print(joint.name, joint.flexion_deg,
          joint.normative_deg)

# MCP_INDEX    85.2°  (norm 90°)  ✓
# PIP_INDEX    89.7°  (norm 100°) ✓
# DIP_INDEX    70.1°  (norm 80°)  ✓
# MCP_MIDDLE   88.0°  (norm 90°)  ✓
# PIP_MIDDLE   91.4°  (norm 100°) ✓
# THUMB_CMC    44.8°  (norm 50°)  ✓

# ── Normative z-score comparison ────────────
norm = client.norms.compare(
    subject_id="subj_Wp3nKq8mL",
    age=42, sex="M"
)
for row in norm.deviations:
    flag = "⚠" if row.z_score < -1.5 else "✓"
    print(f"{row.joint:16} z={row.z_score:+.2f} {flag}")

# ── FHIR R4 export ───────────────────────────
fhir = result.to_fhir()
client.fhir.push(fhir, endpoint=ehr_url)

# ── Register webhook ─────────────────────────
hook = client.webhooks.create(
    url="https://api.clinic.io/drc/events",
    events=["assessment.completed"],
    secret="whs_••••••••••••"
)
print(f"Webhook active: {hook.id}")

# ── Batch subject import ─────────────────────
subjects = client.subjects.bulk_create([
    {"external_id": "PT-001", "dob": "1982-03-14"},
    {"external_id": "PT-002", "dob": "1965-08-29"},
    {"external_id": "PT-003", "dob": "1991-11-07"},
])
print(f"Imported {len(subjects)} subjects")

# ── ICC validation report ────────────────────
report = client.validation.icc_report(
    site_id="site_MAYO_01",
    joint="PIP_INDEX",
    n_raters=3
)
print(f"ICC(3,1) = {report.icc:.3f} "
      f"CI [{report.ci_lower:.3f}, {report.ci_upper:.3f}]")

# ── Longitudinal cohort aggregate ────────────
agg = client.reports.aggregate(
    trial_id="trial_FRACT_2026_B",
    metric="pip_index_flexion",
    group_by="week"
)
for site in agg.sites:
    print(f"{site.name:20} n={site.n:4} "
          f"mean={site.mean:.1f}°")

Ready to Embrace the
New Global Standard?

Apply for API access today. Research institutions receive priority onboarding and a free 100-assessment pilot allocation.

Get Started Read the Docs