From f09e1fc75d3801624783a0a61aa1bea804f576f3 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Sat, 3 Jun 2023 04:47:08 +0200 Subject: [PATCH] [dossier] Added docs for the /patient/dossier endpoint and separated out patient personal info into separate schema file --- paths/patient_base.yaml | 190 ++---------------- paths/patient_dossier.yaml | 128 +++++++++++- schemas/PatIdentity.yaml | 234 ++++++++++++++++++++++ schemas/med_dossier/Contraindication.yaml | 19 ++ schemas/med_dossier/Correspondence.yaml | 57 ++++++ schemas/med_dossier/Episode.yaml | 45 +++++ schemas/med_dossier/Feat.yaml | 46 +++++ schemas/med_dossier/Journal.yaml | 79 ++++++++ schemas/med_dossier/Measurement.yaml | 69 +++++++ schemas/med_dossier/Medication.yaml | 57 ++++++ schemas/med_dossier/Practicioner.yaml | 14 ++ zoo-api.yaml | 14 +- 12 files changed, 765 insertions(+), 187 deletions(-) create mode 100644 schemas/PatIdentity.yaml create mode 100644 schemas/med_dossier/Contraindication.yaml create mode 100644 schemas/med_dossier/Correspondence.yaml create mode 100644 schemas/med_dossier/Episode.yaml create mode 100644 schemas/med_dossier/Feat.yaml create mode 100644 schemas/med_dossier/Journal.yaml create mode 100644 schemas/med_dossier/Measurement.yaml create mode 100644 schemas/med_dossier/Medication.yaml create mode 100644 schemas/med_dossier/Practicioner.yaml diff --git a/paths/patient_base.yaml b/paths/patient_base.yaml index 1dc528c..b50c6ce 100644 --- a/paths/patient_base.yaml +++ b/paths/patient_base.yaml @@ -30,195 +30,33 @@ get: - start_date properties: bsn: - description: |- - Patient SSN (dutch: _BSN_). If not known or patient has no BSN, this value will be `0`. - It is customary that BSNs are 9 digits; API caller may want to transform this value into - a string by explicitly left-padding `0` characters to the front to make the bsn value 9 digits. - type: number - example: 123456789 + $ref: 'schemas/PatIdentity.yaml#/bsn' name: - description: All relevant info about the patient's name. - type: object - properties: - firstname: - description: |- - Patient's first name(s), separated by spaces. - It's possible that no first names are known and instead only initials are known; in that case, - the initials are provided with dots (`.`) in between the letters, e.g. `"J.M."`. - type: string - example: Marie Antoinnette - initials: - description: |- - Patient's initials, with no separators. - Initials might be derived from a patient's first name if initials weren't explicitly provided by - the source HIS. - type: string - example: MA - infix_own: - description: |- - The prefix of the patient's own last name (what they were born with; not the name inherited from - a spouse): `van`, `de`, `van der` - a mostly uniquely dutch aspect to last names. - type: string - example: de - own_lastname: - description: |- - The patient's own last name without a prefix (what they were born with; not the name inherited from - a spouse). - type: string - example: Villepin - infix_partner: - description: |- - The prefix of the patient's (ex-)spouse's last name; not all patients that are married go by their spouse's last name and often, if they don't, this field will be blank. - type: string - example: van der - partner_lastname: - description: |- - The the patient's (ex-)spouse's last name without prefix; not all patients that are married go by their spouse's last name and often, if they don't, this field will be blank. - type: string - example: Dussen + $ref: 'schemas/PatIdentity.yaml#/name' gender: - description: |- - Patient's gender. `M` = male, `V` = female, `O` = other/unknown. - Follows [NHG-table-4](https://referentiemodel.nhg.org/sites/default/files/NHG-Tabel%204-Geslacht-versie-5-Inkijkexemplaar_1.pdf). - type: string - example: V - enum: - - M - - V - - O + $ref: 'schemas/PatIdentity.yaml#/gender' dob: - description: |- - Patient's date of birth. - Note that by convention, patients whose birthdate is unknown pick a date and tend to pick either `xxxx-01-01` or `xxxx-07-01`. Can, in rare cases, be unavailable - if birth date is not known. - type: string - format: date - example: 1970-07-01 + $ref: 'schemas/PatIdentity.yaml#/dob' category: - description: |- - The status of the patient's registration within this practice. - As per [NHG-table-5](https://referentiemodel.nhg.org/sites/default/files/NHG-Tabel%205-Categorie%20pati%C3%ABnt-versie-5-Inkijkexemplaar_1.pdf): - - `V` = Standard patient, part of the GP's population (dutch: _vast_). - - `T` = Temporary patient (likely do _not_ treat as part of GP's population). - - `P` = Opportunity patient (dutch: _passant_ - patient is not signed up with this GP. For example: tourist). - type: string - example: V + $ref: 'schemas/PatIdentity.yaml#/category' doctor: - description: |- - If known, the AGB code of the primary care GP (dutch: _Inschrijf arts_). Value 0 indicates - this HIS or practice doesn't assign patients to individual GPs, or this information isn't - known. - type: number - example: 1051234 + $ref: 'schemas/PatIdentity.yaml#/doctor' address: - description: Patient's address (where they live). If not known, this property will not be in the response. - type: object - properties: - street: - description: Full name of the street, excluding house number. - type: string - example: Lange Geer - housenumber: - description: |- - Just the house number; 0 if unknown or in the exotic case where no house number exists. This does - not include any addendums such as 'A' or 'room 15'. Guaranteed to be non-negative. - type: integer - example: 4 - housenumber_suffix: - description: |- - Often empty, the string that follows the numeric part of the address house number. For example, `"A"`, or - `"k22"`. - type: string - example: A - postcode: - description: The post code, in `1234AB` format. If not known, blank. - type: string - example: 2611PV - city: - description: The city or town. - type: string - example: Delft + $ref: 'schemas/PatIdentity.yaml#/address' contact: - type: object - properties: - tel: - description: |- - Patient's phone number(s). By convention, the mobile number, if available, is always listed first. - Phone numbers are always in international format (they start with a `+` symbol). - If no phone numbers are available or patient has no phone, an empty list is returned. - type: array - example: ["+31612345678", "+31701234567"] - items: - type: string - email: - description: |- - Patient's email address(es); first one returned is indicated as preferred. - If no emails are known or available, or patient has no email, an empty list is returned. - type: array - items: - type: string - example: ["info@zorgoporde.nl"] + $ref: 'schemas/PatIdentity.yaml#/contact' insurance: - description: |- - Info about where the patient is insured. If patient is not insured, this field will not be present. - Only the main insurance used for reimbursement of GP costs will be returned, if any such insurance exists. - - type: object - properties: - policy_number: - description: |- - Patient's insurance registration number (dutch: _polisnummer_). - type: string - example: 123456789012345 - uzovi: - description: |- - Insurer's identity number in the dutch insurance system (dutch: _UZOVI nummer_). Always - 4 digits exactly, 0-left-padded if needed. If unknown or not insured, 4 zeroes. - type: number - example: 101 + $ref: 'schemas/PatIdentity.yaml#/insurance' patid: - description: |- - Patient's "public" ID, as used and shown on the HIS patient page. Not necessarily unique, - and not necessarily present; 0 indicates no patid is known or this HIS does not use (numeric) - public IDs. - type: number - example: 1234 + $ref: 'schemas/PatIdentity.yaml#/patid' pat_unid: - description: |- - Patient's unique and persistent ID in HIS. Usually identical to `patid` but certain HISes may - use UUID, or has globally unique keys (e.g. very large numbers). Can be blank, but only - if supplying HIS does not send them. - type: string - example: 1234 + $ref: 'schemas/PatIdentity.yaml#/pat_unid' start_date: - type: string - format: date - description: |- - Date patient joined the practice (dutch: _inschrijf datum_). - In rare cases, a patient joined so long ago, this date is no longer known. In this case, - a sentinel value of `"1900-01-01"` is sent which is presumed to result in the desired behaviour - (which is to consider this patient as part of this practice's population regardless of how far - back you want to go). - example: 1994-08-20 + $ref: 'schemas/PatIdentity.yaml#/start_date' end_date: - type: string - format: date - description: |- - If not blank, patient has exited the practice on this date. (dutch: _uitschrijf datum_). - example: "" + $ref: 'schemas/PatIdentity.yaml#/end_date' end_reason: - description: |- - Reason patient left the practice (dutch: _reden vertrek_). - This will always be blank if `end_date` is blank. Otherwise, this value _might_ contain - a non-blank letter as per [NHG-table-9](https://referentiemodel.nhg.org/sites/default/files/NHG-Tabel%209-Reden%20vertrek-versie-5-Inkijkexemplaar_1.pdf): - - `A` = To other practice - - `V` = Moved - - `O` = died - - `T` = Temporary - - `I` = Care home / institution - - `Q` = unknown - - `X` = Other - type: string - example: "" + $ref: 'schemas/PatIdentity.yaml#/end_reason' '400': description: The request is invalid; for example, it doesn't contain the required `BSN` parameter. '401': diff --git a/paths/patient_dossier.yaml b/paths/patient_dossier.yaml index 240832b..e0c0fd4 100644 --- a/paths/patient_dossier.yaml +++ b/paths/patient_dossier.yaml @@ -3,9 +3,8 @@ get: - patient summary: Get detailed medical dossier info for the stated patient description: |- - WorkInProgress: The API will require you to provide (as parameters) the purpose of the request and potentially - the person on whose authority this request is being made, which will be logged and reviewed for the - _Principle of Least Privilege_ policy. + WorkInProgress: The API may require you to provide the person on whose authority this request is being made, + which will be logged and reviewed for the _Principle of Least Privilege_ policy. Known design parameters: - send along the date on which the result is based (HIS snapshot date) @@ -26,28 +25,137 @@ get: in: query description: |- The Patient unique ID, as e.g. reported by `/patient/base`'s `pat_unid` response. - Either `bsn` or `pu` must be present. + + Either `bsn` or `pu` must be present. We do not recommend including both; if this is done, _both_ filters are applied, and + patient info is only returned if a patient exists with both schema: type: string example: "" - name: q in: query description: |- - A space, comma, or bar-separated list of dossier aspects to query. If omitted, everything is returned. + A comma-separated list of dossier aspects to query. If omitted, everything is returned. The keys match the keys in the JSON structure that is returned on a success, such as `medication` or `measurements`. schema: type: string example: "medication,measurements" + - name: purpose + in: query + description: |- + A unique key identifying for what purpose this request is being made. Keys are agreed upon between + ZorgOpOrde and the API user, and will result in the data returned filtered down to what is relevant / necessary for + the stated purpose. For example, `"diet-dm2"` would be a key to represent that this patient is being + enrolled in Diabetes Mellitus chronic care and a report on this patient's DM status is being prepared to send + to a licensed dietitian. The data returned would be filtered to only include those aspects relevant for this task. + required: true + schema: + type: string + example: diet-dm2 responses: + '400': + $ref: '#/components/responses/ReqFailure' + '401': + $ref: '#/components/responses/JwtFailure' + '403': + description: |- + Practice associated with the JWT is known but has not authorized ZOO to share information with signer for the provided purpose. + + This error also occurs if the provided purpose isn't a known key. + '404': + $ref: '#/components/responses/PatNotFound' '200': - description: Detailed medical dossier information for the patient is returned. + description: |- + Detailed medical dossier information for the patient is returned. + + Filtered to only return what was requested (via optional query parameter `q`), and including only those aspects + of the medical dossier relevant for the stated purpose. content: application/json: schema: type: object properties: - tbd: + personal: + description: |- + Contains core identification information about this patient; a duplication of the `/patient/base` API. + type: object + properties: + bsn: + $ref: 'schemas/PatIdentity.yaml#/bsn' + name: + $ref: 'schemas/PatIdentity.yaml#/name' + gender: + $ref: 'schemas/PatIdentity.yaml#/gender' + dob: + $ref: 'schemas/PatIdentity.yaml#/dob' + category: + $ref: 'schemas/PatIdentity.yaml#/category' + doctor: + $ref: 'schemas/PatIdentity.yaml#/doctor' + address: + $ref: 'schemas/PatIdentity.yaml#/address' + contact: + $ref: 'schemas/PatIdentity.yaml#/contact' + insurance: + $ref: 'schemas/PatIdentity.yaml#/insurance' + patid: + $ref: 'schemas/PatIdentity.yaml#/patid' + pat_unid: + $ref: 'schemas/PatIdentity.yaml#/pat_unid' + start_date: + $ref: 'schemas/PatIdentity.yaml#/start_date' + end_date: + $ref: 'schemas/PatIdentity.yaml#/end_date' + end_reason: + $ref: 'schemas/PatIdentity.yaml#/end_reason' + episodes: + type: array + description: |- + Lists chronic problems or other diagnosed medical issues (dutch: _behandelingen / episodes / problemen_) based on ICPC1-NL. + items: + $ref: 'schemas/med_dossier/Episode.yaml' + measurements: + type: array + description: |- + Lists measurements, including lab-determined values (example: Direct measurement of LDL cholesterol in a blood sample), + measurements done by the practicioner or by the patient themselves (example: weight), care process information + (such as 'responsible for chronic diabetes care: Specialist'), and answers to questionnaires such as 'do you have trouble + walking up stairs'). + items: + $ref: 'schemas/med_dossier/Measurement.yaml' + feats: + type: array + description: |- + Lists declarable acts (dutch: _verrichtingen_, also known as _prestaties_), and includes: + * actual work done (such as spending 10 minutes with a patient) + * material that is paid separately (such some nitrogen to burn off a wart) + * 'subscription' fees such as the standard subscription fee as well as extras charged for each patient per quarter (dutch: _inschrijf_ en _module_ tarieven). + items: + $ref: 'schemas/med_dossier/Feat.yaml' + correspondence: + type: array + description: |- + Lists records of correspondence (excluding correspondence within the GP office and correspondence with the patient themselves). + items: + $ref: 'schemas/med_dossier/Correspondence.yaml' + medications: + type: array + description: |- + Lists medication, either prescribed, or delivered to the patient (or both, of course). + items: + $ref: 'schemas/med_dossier/Medication.yaml' + contraindications: + type: array + description: |- + Lists registered contra-indications, also often used for the generalized concept of popping up warnings any time + this patient's information is shown to a practicioner. Generally simply is an alternate take on a list of problems + a patient suffers from; specifically issues that may affect unrelated care (such as allergies, mental issues, and so on). + items: + $ref: 'schemas/med_dossier/Contraindication.yaml' + journals: + type: array description: |- - Work in progress - type: string - example: Work in progress + Lists registered journal entries - text typed by practicioners for a variety of reasons, including representing what the + patient themselves tells the practicioner (can include verbatim copies of what the patient wrote for text-based telehealth systems), + as well as explaining in text the conclusions included in a lab report received via mail. + items: + $ref: 'schemas/med_dossier/Journal.yaml' diff --git a/schemas/PatIdentity.yaml b/schemas/PatIdentity.yaml new file mode 100644 index 0000000..b437386 --- /dev/null +++ b/schemas/PatIdentity.yaml @@ -0,0 +1,234 @@ +bsn: + description: |- + Patient SSN (dutch: _BSN_). If not known or patient has no BSN, this value will be `0`. + + It is customary that BSNs are 9 digits; this API returns a number, i.e., no leading zeroes. + API callers may want to transform this value into a string by explicitly left-padding `0` + characters to the front to make the bsn value 9 digits. + type: number + example: 123456789 +name: + description: All relevant info about the patient's name. + type: object + properties: + firstname: + description: |- + Patient's first name(s), separated by spaces. + + It's possible that no first names are known and instead only initials are known; in that case, + the initials are provided with dots (`.`) in between the letters, e.g. `"J.M."`. + type: string + example: Marie Antoinnette + initials: + description: |- + Patient's initials, with no separators. + + Initials might be derived from a patient's first name if initials weren't explicitly provided by + the source. + type: string + example: MA + infix_own: + description: |- + The prefix of the patient's own last name (what they were born with; not the name inherited from + a spouse): `van`, `de`, `van der` - a mostly uniquely dutch aspect to last names. + type: string + example: de + default: "" + own_lastname: + description: |- + The patient's own last name without a prefix (what they were born with; not the name inherited from + a spouse). + type: string + example: Villepin + infix_partner: + description: |- + The prefix of the patient's (ex-)spouse's last name; not all patients that are married go by their + spouse's last name and often, if they don't, this field will be blank (i.e. not sent). + type: string + example: van der + default: "" + partner_lastname: + description: |- + The the patient's (ex-)spouse's last name without prefix; not all patients that are married go by + their spouse's last name and often, if they don't, this field will be blank. + + This API does not provide an indication about how this person prefers to be addressed. Culturally it + is customary for this person to be addressed by their own first name followed by their partner's + infix and last name if present, and their own if not. + type: string + example: Dussen + default: "" +gender: + description: |- + Patient's gender. `M` = male, `V` = female, `O` = other/unknown. + + Follows [NHG-table-4](https://referentiemodel.nhg.org/sites/default/files/NHG-Tabel%204-Geslacht-versie-5-Inkijkexemplaar_1.pdf). + type: string + example: V + enum: + - M + - V + - O +dob: + description: |- + Patient's date of birth. + + Note that by convention, patients whose birthdate is unknown (rare, but can happen in certain asylum seeker cases) + pick a date and tend to pick either `xxxx-01-01` or `xxxx-07-01`. Can, in rare cases, be unavailable - if birth date is not known. + type: string + format: date + example: 1970-07-01 +category: + description: |- + The status of the patient's registration within this practice. + + As per [NHG-table-5](https://referentiemodel.nhg.org/sites/default/files/NHG-Tabel%205-Categorie%20pati%C3%ABnt-versie-5-Inkijkexemplaar_1.pdf). + + The commonly used status letters are: + * `V` = Standard patient, part of the GP's population (dutch: _vast_). + * `T` = Temporary patient (likely do _not_ treat as part of GP's population). + * `P` = Opportunity patient (dutch: _passant_ - patient is not signed up with this GP. For example: tourist). + type: string + example: V +doctor: + description: |- + If known, the AGB code of the primary care GP (dutch: _Inschrijf arts_). + + Value 0 indicates this HIS or practice doesn't assign patients to individual GPs, + or this information isn't known. + type: number + example: 1051234 +address: + description: Patient's address (where they live). If not known, this property will not be in the response. + type: object + properties: + street: + description: Full name of the street, excluding house number. + type: string + example: Lange Geer + housenumber: + description: |- + Just the house number; 0 if unknown or in the exotic case where no house number exists. This does + not include any addendums such as 'A' or 'room 15'. Guaranteed to be non-negative, and at most 5 digits. + type: integer + example: 4 + housenumber_suffix: + description: |- + The string that follows the numeric part of the address house number. + + For example, `"A"`, or `"k22"`. Most addresses don't have one. + type: string + example: A + default: "" + postcode: + description: The post code, in `1234AB` format. If not known, blank. + type: string + example: 2611PV + city: + description: The city or town. + type: string + example: Delft +contact: + type: object + properties: + tel: + description: |- + Patient's phone number(s). + + By convention, the mobile number, if available, is always listed first. + + Phone numbers are always in international format (they start with a `+` symbol). + If no phone numbers are available or patient has no phone, an empty list is returned. + type: array + example: ["+31612345678", "+31701234567"] + items: + type: string + email: + description: |- + Patient's email address(es); first one returned is indicated as preferred. + + If no emails are known or available, or patient has no email, an empty list is returned. + type: array + items: + type: string + example: ["info@zorgoporde.nl"] +insurance: + description: |- + Info about where the patient is insured. + + If patient is not insured, this field will not be present. + + Only the main insurance used for reimbursement of GP costs will be returned, if any such insurance exists. + type: object + properties: + policy_number: + description: |- + Patient's insurance registration number (dutch: _polisnummer_). + + In theory can contain alphanumeric characters but no insurer does that as far as we know. + + _if_ the value is fully numeric, any leading zeroes will be stripped. + + We suggest this number is parsed and stored as a string; they can be longer than the limits of + 32-bit/64-bit numbers and therefore exceed JSON's limits on numeric values. + type: string + example: 123456789012345 + uzovi: + description: |- + Insurer's identity number in the dutch insurance system (dutch: _UZOVI nummer_). + + A value between 0 (no insurance) and 9999; these numbers are customary rendered as 4 digits. + When rendering, we suggest callers left-pad with zeroes. + type: number + example: 101 +patid: + description: |- + Patient's "public" ID, as used and shown on the HIS patient page. Not necessarily unique, + and not necessarily present; 0 indicates no patid is known or this HIS does not use (numeric) + public IDs. + + The primary purpose of this field is to show it to medical professionals working at this practice + who can use it to search for this dossier and is a way to communicate without sharing privacy-sensitive + details. + type: number + example: 1234 +pat_unid: + description: |- + Patient's unique and persistent ID in HIS. Usually identical to `patid` but certain HISes may + use UUID, or has globally unique keys (e.g. very large numbers). Can be blank, but only + if supplying HIS does not send them. + type: string + example: 1234 +start_date: + type: string + format: date + description: |- + Date patient joined the practice (dutch: _inschrijf datum_). + + In rare cases, a patient joined so long ago, this date is no longer known. In this case, + a sentinel value of `"1900-01-01"` is sent which is presumed to result in the desired behaviour + (which is to consider this patient as part of this practice's population regardless of how far + back you want to go). + example: 1994-08-20 +end_date: + type: string + format: date + description: |- + If present, patient has exited the practice on this date. (dutch: _uitschrijf datum_). + default: "" +end_reason: + description: |- + Reason patient left the practice (dutch: _reden vertrek_). + + This property is never present if `end_date` isn't present. Otherwise, this value _might_ contain + a non-blank letter as per [NHG-table-9](https://referentiemodel.nhg.org/sites/default/files/NHG-Tabel%209-Reden%20vertrek-versie-5-Inkijkexemplaar_1.pdf): + + * `A` = To other practice + * `V` = Moved + * `O` = died + * `T` = Temporary + * `I` = Care home / institution + * `Q` = unknown + * `X` = Other + type: string + default: "" diff --git a/schemas/med_dossier/Contraindication.yaml b/schemas/med_dossier/Contraindication.yaml new file mode 100644 index 0000000..ba56b7f --- /dev/null +++ b/schemas/med_dossier/Contraindication.yaml @@ -0,0 +1,19 @@ +type: object +required: + - description + - when +properties: + description: + description: |- + If possible, normalized, but usually a coding unique to the source system or manually typed by a practicioner. + + OPEN QUESTION: Given the unstructured nature of this field, contraindication does not appear usable to callers for anything + but showing it directly to a practicioner and hoping they know what it means. + type: string + example: 'RAYNAUD, FENOMEEN' + when: + description: |- + *OPTIONAL* If present, the date when this contraindication was registered. + type: string + format: date + example: "2019-02-05" diff --git a/schemas/med_dossier/Correspondence.yaml b/schemas/med_dossier/Correspondence.yaml new file mode 100644 index 0000000..28d3912 --- /dev/null +++ b/schemas/med_dossier/Correspondence.yaml @@ -0,0 +1,57 @@ +type: object +required: + - direction + - when + - text +properties: + direction: + description: |- + The direction of the correspondence. + * `S` means it was sent/initiated from the GP office to `other`. + * `R` means it was sent/initiated from `other` to the GP office. + * `X` means the direction isn't known. + type: string + example: S + enum: + - S + - R + - X + when: + description: |- + The date when this correspondence was received or sent. + type: string + format: date + example: "2023-03-31" + specialty_code: + description: |- + A short memocode representing the speciality of `other`. For example, `"OOG"` (eye specialist), `"CHI"` (Surgery), etc. Often blank. + + OPEN QUESTION: Is an explicitly enumerated list of all possible values warranted? We'd love to receive sources of such lists. + type: string + example: KNO + episode: + description: |- + *OPTIONAL* An ICPC code (formatted as e.g. `X99.12`) representing the problem or chronic illness that serves as context for this correspondence. + + Not all correspondence can be directly related to an ICPC code, and many source systems fundamentally do not allow linking correspondence to + a given medical issue. Hence, this field is usually blank. + type: string + pattern: '^[A-Z]\d{2}\.\d{2}$' + text: + description: |- + The content of the correspondence, as registered in the source system. This usually describes the nature of the content, or is merely a fragment + of the content, or is simply blank - most source systems do not store a copy of the entire conversation in text form. + type: string + example: Echo + other: + description: |- + A free-form textual description of the other party in this correspondence. + type: string + example: "Naar: Plastische chirurgie HMC, Den Haag" + practicioner: + $ref: 'Practicioner.yaml' + zd: + description: |- + If known and provided, The ZorgDomein message ID. ZD IDs are often used when referring a patient. Not all source systems provide these. + type: string + example: "ZD1234" diff --git a/schemas/med_dossier/Episode.yaml b/schemas/med_dossier/Episode.yaml new file mode 100644 index 0000000..99228fd --- /dev/null +++ b/schemas/med_dossier/Episode.yaml @@ -0,0 +1,45 @@ +type: object +required: + - icpc + - start + - mut +properties: + icpc: + description: |- + The ICPC1.1 (NL variant) code describing this problem / chronic condition. + + Guaranteed to be formatted as `X01.00`, _or_ blank (for HIS systems that allow registering problems / conditions without an ICPC). + + Note that certain ICPC1.1 codes are generally stated without the subcode, for example, `B73` (Leukemia). Nevertheless these are + returned by this API as `B73.00`. + type: string + pattern: '^[A-Z]\d{2}\.\d{2}$' + example: A97.00 + start: + description: |- + This problem / episode / chronic condition was opened on this date, usually because it was diagnosed on this date. + + Always provided, but may contain the sentinel value of `1900-01-01` if the source doesn't have a start date. Generally + such episodes are to be treated as having always been part of the patient's dossier. + type: string + format: date + example: 1900-01-01 + end: + description: |- + *OPTIONAL* If the episode has been determined to no longer be relevant (for example, cured), the date when the episode was closed. + type: string + format: date + example: "2022-12-31" + mut: + description: |- + The last time an event (for example, seeing the patient for chronic care related to this episode) was recorded in context of + this episode. Is guaranteed to be present and will never be earlier than `start`. + type: string + format: date + example: "2022-10-20" + description: + description: |- + *OPTIONAL* Most HIS source systems default the 'description' of an episode to the standard description for the provided ICPC, but allow the + practicioner to change this description. + type: string + example: "Geboorte dochter" diff --git a/schemas/med_dossier/Feat.yaml b/schemas/med_dossier/Feat.yaml new file mode 100644 index 0000000..f611206 --- /dev/null +++ b/schemas/med_dossier/Feat.yaml @@ -0,0 +1,46 @@ +type: object +required: + - vektis + - when +properties: + code: + description: |- + If present, the source uses a short code (a 'memocode') to represent feats, and this is the code associated with it. + type: string + example: ECG + vektis: + description: |- + The vektis code from list 8 (the list for feats GPs can declare) representing this feat. + + For custom feats that therefore cannot actually be declared with any insurance company, this value is 0. + type: number + example: 13005 + when: + description: |- + The stated feat was performed on this date. subscription style feats by convention always on the first day of a quarter. + format: date + type: string + example: "2023-02-28" + invoice: + description: |- + *OPTIONAL* If this feat has been declared, the invoice id that declared it. Not all source systems track this, and generally + invoices aren't instantly sent as feats are registered. Thus, if this field isn't provided, either the feat hasn't been invoiced yet, + or the source system doesn't track invoicing, or the GP office doesn't use the source system for invoicing. + type: string + example: A00001234 + gp: + description: |- + The GP responsible for this patient at the time of the feat. If income is redistributed to each GP participating in this practice, + this should be used to know where to send received funds to. + + Contents are free-form as it depends on the source system. + type: string + example: AA + practicioner: + $ref: 'Practicioner.yaml' + description: + description: |- + Some source systems allow adding a comment or description when registering a feat; often simply a copy of the description of + what `vektis` represents, but can be explicitly typed in by the practicioner registering this feat. + type: string + example: "12001: Dubbel consult huisarts" \ No newline at end of file diff --git a/schemas/med_dossier/Journal.yaml b/schemas/med_dossier/Journal.yaml new file mode 100644 index 0000000..d1ea775 --- /dev/null +++ b/schemas/med_dossier/Journal.yaml @@ -0,0 +1,79 @@ +type: object +required: + - when + - soap + - text +properties: + icpc: + description: |- + *OPTIONAL* An ICPC1.1-NL code representing the nature of this journal note. Does not necessarily mean the patient suffers from the condition + this ICPC represents. For example, a patient that comes in asking questions about signs of Diabetes would have journal text with ICPC `"T90.02"`, + even if tests show they clearly do not have Diabetes Mellitus. + + Not all journal texts have a context, or a context that can be expressed as an ICPC. + type: string + pattern: '^[A-Z]\d{2}.\d{2}$' + example: "A97.00" + episode: + description: |- + *OPTIONAL* An ICPC1.1-NL code representing the problem / chronic illness that this journal note has been filed under. + + In our experience the difference between `icpc` and `episode` are not well demarkated and practicioners do not necessarily use these fields + for their intended purpose. We suggest making no distinction between these 2 fields and accepting instead that this means journal text + can have up to 2 ICPCs associated with them. + type: string + pattern: '^[A-Z]\d{2}\.\d{2}$' + example: "T90.02" + when: + description: |- + The date when this journal text was typed and registered. + type: string + format: date + example: "2015-05-01" + text: + description: |- + The journal text as typed by the practicioner. Can, obviously, be quite long, and can contain newlines. + type: string + soap: + description: |- + Most medical systems separate journal text using the SOAP system (dutch: _SOEP_): + * `S`: Subjective (dutch: _Subjectief_) - A (transcription of the) description of the medical issue by the patient themselves + * `O`: Objective (dutch: _Objectief_) - The description of the medical issue as observed by a trained medical practicioner + * `A`: Analysis (dutch: _Evaluatie_) - The diagnosis. + * `P`: Plan (dutch: _Plan_) - The course of action to take, or notes about next steps to deal with the issue raised in this journal entry. + * `X`: Unknown - this text does not fit any of the 4 SOAP categories, or this represents journal text not written using the SOAP system. + + Any of these can be missing. For example, for tele-health various practices have internal policy to leave Objective blank, especially if + no video or pictures are made, because no medical professional is on hand to make an objective report about the stated issues. + + Often newlines appear in weird places, or newlines are not conveyed even if typed by the practicioner; these are limitations in the source system. + type: string + enum: + - S + - O + - A + - P + - X + example: S + practicioner: + $ref: 'Practicioner.yaml' + type: + description: |- + A code representing of the style of consult: + * N - note, generally made without the presence of the patient, for example to register that some lab value was received by mail. + * C - journal was registered as part of a consult (the patient was present). + * V - journal was registered during a visit to the patient's location. + * CT - journal was registered during a phone or other tele-consult. + * Other codes exist; depends on source system. + type: string + example: C + code: + description: |- + *OPTIONAL* If present, a short code representing a specific kind of action, such as a referral (`VER` - from dutch _Verwijzing_), + `H` for medication recipe refill (dutch: _Herhaalrecept_), `REC` for prescribing a recipe, `LAB` for processing laboratory results, + or `BVO` for a nationally organized checkup such as for Cervical Cancer (from dutch: _Bevolkingsonderzoek_). + + This coding depends on the source system, and not all source systems use this concept (if the source is such a system, this field is never present), + nor do they use standardized codes for this concept. + type: string + example: REC diff --git a/schemas/med_dossier/Measurement.yaml b/schemas/med_dossier/Measurement.yaml new file mode 100644 index 0000000..a8fe6c1 --- /dev/null +++ b/schemas/med_dossier/Measurement.yaml @@ -0,0 +1,69 @@ +type: object +required: + - code + - when + - value +properties: + code: + description: |- + NHG-standardized labcode (describes the nature of the measurement), as listed on + [Webtools NHG labcodeviewer](https://bepalingen.nhg.org/labcodes/determinations). + The full memo+mat+bijz code is provided with no separation. + + If the source allows custom labcodes, this value can contain a non-NHG-standard code. Most source systems do allow this. + + Guaranteed to be provided, and will never be blank. + + OPEN QUESTION: Would it be more convenient if this API guarantees the provided code is NHG compatible, relying on the `source_code` field + to represent such custom codes? + + OPEN QUESTION: Would it be more convenient if this API provides this code separated out into memo/mat/bijz, e.g. "KREA O MK" instead of "KREAOMK"? + type: string + example: KREAOMK + source_code: + description: |- + *OPTIONAL* If the source system uses a different code to represent this measurement in its own system, it is listed here. + + If present, guaranteed to be different from `nhg_code`. For example, a HIS might use `ROKENHG` instead of NHG-standard `ROOKAQ` to + represent registration of patient's smoking behaviour. + type: string + example: ROKENNHG + when: + description: |- + Date when this measurement was done. In practice it may instead represent the date when the measurement was registered + which might be a day or two after the measurement was actually performed; not all source systems make it possible to + distinguish the nature of the date. + type: string + format: date + example: "2023-04-30" + value: + description: |- + The value of the measurement. Normalized and NHG compatible if possible. For example, enumerated values (such as for `DMHBKZ` which + represents whether the general practicioner or the specialist is the primary caregiver for chronic diabetes mellitus care) use the + NHG numeric answer codes (in `DMHBKZ`'s case, `"48"` is returned if the GP is the primary caregiver, and `"49"` if the specialist is). + + If the source provides a value that is not understood by ZOO's normalizers, the source value is provided verbatim. + + This value can be blank; various labcodes simply represent that an act was performed and do not register any result. + + If the value is numeric (for example, systolic blood pressure: `nhg_code = "RRSYKA"`), the dot is used as fractional separator, regardless + of what the source has provided. + type: string + example: 48 + source_value: + description: |- + *OPTIONAL* The value of the measurement as reported by the source, verbatim (no normalization is applied in any way). + Only provided if meaningfully different from the normalized value. + type: string + example: HUISARTS + comment: + description: |- + *OPTIONAL* Some source systems allow adding a comment to any measurement; if one is present, it is provided here. + + Note that these can be quite lengthy, as sometimes a lab will add standard boilerplate text about how to interpret + the result in these fields. + type: string + example: >- + tekst Sensibilisatie voor algemeen voorkomende inhalatieallergenen (huisstofmijt, kat, hond, graspollen, boompollen, bijvoetpollen, kruidpollen) is op dit moment niet vastgesteld. + practicioner: + $ref: 'Practicioner.yaml' diff --git a/schemas/med_dossier/Medication.yaml b/schemas/med_dossier/Medication.yaml new file mode 100644 index 0000000..6ef9dc6 --- /dev/null +++ b/schemas/med_dossier/Medication.yaml @@ -0,0 +1,57 @@ +type: object +required: + - atc +properties: + atc: + description: |- + An [Anatomical Therapeutic Chemical (ATC)](https://en.wikipedia.org/wiki/Anatomical_Therapeutic_Chemical_Classification_System) level 5 code. + + OPEN QUESTION: Is it convenient to also send the dutch and/or english commonly accepted name for this ATC code? Feels wasteful in an API. + type: string + format: '^[A-Z]\d{2}[A-Z]{2}\d{2}$' + example: C03CA01 + prescribed: + description: |- + If present, the date when a practicioner prescribed this medication; possibly without actual medical review (e.g. just filing a refill request). + Depending on how the medication was dispensed, some dispensing entities (e.g. pharmacies) are linked with source systems and will cause a + medication record to be registered that has no prescriber or prescription date (because it wasn't prescribed; at least, not by this GP office), + but was picked up by the patient. + + We advise coalescing `prescribed` and `delivered`, as this guarantees an actual date. + type: string + format: date + example: "2023-03-27" + delivered: + description: |- + If present, the date when the patient received this medication (usually, because they picked it up at a pharmacy). Not all pharmacies are + linked to source systems and therefore, a blank value for `delivered` _may_ mean the prescription was never filled, or it _may_ mean the + entity that filled the prescription does not relay this to the source system. + + At least one of `prescribed` and `delivered` is guaranteed to have a value. + type: string + format: date + example: "2023-03-28" + prescriber: + $ref: "Practicioner.yaml" + end: + description: |- + The medication is intended to last the patient no further than this date, if present. If source system doesn't send this date (not all do), + an estimate based on the nature of the medication and the suggested dosage. + + If not present, this isn't the kind of medication that is designed to be used until symptoms fade or is no longer needed, or, + our normalization systems aren't capable of normalizing the dosage/form into a meaningful end date. + type: string + format: date + example: "2023-04-14" + description: + description: |- + This field is usually initialized with a general dutch name for the medication, but can be overwritten with custom text by the prescriber. + + Can describe the general medication or the specific brand name; it varies considerably between source systems. + type: string + example: "CUTISOFT NWK ST 10X10 48851" + pharmacy: + description: |- + *OPTIONAL* If automatically sent to a specific pharmacy, some source-system custom coding that indicates which pharmacy it was sent to. + type: string + example: AN \ No newline at end of file diff --git a/schemas/med_dossier/Practicioner.yaml b/schemas/med_dossier/Practicioner.yaml new file mode 100644 index 0000000..29a1566 --- /dev/null +++ b/schemas/med_dossier/Practicioner.yaml @@ -0,0 +1,14 @@ +description: |- + The medical practicioner (could be a doctor, an assistant, a chronic care specialist working at the GP, etc) who is responsible for entering this + information. Can be an assistant simply entering data from external sources; necessarily refers to somebody who works for the GP that is the source + of this medical dossier. + + The format of this string depends on the source. It's sometimes a short 'memo code', sometimes an ID (such as a BIC registry number or AGB code), + sometimes a full name. + + OPEN QUESTION: Would it be useful if this field is more structured and e.g. explains what it is, or that this field contains an ID that can be + separately looked up using another API endpoint; we are very dependent on the source for the nature of this information, but some e.g. provide + the doctor under whose authority a practicioner is operating, which could be useful information. We can't guarantee that we can provide this data + in a specific structure due to fundamental differences between HIS vendors, hence why right now this field is free-form. +type: string +example: AA \ No newline at end of file diff --git a/zoo-api.yaml b/zoo-api.yaml index 7146454..67ba868 100644 --- a/zoo-api.yaml +++ b/zoo-api.yaml @@ -81,8 +81,20 @@ components: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJraWQiOiJaT08tQVBJLVBLSS1JRCIsImFnYiI6IjAxMDEyMzQ1IiwiaWF0IjoxNTE2MjM5MDIyLCJqdGkiOiJ0MTIzNC01Njc4LUFCQ0QifQ.wTesCfFTq1Mz8z7hUWU6zzKSc3dopWnpeETR7eDzFtc responses: + ReqFailure: + description: |- + The request isn't valid; for example, it is missing a required parameter. + content: + application/json: + type: object + properties: + err: + description: A plain text explanation of what's wrong with the request + type: string + example: Either pu or bsn query parameter needs to be present and not blank. JwtFailure: - description: The JWT token isn't valid or wasn't provided. + description: |- + The JWT token isn't valid or wasn't provided. content: application/json: schema: