Quality management system
Quality management system integrations connect Aidn patient-related adverse events with the municipality’s established deviation handling process. When an adverse event is signed in Aidn, Aidn sends a structured and data-minimized JSON payload to the QMS. The QMS then handles the case and returns one or more status updates to Aidn.
This use case is inspired by FHIR concepts, but the integration API uses a custom JSON format. The API description is therefore included here instead of in the FHIR API reference.
Scenario
The municipality uses Aidn as the electronic patient record and a separate quality management system for deviation handling. Employees register patient-related adverse events in Aidn. When the adverse event is signed, Aidn immediately transfers it to the QMS so the municipality can continue case handling in its existing QMS workflow.
Aidn stores the link to the QMS case and shows the latest status returned by the QMS 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 give the QMS vendor a list of department names and Aidn department IDs for departments that will use the QMS integration. |
| QMS receiver endpoint | Vendor | HTTPS endpoint where Aidn can POST signed adverse events. Authentication for calls from Aidn to the QMS is agreed during onboarding. |
| Integration enabled for municipality | Municipality or Aidn administrator | The QMS integration must be enabled before requests will be allowed for the municipality. |
The municipality can choose whether the integration is active. If required by the municipality, traffic can also be limited to Helsenettet.
Department onboarding
Before the integration is enabled, the municipality must provide the department overview to the QMS vendor. The overview must include the department name and Aidn department ID for each department that will use the QMS integration, and the vendor uses it when configuring the QMS setup.
The QMS vendor uses the department IDs and names to route, classify, or display adverse events according to the municipality’s agreed setup.
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 integration for municipality
User->>Aidn: Register and sign adverse event
Aidn->>QMS: POST adverse event JSON
QMS-->>Aidn: Technical receipt
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 receipt
Aidn->>Aidn: Show latest QMS status in adverse event view
The transfer from Aidn to the QMS is synchronous for the technical receipt, but functionally asynchronous. Further case handling happens in the QMS, and the QMS returns status updates when relevant.
If Aidn cannot 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 are not sent. |
category |
Coding | Type of adverse event. |
severity |
Coding | Severity of the adverse event. |
occurredDateTime |
string (ISO timestamp) | Date and time when the event occurred. |
detectedDateTime |
string (ISO timestamp) | Optional. Date and time when the event was detected or recognized. |
fields |
Field[] | Content from the adverse event form. At least one item 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 municipality identity setup, at least nationalId or userPrincipalName is present. |
Organization |
tenantMunicipalityNumber, tenantName, organizationNumber, organizationName, departmentId UUID, departmentName. |
Categories and severity
The category and severity values are coded. 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 display text is intended for end users and should be preserved when shown in the QMS.
Form fields
Standard fields include:
| 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 for fall activity, malaise, and fracture:
| 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 during case handling. Aidn displays the latest received status in the adverse event UI.
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 | QMS 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 QMS-defined structured text blocks.
Privacy and data minimization
The integration is designed to avoid direct patient-identifying information:
- Patient name and national identification number are not sent.
- The patient is represented by an anonymized Aidn patient identifier.
- Image attachments in the Aidn adverse event form are not transferred through the API.
- Free-text fields can still contain indirect identifiers if users enter them. The municipality should handle this through training, routines, and DPIA assessment where needed.
- The QMS should avoid storing reporter national identification numbers or UPNs unless this is part of the agreed processing purpose.
Aidn shows text in the adverse event form informing users that the adverse event will be transferred to the QMS and must not contain patient-sensitive 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 can handle duplicate or repeated adverse event deliveries without creating incorrect cases.
- The QMS handles Norwegian coded values and display texts as agreed.
- The QMS does not persist patient-identifying information beyond the agreed purpose.
- Key rotation, operational monitoring, retry behavior, and incident contacts are agreed.