Appearance
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 ──< AnalyticsDashboardEntities
| Entity | Purpose |
|---|---|
| Folder | Node of the content tree. Carries a configuration fragment that is inherited downwards and permissions that may apply recursively. |
| Questionnaire | The 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 revision | An 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. |
| Enrollment | The 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 user | One patient inside an enrollment, with a per-patient status. |
| Schedule and slot | The schedule is stored with the questionnaire and resolved into dated slots with access windows; a slot accepts one submission. |
| Patient | A user record with a patient profile. Identified questionnaires attach submissions to the patient; anonymous ones never do. |
| Device | A paired mobile device with its registration status, bound to a patient and used for device authentication. |
| Submission | A 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 key | Accounts, their roles, the scopes each role grants, and machine credentials acting under a role. |
| External identifier | The binding between a local user and an identity in the organisation's directory. |
| Vault entry | A named secret, variable or file reference, encrypted at rest when secret. |
| Plugin definition, instance | An installed plugin and its configured instances, each with its own settings and vault references. |
| Event subscription, delivery task | An outbound subscription to event types with filters, and the per-event delivery attempts. |
| Webhook, webhook delivery | An HTTPS endpoint registered for events and the log of signed deliveries and retries. |
| Workflow, run, run node | The automation graph (nodes and edges) and the record of each execution with per-node status. |
| Consent document | A versioned legal text per language, shown at pairing or before anonymous questionnaires. |
| Clinical source | A configured connection to a hospital system, with its kind and connection settings referencing vault entries. |
| Analytics data mapping, chart, dashboard | A 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.