Skip to content

Data Model ​

The API server stores everything in one PostgreSQL database whose structure is generated from the platform schema. This page describes the entities that matter to integrators and operators and how they relate. Field-level detail is in the OpenAPI document of your instance.

Relationship sketch ​

 Folder ──< Folder (nested)
   │
   ├──< FolderPermission ──> User
   │
   └──< Questionnaire ──< QuestionnaireRevision
          │   │
          │   ├──< QuestionnairePermission ──> User
          │   │
          │   └──< Enrollment ──< EnrollmentUser ──> Patient (User)
          │              │              │
          │              │              └──< Device
          │              │
          │              └── schedule → slots
          │
          └──< QuestionnaireSubmission ──> (Enrollment, slot, Device | Web | API)

 User ──< UserRole ──> Role ──< RoleScope ──> Scope
 User ──< ApiKey
 User ──< UserExternalIdentifier (directory binding)
 User ──< UserMfa, RefreshToken, PasswordResetToken

 VaultEntry (secret | variable | file)
 PluginDefinition ──< PluginInstance
 EventSubscription ──< EventDeliveryTask
 Webhook ──< WebhookDelivery
 EventWorkflow ──< WorkflowNode, WorkflowEdge ; ──< WorkflowRun ──< WorkflowRunNode
 ConsentDocument
 ClinicalSource ──< patient links (external identifiers)
 AnalyticsDataMapping ──< AnalyticsChart ──< AnalyticsDashboard

Entities ​

EntityPurpose
FolderNode of the content tree. Carries a configuration fragment that is inherited downwards and permissions that may apply recursively.
QuestionnaireThe editable questionnaire: name, folder, identity policy (identified, pseudo-anonymised or anonymous), status, its definition and schedule as JSON, and a link to its parent when it was forked.
Questionnaire revisionAn immutable snapshot taken when a questionnaire is published. Revisions form a lineage so that the version tree and diffs can be reconstructed. Enrollments reference the revision they started on.
EnrollmentThe decision to give a questionnaire to one or more patients on a schedule. Has a status lifecycle and a start date; the schedule expands into slots.
Enrollment userOne patient inside an enrollment, with a per-patient status.
Schedule and slotThe schedule is stored with the questionnaire and resolved into dated slots with access windows; a slot accepts one submission.
PatientA user record with a patient profile. Identified questionnaires attach submissions to the patient; anonymous ones never do.
DeviceA paired mobile device with its registration status, bound to a patient and used for device authentication.
SubmissionA completed questionnaire: answers, computed scores and metadata as JSON, the source (device, web or API), the slot it fulfils and the revision it was answered against.
User, role, scope, API keyAccounts, their roles, the scopes each role grants, and machine credentials acting under a role.
External identifierThe binding between a local user and an identity in the organisation's directory.
Vault entryA named secret, variable or file reference, encrypted at rest when secret.
Plugin definition, instanceAn installed plugin and its configured instances, each with its own settings and vault references.
Event subscription, delivery taskAn outbound subscription to event types with filters, and the per-event delivery attempts.
Webhook, webhook deliveryAn HTTPS endpoint registered for events and the log of signed deliveries and retries.
Workflow, run, run nodeThe automation graph (nodes and edges) and the record of each execution with per-node status.
Consent documentA versioned legal text per language, shown at pairing or before anonymous questionnaires.
Clinical sourceA configured connection to a hospital system, with its kind and connection settings referencing vault entries.
Analytics data mapping, chart, dashboardA dataset definition mapping answers, scores and clinical data to columns; charts built on it; dashboards composed of charts.

Status values (questionnaire, enrollment, device, delivery, run) are reference tables seeded on every instance, so they are stable across releases and safe to filter on.

Conventions ​

  • Identifiers are opaque strings, unique per table.
  • Timestamps. Every record has creation and update timestamps and the identifier of the user who last changed it.
  • Soft delete. Deletion sets a timestamp instead of removing the row. Listings exclude deleted rows by default; see API Design.
  • JSON documents. Questionnaire definitions, schedules, folder configuration fragments, submission answers, plugin settings and workflow graphs are stored as JSONB. They can be indexed and queried in place, which is what analytics and workflows rely on.
  • Immutability of revisions. A published revision is never edited. Changing a published questionnaire creates a new draft; publishing it creates a new revision. Submissions always reference the revision they were answered against, so results remain interpretable after the questionnaire changes.
  • Versions on content. Questionnaires record the platform version they were created with and their own version, which the designer uses for compatibility checks.

Where the data model is defined ​

The tables above are not hand-written. The platform schema defines each entity once; the ORM models, the migrations, the request and response models and the OpenAPI document are generated from it. Adding a field is a schema change that flows to every layer in one release. See Architecture.