Skip to main content

Digits Health — Clinical API Documentation

The Clinical API is the Fastify 5 service (apps/api) that backs the Digits Health hand rehabilitation platform. It persists assessments, patient records, journals, reports, and subscriptions to PostgreSQL (via Prisma), proxies camera-based biomechanics analysis to a Python service, and exposes a real-time AI voice orchestrator over WebSocket.

This folder is the source of truth for integrating with the API.

Contents

DocumentWhat's inside
Getting startedBase URLs, environments, your first request, conventions.
AuthenticationAuth0 RS256 JWTs, roles, optional vs. required auth, dev mode.
API referenceEvery endpoint, grouped by route, with request/response shapes.
Clinical conceptsAssessment types, scoring, enums, the result-snapshot model, codes.
ErrorsError envelope, status codes, and handling guidance.
WebhooksStripe billing webhook events and verification.
OpenAPI specMachine-readable OpenAPI 3.1 definition for codegen / Postman / Swagger.

SDK

A first-party, fully-typed TypeScript client is available at packages/clinical-sdk (@digits/clinical-sdk). Prefer it over hand-rolled fetch calls — it handles auth, retries, timeouts, and typed errors for you.

import { DigitsClient } from '@digits/clinical-sdk';

const digits = new DigitsClient({
  baseUrl: 'https://api.digitshealth.com/api',
  token: () => getAccessToken(),
});

const rom = await digits.assessments.submitRom({ hand: 'RIGHT', overallScore: 82 });

Architecture at a glance

Browser ── Next.js BFF proxy ──► Clinical API (Fastify, :3001) ──► PostgreSQL (Prisma)
                                       │
                                       ├─► Python biomechanics service (HTTP)
                                       ├─► Google Cloud TTS / Gemini (AI)
                                       └─► Stripe (billing)

The web app never calls the API directly from the browser — it forwards through a BFF proxy that injects the Auth0 access token. External/native integrations call the API directly with their own bearer token. See Authentication.

Route groups

All routes are mounted under /api:

PrefixGroupAuth
/api/healthHealth probenone
/api/assessmentsSubmit & fetch ROM / dexterity / pain / arthritisoptional
/api/lookupPublic lookup, claim, email, anonymous create (by code)mixed
/api/patientsScore/assessment history, profiles, journal, narrativerequired
/api/journalHand-journal check-insnone*
/api/reportsBundled reports, PDF, email, AI explanationoptional
/api/biomechanicsWrist/thumb kinematic analysis (proxied)none
/api/aiText-to-speech (REST) + orchestrator (/api/ai/ws, WebSocket)none
/api/billingStripe checkout, portal, subscription, webhookrequired**
/api/leadsDeveloper/partner sign-up (marketing site)none

* Journal endpoints are not currently behind an auth guard but expect a patientId. ** The webhook (/api/billing/webhook) is server-to-server and uses Stripe signature verification rather than a JWT.

Conventions

  • JSON in and out (except PDF download and TTS audio). Content-Type: application/json.
  • BigInt IDs in the database are serialized to JSON numbers in responses.
  • 6-character codes (A–Z/2–9, ambiguous chars removed) identify shareable assessment records and reports; accepted with or without the middle dash (XHE7JR / XHE-7JR).
  • Snake_case appears in some camera-derived payloads (e.g. wrist max_extension_deg); everything else is camelCase.