/api
prefix is used for disambiguation of backend API requests,
but stripped in the proxy_pass
directive.
Otherwise, discard the /api
prefix from URI paths.
The following endpoints constitute the "ETL" API for both the Rare Diseases (RD) and Molecular Tumor Board (TMB) use cases.
In the following: use-case
in {mtb,rd}
Request a JSON Schema description of the patient record (generated from the DTOs using library scala-jsonschema), with optional indication of the desired JSON Schema version
GET /api/{use-case}/etl/patient-record/schema[?version={version}]
with version
in {draft-12, draft-09, draft-07, draft-04}
, Default: draft-12
⚠️ IMPORTANT NOTE: Bear in mind that these JSON schemas for MTB and RD Patient Records are provisional, given that some adaptations are to be expected once the technical specifications derived from the "Datenkranz" for the "MVGenomV" model project become available.
API endpoint to request random generated, structurally/syntactically correct JSON examples of patient records
GET /api/{use-case}/fake/data/patient-record
⚠️ IMPORTANT NOTE about Codings: Given that many elements of a patient record are concepts from various code systems, the models contain many Coding objects. In the random generated JSON examples (see above), these Coding elements are created not only with thecode
, but alsodisplay
,system
and possiblyversion
attribute values. However, in uploads only thecode
attribute is required, and the latter attributes can generally be omitted, so bear the following in mind for your Coding management:
Attribute Use Note code
Required system
Optional For most of the coded elements, the code system is clearly defined from the context (e.g. for attribute patient.gender
). Thesystem
must thus only be explicitly specified for those few attributes which allow Codings from multiple code systems (e.g. for rare diseases, the diagnosis codes from ICD-10-GM, Orphanet or Alpha-ID-SE). In these cases, the referenced Coding type in the JSON schema has a requiredsystem
attribute and lists admissible code system identifiers.version
Optional The code system version need only be set in cases where the code-system is versioned and the version particularly relevant (e.g. for medications, the ATC version). Else, by default, the Coding is resolved against the latest available version of the corresponding code system. display
Discarded Upon import, Coding objects are validated against the respective code system and the display
is completed, so no need to set it.
Note on the validations performed and meaning of the different response codes
Upon upload to the following API endpoint, the payload undergoes two-fold validation: After syntactic validation (i.e. if the JSON payload can be properly parsed as a PatientRecord data transfer object (DTO)) there is a semantic validation step. This is required for various reasons:
Beyond mere structural correctness, more advanced validations like referential integrity checks, whether coded entries (e.g. ICD-10 codes) are correctly
resolvable in the respective code system, or that a given entity is in a valid state depending on some status
attribute, are not possible on the schema level anyway,
but require custom application logic (in case of interest, see for instance here.
Also, many of the attributes on the PatientRecord are kept optional on the syntactic level, even though they are semantically required in order for a data set to be meaningful. The reason this was made so, is to separate concerns: Say you are an ETL developer in charge of extracting the data from respective primary systems and send them to the DNPM:DIP node. If this upload were to fail because semantically required attributes are missing or incorrect due to incomplete/erroneous documentation in the patient record, you'd be receiving upload rejections for which you can't really do anything. Therefore, errors pertaining to the content of a patient record are raised in the "data quality issue report" created in the semantic validation step and (aside from being returned in the upload response) are stored in the validation module of the DNPM node.
The idea is that some kind of data quality improvement loop be established at your respective site: Whether this consists in having documentarists in charge to regularly check the data quality issue reports in the node's (upcoming) validation portal, and proceed from there to correct the data in primary systems and trigger a re-export, or that your ETL setup directly forwards the data quality issue report returned in the error response into a corresponding local "workflow", is up to your site.
Given this envisioned process of API usage, you will notice that although the syntactic and semantic error reports have the same JSON structure, the error messages are in English and German, respectively. The reason for this is that the former errors directly originate from the used JSON parsing/validation library, whereas the semantic validation reports, being meant for a "documentarist" user class, are in German in order be understandable by this non-technician user class.
Aside from the different language, this difference of "error report addressee" is also reflected by the different HTTP status codes, to allow differentiated handling:
400
indicates errors concerning the ETL developer (syntactical incorrectness or e.g. breaks of referential integrity)422
or201
indicate more or less severe semantic issues, and thus concern documentarists.
POST /api/{use-case}/etl/patient-record
Response
Case | Response | Effect |
---|---|---|
Data OK | 200 OK |
Data set was saved in the query module |
Data acceptable with quality issues | 201 Created with JSON issue report |
Data Set was saved in the validation module with a corresponding issue report, but also in the query module |
Unacceptable Issues | 422 Unprocessable Content with JSON issue report |
Data Set was saved in the validation module with a corresponding issue report |
Fatal Issues Detected | 400 Bad Request with JSON issue report |
Import transaction aborted |
⚠️ IMPORTANT NOTE for MTB uploads (data uploads, JSON schemas):In order to be backward compatible with the (soon obsolete) bwHC node's data import API, the DNPM:DIP system's API currently supports 2 MTB data upload formats:
Format Definition application/json
old bwHC MTBFile format (Default) application/json+v2
new DNPM:DIP Patient record format In order to be non-breaking with the bwHC API, the old
application/json
is the default format of data upload requests, unless explicitly specified via theContent-type
header. Accordingly, the JSON schema returned for requests toGET /api/mtb/etl/patient-record/schema[?version={version}]
corresponds to thisapplication/json
format.However, the random generated MTB patient records are in the (new)
application/json+v2
format. In order to obtain the JSON schema and perform data uploads for thisapplication/json+v2
format, it must (currently) be specified explicitly:
- JSON Schema:
GET /api/mtb/etl/patient-record/schema?format=application/json%2Bv2
- Data Upload
POST /api/mtb/etl/patient-record
with Header 'Content-type: application/json+v2'Apologies for the confusion and inconveniences this currently causes. Support for the old/obsolete bwHC format will eventually be dropped as soon as the data model has been aligned with Model Project specifications.
This endpoint allows to simply validate a patient record, without actually importing it in the system
POST /api/{use-case}/etl/patient-record:validate
Response
Case | Response |
---|---|
Data fully acceptable | 200 OK |
Data Acceptable with Issues | 200 OK with JSON issue report |
Unacceptable Issues | 422 Unprocessable Content with JSON issue report |
Fatal Issues Detected | 400 Bad Request with JSON issue report |
DELETE /api/{use-case}/etl/patient/{Patient-ID}
GET /api/coding/codesystems
Response
List of CodeSystem info objects containing name, title, URI, and possibly a list of available versions and pre-defined filters applicable to the CodeSystem
{
"entries": [
{
"filters": [
{
"description": "Filter ICD classes of kind 'chapter'",
"name": "is-a-chapter"
},
{
"description": "Filter ICD classes of kind 'block'",
"name": "is-a-block"
},
{
"description": "Filter ICD classes of kind 'category'",
"name": "is-a-category"
}
],
"latestVersion": "2024",
"name": "ICD-10",
"title": "Internationale statistische Klassifikation der Krankheiten und verwandter Gesundheitsprobleme",
"uri": "http://fhir.de/CodeSystem/bfarm/icd-10-gm",
"versions": [
"2019",
"2023",
"2020",
"2024",
"2021",
"2022"
]
},
...
]
}
GET /api/coding/codesystems?uri={CodeSystem-URI}[&version={Version}][&filter=filter-A|filter-B&filter=filter-C]
Response
CodeSystem object
{
"uri": "http://fhir.de/CodeSystem/bfarm/icd-10-gm",
"name": "ICD-10",
"title": "Internationale statistische Klassifikation der Krankheiten und verwandter Gesundheitsprobleme",
"date": "2023-09-15T00:00:00",
"version": "2024",
"properties": [
{
"name": "kind",
"type": "enum",
"description": "Kind of ICD class",
"valueSet": [
"block",
"category",
"chapter"
]
}
],
"concepts": [
{
"code": "C25",
"display": "Bösartige Neubildung des Pankreas",
"version": "2024",
"properties": {
"kind": [
"category"
]
},
"parent": "C15-C26",
"children": [
"C25.4",
"C25.8",
"C25.0",
"C25.1",
"C25.9",
"C25.3",
"C25.7",
"C25.2"
]
},
...
]
}
This CodeSystem structure is conceptually equivalent to FHIR CodeSystem, but syntactically slightly different.
CodeSystems can be requested with applied filters on the concepts by including the filter name(s) as URI query parameter filter
.
The API supports combining filters with AND/OR logic: filter names concatenated into a pipe-separated value list as one filter
parameter are combined as OR, whereas filters occurring in different "filter" parameter values are combined using AND.
For instance, the following request represents the query "Get CodeSystem ICD-O-3, picking only concepts from ICD-O-3-M (morphology) and of kind 'block' or 'category'":
GET /api/coding/codesystems?uri=urn:oid:2.16.840.1.113883.6.43.1&filter=morphology&filter=is-a-block|is-a-category
GET /api/coding/valuesets
Response
List of ValueSet info objects containing name, title and URI (currently identical to CodeSystem Info objects)
{
"entries": [
{
"filters": [
{
"description": "Filter ICD classes of kind 'chapter'",
"name": "is-a-chapter"
},
{
"description": "Filter ICD classes of kind 'block'",
"name": "is-a-block"
},
{
"description": "Filter ICD classes of kind 'category'",
"name": "is-a-category"
}
],
"latestVersion": "2024",
"name": "ICD-10",
"title": "Internationale statistische Klassifikation der Krankheiten und verwandter Gesundheitsprobleme",
"uri": "http://fhir.de/CodeSystem/bfarm/icd-10-gm",
"versions": [
"2019",
"2023",
"2020",
"2024",
"2021",
"2022"
]
},
...
]
}
GET /api/coding/valuesets?uri={ValueSet-URI}[&version={Version}]
Response
ValueSet object
{
"uri": "http://fhir.de/CodeSystem/bfarm/icd-10-gm",
"name": "ICD-10",
"title": "Internationale statistische Klassifikation der Krankheiten und verwandter Gesundheitsprobleme",
"date": "2023-09-15T00:00:00",
"version": "2024",
"concepts": [
{
"code": "C25",
"display": "Bösartige Neubildung des Pankreas",
"system": "http://fhir.de/CodeSystem/bfarm/icd-10-gm",
"version": "2024"
},
...
]
}
This ValueSet structure is conceptually equivalent to FHIR ValueSet, but syntactically slightly different.
Query Criteria for MTB patient records:
Block | Attribute Name | Type | Multiplicity | API Binding for CodeSystem/ValueSet (incl. Filters) |
---|---|---|---|---|
Diagnosis Criteria | Code | Coding[ICD-10-GM] | 0...N | /api/coding/codesystems?uri=http://fhir.de/CodeSystem/bfarm/icd-10-gm&filter=is-a-category |
Tumor-Morphology Criteria | Code | Coding[ICD-O-3-M] | 0...N | /api/coding/codesystems?uri=urn:oid:2.16.840.1.113883.6.43.1&filter=morphology&filter=is-a-category |
SNV Criteria (0...N) | Gene | Coding[HGNC] | 0...1 | /api/coding/codesystems?uri=https://www.genenames.org/ |
SNV Criteria (0...N) | DNA Change | Coding[HGVS.DNA] | 0...1 | |
SNV Criteria (0...N) | Protein Change | Coding[HGVS.Protein] | 0...1 | NOTE: 3-letter amino acid code required |
CNV Criteria (0...N) | Genes | Coding[HGNC] | 0...N | /api/coding/codesystems?uri=https://www.genenames.org/ |
CNV Criteria (0...N) | Type | Coding[CNV.Type] | 0...1 | /api/coding/codesystems?uri=dnpm-dip/mtb/ngs-report/cnv/type |
DNA-Fusion Criteria (0...N) | 5'-Gene | Coding[HGNC] | 0...1 | /api/coding/codesystems?uri=https://www.genenames.org/ |
DNA-Fusion Criteria (0...N) | 3'-Gene | Coding[HGNC] | 0...1 | /api/coding/codesystems?uri=https://www.genenames.org/ |
RNA-Fusion Criteria (0...N) | 5'-Gene | Coding[HGNC] | 0...1 | /api/coding/codesystems?uri=https://www.genenames.org/ |
RNA-Fusion Criteria (0...N) | 3'-Gene | Coding[HGNC] | 0...1 | /api/coding/codesystems?uri=https://www.genenames.org/ |
Medication Criteria (0...1) | Medication | Coding[ATC] | 0...N | /api/coding/codesystems?uri=http://fhir.de/CodeSystem/bfarm/atc |
Medication Criteria (0...1) | Usage Mode | Coding[Usage] | 0...2 | /api/coding/codesystems?uri=dnpm-dip/mtb/query/medication-usage |
Medication Criteria (0...1) | Operator | String | 0...1 | {and, or} Default: or |
Response Criteria | Code | Coding[RECIST] | 0...N | /api/coding/codesystems?uri=RECIST |
See MTBQueryCriteria DTO for structure of the corresponding JSON form.
Query Criteria for RD patient records:
Block | Attribute Name | Type | Multiplicity | API Binding for CodeSystem/ValueSet (incl. Filters) |
---|---|---|---|---|
HPO Term | Code | Coding[HPO] | 0...N | /api/coding/codesystems?uri=https://hpo.jax.org |
Disease Category | Code | Coding[Orphanet] | 0...N | /api/coding/codesystems?uri=https://www.orpha.net |
Variant | Gene | Coding[HGNC] | 0...N | /api/coding/codesystems?uri=https://www.genenames.org/ |
Variant | cDNA change | Coding[HGVS.DNA] | 0...N | |
Variant | gDNA change | Coding[HGVS.DNA] | 0...N | |
Variant | protein change | Coding[HGVS.Protein] | 0...N | NOTE: 3-letter amino acid code required |
See RDQueryCriteria DTO for structure of the corresponding JSON form.
POST /api/{use-case}/queries
Request Body
Composite of Query Mode and Query Criteria object
{
"mode": {
"code": "local" // {local, federated}
},
"criteria": { ... }
}
Response
Created Query session object
{
"id" : "1e3c229e-ffb4-47fa-9602-1c2b26c8117f",
"submittedAt" : "2023-09-15T12:04:06.521604",
"querier" : "Dummy-Querier-ID",
"mode" : { ... },
"criteria" : {
// Query Criteria object as submitted, but with initialized "display" and "system" values in all codings
},
"expiresAfter" : 900, // Validity period (seconds) after which query session expires unless refreshed by some operation
"lastUpdate" : "2023-09-15T10:04:06.521634Z"
}
GET /api/{use-case}/queries
Response
Collection of Query session objects
{
"entries": [
{
"id" : "1e3c229e-ffb4-47fa-9602-1c2b26c8117f",
"submittedAt" : "2023-09-15T12:04:06.521604",
"querier" : "Dummy-Querier-ID",
"mode" : { ... },
"criteria" : { ... },
"expiresAfter" : 900, // Validity period (seconds) after which query session expires unless refreshed by some operation
"lastUpdate" : "2023-09-15T10:04:06.521634Z"
}
]
}
GET /api/{use-case}/queries/{Query-ID}
GET /api/{use-case}/queries?id={Query-ID}
Response
Query session object
{
"id" : "1e3c229e-ffb4-47fa-9602-1c2b26c8117f",
"submittedAt" : "2023-09-15T12:04:06.521604",
"querier" : "Dummy-Querier-ID",
"mode" : { ... },
"criteria" : { ... },
"expiresAfter" : 900, // Validity period (seconds) after which query session expires unless refreshed by some operation
"lastUpdate" : "2023-09-15T10:04:06.521634Z"
}
GET /api/{use-case}/queries/{Query-ID}/summary
Response
Query Result Summary object
{
"id": "<Query-ID>",
"numPatients": 31,
....
}
GET /api/{use-case}/queries/{Query-ID}/patient-matches
GET /api/{use-case}/queries/{Query-ID}/patients
Response
Collection of Patient Match objects, i.e. minimal Patient Info together with subset of matching query criteria
{
"entries": [
{
"id": "018b00bb-2898-49eb-82b8-dd88617da326", // Patient-ID
"age": {
"value": 48,
"unit": "a" // Years
},
"gender": {
"code": "other",
"display": "Divers",
"system": "Gender"
},
"vitalStatus": {
"code": "alive",
"display": "Lebend",
"system": "dnpm-dip/patient/vital-status"
},
"matchingCriteria": {
// Subset of criteria matching the submitted criteria...
},
},
...
]
}
GET /api/{use-case}/queries/{Query-ID}/patient-record/{Patient-ID}
Response
Patient Record (see above for JSON Schema and example data)
PUT /api/{use-case}/queries/{Query-ID}
Request Body
Query Update object
{
"id": "<Query-ID>",
"mode": { // Optional here, only if mode changed
"code": "local | federated"
},
"criteria": { // Optional here, only if query criteria changed
...
}
}
Response
Updated Query session object
{
"id" : "1e3c229e-ffb4-47fa-9602-1c2b26c8117f",
...
"lastUpdate" : "2023-09-15T10:04:06.521634Z"
}
DELETE /api/rd/queries/{Query-ID}
Response
Query session object
{
"id" : "1e3c229e-ffb4-47fa-9602-1c2b26c8117f",
"submittedAt" : "2023-09-15T12:04:06.521604",
"querier" : "Dummy-Querier-ID",
"mode" : { ... },
"criteria" : { ... },
"expiresAfter" : 900, // Validity period (seconds) after which query session expires unless refreshed by some operation
"lastUpdate" : "2023-09-15T10:04:06.521634Z"
}