Quality management system
Integrations with quality management systems connect patient-related adverse events in Aidn to the municipality’s established incident management process. When an adverse event is signed in Aidn, Aidn sends the QMS a structured JSON payload containing only the necessary data. The QMS then handles the case and sends one or more status updates back to Aidn.
This use case is inspired by FHIR concepts, but the integration uses a custom JSON API. It’s documented here rather than in the FHIR API reference.
Scenario
The municipality uses Aidn as its electronic health record and a separate quality management system to manage incidents. Employees report patient-related adverse events in Aidn. When an event is signed, Aidn immediately sends it to the QMS so the municipality can handle the case within its existing workflow.
Aidn stores a link to the QMS case and displays its latest status in the adverse event view.
Required setup
| Configuration | Owner | Description |
|---|---|---|
| OAuth client | Municipality or Aidn administrator | Client configured for the QMS vendor and environment. See Municipality setup. |
| Client private key | Vendor | Private key corresponding to the registered public key. The vendor can generate this key pair, or the admin portal can generate it during client setup. Store it securely. |
| Scope | Municipality or Aidn administrator | The client needs adverseevent.write to send status updates to Aidn. |
| Department overview | Municipality | The municipality must provide the QMS vendor with the names and Aidn department IDs of departments that will use the integration. |
| QMS receiver endpoint | Vendor | HTTPS endpoint where Aidn can POST signed adverse events. Authentication for requests from Aidn to the QMS is agreed during onboarding. |
| Integration enabled for municipality | Municipality or Aidn administrator | The QMS integration must be enabled before Aidn can send requests for the municipality. |
The municipality can choose whether to enable the integration. If required, traffic can also be restricted to the Norwegian Health Network (Helsenettet).
Department onboarding
Before the integration is enabled, the municipality must provide the department overview to the QMS vendor. It must include the name and Aidn department ID for each department that will use the integration. The vendor uses this information to configure the QMS.
The QMS vendor uses the department IDs and names to route, classify, or display adverse events according to the configuration agreed with the municipality.
Data flow
sequenceDiagram
participant User as Aidn user
participant Aidn as Aidn
participant IdP as Aidn identity provider
participant QMS as QMS vendor
User->>QMS: Provide department names and Aidn department IDs
QMS->>QMS: Configure departments for the municipality
User->>Aidn: Enable the integration for the municipality
User->>Aidn: Register and sign an adverse event
Aidn->>QMS: POST adverse event JSON
QMS-->>Aidn: Technical acknowledgement
QMS->>QMS: Handle case in QMS workflow
QMS->>IdP: Request access token using private_key_jwt
IdP-->>QMS: Access token with approved scopes
QMS->>Aidn: PUT status update JSON
Aidn-->>QMS: Technical acknowledgement
Aidn->>Aidn: Show latest QMS status in the adverse event view
Aidn sends the event to the QMS synchronously and waits for a technical acknowledgement. Case handling then continues asynchronously in the QMS, which sends status updates as needed.
If Aidn can’t transfer the adverse event to the QMS when the user signs it, the adverse event remains in draft mode in Aidn. The user can sign it again later after the integration issue has been resolved.
Receive adverse events from Aidn
Aidn sends a signed adverse event to the QMS receiver endpoint as JSON.
POST <QMS_ADVERSE_EVENT_ENDPOINT> HTTP/1.1
Host: <QMS_HOST>
Accept: application/json
Content-Type: application/json
{
"identifier": "019c298c-366b-76a8-b73e-87306ae6550d",
"patientId": "9XFLLS",
"category": {
"code": "1",
"display": "Fall"
},
"severity": {
"code": "5",
"display": "Livstruende/invalidiserende"
},
"occurredDateTime": "2026-02-04T16:39:38.499132+00:00",
"detectedDateTime": "2026-02-04T16:39:38.499132+00:00",
"fields": [
{
"label": "Beskrivelse",
"identifier": 3486,
"value": "Description of adverse event",
"code": null
},
{
"label": "Utførte tiltak",
"identifier": 3492,
"value": "Measures taken",
"code": null
}
],
"reporter": {
"person": {
"name": "Example User",
"nationalId": "<NATIONAL_ID>",
"userPrincipalName": "example.user@example.org",
"actorId": "55598fe4-2826-4a0d-8881-db63ee27afd4"
},
"organization": {
"tenantMunicipalityNumber": "0000",
"tenantName": "Example municipality",
"organizationNumber": "874593842",
"organizationName": "Example nursing home",
"departmentId": "0ed0c8fd-1c82-4b3b-82bc-ae07c2cf38f5",
"departmentName": "Short-term ward"
}
}
}
Adverse event payload
| Property | Type | Description |
|---|---|---|
identifier |
string (UUID) | Aidn identifier for the adverse event. Use this as the correlation key when sending status updates back to Aidn. |
patientId |
string | Anonymized Aidn patient identifier. Patient name and national identification number aren’t sent. |
category |
Coding | Type of adverse event. |
severity |
Coding | Severity of the adverse event. |
occurredDateTime |
string (ISO 8601 timestamp) | Date and time when the event occurred. |
detectedDateTime |
string (ISO 8601 timestamp) | Optional. Date and time when the event was detected. |
fields |
Field[] | Content from the adverse event form. At least one field is included. |
reporter |
Reporter | Technical information about the reporter and organizational context. |
Shared types
| Type | Properties |
|---|---|
Coding |
code string, display string. |
Field |
label string, identifier number, value string, optional code string. |
Reporter |
person and organization. |
Person |
name, optional nationalId, optional userPrincipalName, actorId UUID. Depending on the municipality’s identity setup, at least one of nationalId and userPrincipalName is present. |
Organization |
tenantMunicipalityNumber, tenantName, organizationNumber, organizationName, departmentId UUID, departmentName. |
Categories and severity
Category and severity are represented by codes. The current adverse event categories are:
| Code | Display |
|---|---|
1 |
Fall |
2 |
Medisinavvik |
3 |
Ernæring |
4 |
Skade, vold eller trusler |
5 |
Svikt i utstyr |
6 |
Rutinesvikt |
7 |
Tjenesteavvik |
8 |
Personvern og informasjonssikkerhet |
9 |
Annet avvik |
Severity uses codes 1 to 6, from no harm to death. The Norwegian text in display is intended
for end users and should be preserved when shown in the QMS.
Form fields
The standard fields are:
| Identifier | Label | Description |
|---|---|---|
3486 |
Beskriv avviket | Plain text description of the adverse event. |
3492 |
Hvilke tiltak ble iverksatt på grunn av hendelsen | Plain text description of actions taken after the adverse event occurred. |
3493 |
Forslag til fremtidige tiltak | Plain text suggestions for future actions. |
For category 1 (Fall), Aidn can also include coded fields describing the activity at the time of
the fall, any sudden illness, and any fractures:
| Identifier | Label | Codes |
|---|---|---|
3487 |
Aktivitet | 1 Ut av og opp i seng, 2 Bruk av rullestol, 3 Toalettbesøk, 4 Gange med rullator, 5 Fri gange, 6 Opp og ned av stol, 7 Annet. |
3488 |
Illebefinnende | 1 Ja, 2 Nei, 3 Vet ikke. |
3489 |
Brudd | 1 Ja, 2 Nei, 3 Vet ikke. |
Send status updates to Aidn
The QMS sends one or more status updates to Aidn while handling the case. Aidn displays the latest status in the adverse event view.
PUT <OPEN_AIDN_QMS_STATUS_ENDPOINT> HTTP/1.1
Host: <OPEN_AIDN_HOST>
Accept: application/json
Content-Type: application/json
Authorization: Bearer <ACCESS_TOKEN>
{
"qmsId": "QMS-12345",
"identifier": "019c298c-366b-76a8-b73e-87306ae6550d",
"status": {
"code": "closed",
"display": "Ferdig behandlet"
},
"text": [
{
"title": "Status",
"date": 1770219578,
"text": "The adverse event has been handled in the QMS.",
"class": "summary"
}
],
"lastUpdated": 1770219578
}
| Property | Type | Description |
|---|---|---|
qmsId |
string | The QMS’s internal identifier for the case, stored in Aidn for traceability. |
identifier |
string (UUID) | Aidn adverse event identifier. Must match the identifier sent from Aidn. |
status |
Coding | QMS-defined user-friendly status code and display text. The display value can be shown directly to end users. |
text |
StatusText[] | One or more status text blocks. |
lastUpdated |
number | Unix timestamp for when the adverse event was last updated in the QMS. |
StatusText contains title, optional date, text, optional class, and optional nested
objects for structured text blocks defined by the QMS.
Privacy and data minimization
The integration is designed to avoid direct patient-identifying information:
- Patient name and national identification number aren’t sent.
- The patient is represented by an anonymized Aidn patient identifier.
- Image attachments in the Aidn adverse event form aren’t transferred through the API.
- Free-text fields can still contain indirect identifiers. The municipality should address this through training, procedures, and a data protection impact assessment (DPIA) where needed.
- The QMS should avoid storing reporter national identification numbers or UPNs unless this is part of the agreed processing purpose.
The adverse event form informs users that the event will be sent to the QMS and must not contain sensitive patient information.
Validation checklist
Before production rollout, validate the setup with the municipality and QMS vendor:
- The integration is enabled for the correct municipality and environment.
- The QMS client can request
adverseevent.write. - The municipality has provided the QMS vendor with department names and Aidn department IDs for departments using the QMS integration.
- Aidn can reach the QMS receiver endpoint over the agreed network path.
- The QMS stores the Aidn
identifierand returns it unchanged in status updates. - The QMS handles duplicate or repeated event deliveries without creating duplicate or incorrect cases.
- The QMS handles Norwegian coded values and display texts as agreed.
- The QMS doesn’t persist patient-identifying information beyond the agreed purpose.
- Key rotation, operational monitoring, retry behaviour, and incident contacts are agreed.