FHIR model of the prescription
Introduction
Modeling the prescription scan result is based on the use of the FHIR resources Bundle
, RequestGroup
, MedicationRequest
, Patient
and Practitioner
.
Reminder of FHIR documentation
Only one RequestGroup
object is generated. It directly contains the other necessary resources and does not depend on an external system, so it is completely autonomous.
Different value sets and terminologies are used and documented. In the absence of explicit mention, the value sets suggested by HL7 are used.
Attention !
The exact content of the FHIR prescription resource will evolve according to advances in dosage recognition. You will be notified in advance in the event of significant changes (which are not planned at the moment).
Description of objects
RequestGroup
object
This object represents the order itself
RequestGroup example
{
"resourceType": "RequestGroup",
// unique identifier for the whole prescription
"identify": [
{
"system": "id://posos",
"value": "aca3fb04-dc8c-4091-b7f9-c907eea05d1d"
}
],
// Raw prescription as read by our scanner and converted in very basic html
"text": {
"status": "generated",
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\"><ul><li>CELLCEPT 500<br/>1 tablet morning and evening for 15 days</li ><li>CORDANCYL 20<br/>60 mg per day in the morning with breakfast for 3 weeks then 50 mg per day in the morning for 3 weeks then 40 mg per day in the morning for 3 weeks then 30 mg per day in the morning for 3 weeks </li></ul></div>"
},
"contained": [
// List of all embedded Medications, MedicationRequest(s), Patient and Practitioner resources
],
// if it can be read, the date of authoring
"authoredOn": "2022-04-01T12:32:00.000Z",
"status": "draft", // POSOS will always push prescriptions as draft
"intent": "order",
// This represents the Patient entity to link the prescription to
"subject": {
"reference": "urn:uuid:68ff0a08-89f5-408b-9d78-1106cba4c44d"
},
// Beware we're sending here who is scanning the prescription, not its original author
"author": {
"reference": "urn:uuid:a3e2ce74-ff1f-443f-86b0-f9c53417749b"
},
// Each action is a reference to a MedicationRequest
"action": [
{
"resource": {
"reference": "#511e1fa4-2aed-4cd9-a64e-2c652a266ddc"
}
},
{
"resource": {
"reference": "#5e9eadf9-7730-47f9-bbe2-a87216db252c"
}
}
]
}
Included object - MedicationRequest
A prescription line, often concerns a single medication and dosage instructions.
MedicationRequest Example
{
"resourceType": "MedicationRequest",
// Unique identifier for the prescription line
"id": "511e1fa4-2aed-4cd9-a64e-2c652a266ddc",
"text": {
"status": "generated",
// Raw text as read by our scanner
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">Cellcept 500mg<br/>1 tablet morning and evening for 15 days</div>"
},
"status": "draft", // same as in RequestGroup
"intent": "order", // same as in RequestGroup
// should be same as in RequestGroup
"subject": {
"reference": "urn:uuid:68ff0a08-89f5-408b-9d78-1106cba4c44d"
},
// The prescribed medication, a reference to the Medication resource defined in `contained` field
"medicationReference": {
"reference": "#93bd1aa2-7a85-47e1-b332-e3caccdf5cb9"
},
// Dosage conforms to FHIR Dosage resource
"dosageInstruction": [
{
// There is always at least a text representation.
// For complex dosages where no model could be inferred, only text will be present
"text": "1 tablet morning and evening for 15 days",
// “1 tablet morning and evening for 15 days”
// "for 15 periods of 1 day, take 2 times per period during breakfast and dinner"
"timing": {
"repeat": {
"count": 15, // for 15 periods
"period": 1, // of 1
"periodUnit": "d", // day
"frequency": 2, // take 2 times
"when": ["CM", "CV"] // during breakfast and dinner
// when values are from http://hl7.org/fhir/valueset-event-timing.html
}
},
// it doesn't apply for this drug but we may also provides with
// an administration route
// "route": {
// "text": "intramusculaire",
// "coding": [
// {
// "system": "http://snomed.info/sct",
// "code": "78421000",
// "display": "Intramuscular use"
// }
// ]
// },
// for each take, take 1 tablet
"doseAndRate": [
{
"doseQuantity": {
"value": 1,
"unit": "comprimé",
"system": "http://terminology.hl7.org/CodeSystem/v3-orderableDrugForm",
"code": "TAB"
}
}
]
}
]
}
Object included - Medication
A medication linked to a MedicationRequest
.
Medication Example
{
"resourceType": "Medication",
"id": "da084efc-01ad-4614-a92a-2573120664b7",
// Different coding of this drug in different terminologies
// There should always be at least a DCI or ATC code
"coded": {
"coding": [
{
"system": "http://posos.on.fhir/shortname",
"code": "cortancyl",
"display": "cortancyl"
},
{
"system": "http://posos.on.fhir/dci",
"code": "prednisone",
"display": "Prednisone"
},
{
"system": "http://www.whocc.no/atc",
"code": "H02AB",
"display": "GLUCOCORTICOIDES"
}
]
},
// Active ingredient of the medication
// Substance is coded with DCI
"ingredient": [
{
"itemCodeableConcept": {
"coding": {
"system": "http://posos.on.fhir/dci",
"code": "prednisone",
"display": "Prednisone"
}
},
// Strength is a bit cumbersome for tablets
// It must be read as "20mg per 1 tablet"
"strength": {
"numerator": {
"value": 20,
"system": "http://unitsofmeasure.org",
"code": "mg"
},
"denominator": {
"value": 1,
"system": "http://terminology.hl7.org/CodeSystem/v3-orderableDrugForm",
"code": "TAB"
}
}
}
]
}
Patient
object
The patient concerned by the prescription: it must be defined to attach the prescription to the correct patient file in the destination system.
Patient Example
{
"resourceType": "Patient",
"id": "urn:uuid:68ff0a08-89f5-408b-9d78-1106cba4c44d",
// Patient are just identified by an identifier coming from destination system
"identify": [
{
"system": "id://partner",
"value": "38fd36cc-2148-4ee5-852a-4f0533d0c375"
}
]
}
Practitioner
object
The practitioner who scanned the prescription.
Practitioner Example
{
"resourceType": "Practitioner",
"id": "urn:uuid:a3e2ce74-ff1f-443f-86b0-f9c53417749b",
// Practitioner are identified in both destination system and POSOS
"identify": [
{
"system": "id://partner",
"value": "9e3f7b92-6ca3-4466-b970-abae9b56b4fa"
},
{
"system": "id://posos",
"value": "3e71ff9a-221b-497b-983a-f546cf8b9ea4"
}
]
}
Observation
object
Any patient observations detected by the scan. Includes weight, height, BMI and age.
Observation Example
{
"resourceType": "Observation",
"id": "647d6030-5600-4a31-b1d7-bc854b95a53f",
"status": "preliminary",
"category": [
{
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/observation-category",
"code": "vital-signs",
"display": "Vital Signs"
}
],
"text": "Vital Signs"
}
],
"coded": {
"coding": [
{
"system": "http://loinc.org",
"code": "21612-7",
"display": "Age - Reported"
}
],
"text": "Age"
},
"subject": {
"reference": "urn:uuid:f7d09973-4677-4fb5-822d-35f63566f4ea"
},
"valueQuantity": {
"value": 46,
"unit": "a",
"system": "http://unitsofmeasure.org",
"code": "a"
}
}
DocumentReference
object
Informations about the prescription PDF document generated by the scan are available in a DocumentReference object inside the bundle as an independant entry with the following structure:
DocumentReference exemple
{
"resourceType": "DocumentReference",
"id": "f7d09973-4677-4fb5-822d-35f63566f4ea",
"identifier": [
{
"use": "usual",
"system": "https://terminology.posos.co/storage-path",
"value": "https://internalpososurl/423132123.pdf"
}
],
"status": "current",
"content": [
{
"attachment": {
"url": "https://publictemporaryurl/9123891.pdf",
"data": "efc2b..."
}
}
]
}
- The field
identifier[0].value
contains an internal POSOS URL for the document and is not accessible for public use - The field status contains either “current” if the document was successfully saved, or “entered-in-error” if there was an error processing the document. If there was an error, the object
content[0].attachment
will be empty . - The field content always has a single object and
content[0].attachment.url
contains the public URL to download the prescription PDF document (available for 24h after the scan). The “data” field may has a value depending on the configuration and if so, will contain the PDF document content as base64
In addition, this DocumentReference is referenced by an extension in the RequestGroup:
RequestGroup example with extension
{
...,
"extension": [
...,
{
"url": "https://terminology.posos.co/fhir-extension/requestgroup/prescriptionDocumentReference",
"valueReference": { "reference": "urn:uuid:f7d09973-4677-4fb5-822d-35f63566f4ea" }
}
]
}
Format v1 (deprecated)
This response format is deprecated and should no longer be used. It is retained to ensure backwards compatibility. It can be enabled by passing the shouldSimplify=true
parameter to the prescription scan API.
Interface
type ScanOrdoApiResponse = {
patientObservations?: {
age?: number;
weight?: number;
height?: number;
};
drugs: {
entity: string;
dci: string[];
boundingPolyVertices?: [
{ x: number; y: number },
{ x: number; y: number },
{ x: number; y: number },
{ x: number; y: number }
];
strength?: string;
isStrengthInMedicalDB?: boolean;
dosage?: string;
structuredDosage?: DosageInstruction[];
form?: string;
}[];
};
Example
{
"patientObservations": {
"age": 45,
"weight": 73,
"height": 175
},
"drugs": [
{
"entity": "inexium",
"dci": ["esomeprazole"],
"boundingPolyVertices": [
{ "x": 133, "y": 173 },
{ "x": 251, "y": 172 },
{ "x": 251, "y": 194 },
{ "x": 133, "y": 195 }
],
"strength": "20 mg",
"isStrengthInMedicalDB": true,
"dosology": "Take 1 tablet in the evening, for 1 month.",
"structuredDosage": [
{
"frequency": 1,
"period": 1,
"period_unit": "day",
"bounds_duration": {
"value": 1,
"unit": "month"
},
"when": ["EVE"],
"frequency_texts": ["evening"],
"duration_text": "for 1 month"
}
]
}
]
}
The object contains a patientObservations
field containing:
Attribute | Description |
---|---|
age | the age of the patient in years if it exists |
weight | the patient’s weight in kg if it exists |
height | the height of the patient in cm if it exists |
A drugs
field containing the list of recognized drugs. Each medication is at least described by 2 concepts:
Attribute | Description |
---|---|
dci | a table field containing a single character string corresponding to the common name of the recognized drug |
entity | the shortname of the drug if it is recognized, otherwise its dci. |
The following fields are not always present:
Attribute | Description |
---|---|
boundingPolyVertices | the coordinates of the text which was used to recognize the medicine. If the image sent is a PDF, these coordinates will be normalized (between 0 and 1). Otherwise, they will be in pixels. |
strength | the quantity of active substance (commonly called dosage); if none could be recognized, the value is null . |
isStrengthInMedicalDB | flag worth true if the strength is recognized AND has been identified and validated in our drug information base, false otherwise. |
form | the prescribed form if recognized AND in our drug information base. Absent otherwise. |
dosage | the dosage in unstructured textual form as written in the prescription. Absent if no dosage indication could be detected. |
structuredDosology | the dosage in structured form (a list of PosologyInstruction ), it is an array of different information extracted from the value of posology . The concepts and syntax used are similar to the Dosage and Timing resources of FHIR |
DosageInstruction
Attribute | Description |
---|---|
frequency | frequency of taking the medication (if frequency_max exists, frequency corresponds to the minimum frequency) |
frequency_max | maximum frequency |
period | matches the period during which frequency takes take place |
period_unit | unit of the period |
period_max | corresponds to the maximum period |
bounds_duration | duration of treatment |
time_of_day | table of string , times of day when the treatment must be taken (8 a.m., 12:30 p.m., …) |
day_of_week | array of string , days of the week the treatment should be taken (mon, tue, wed, thur, fri, sat, sun) |
when | table of string , times of the day at which the processing takes place (the meanings of the codes are explained on this site [https://www.hl7.org/fhir/valueset-event-timing.html#definition](https ://www.hl7.org/fhir/valueset-event-timing.html#definition) |
offset | time interval between taking and when, in minutes |
sequence | number starting at 0 indicating the succession of dosages (2 tablets for one week then 1 tablet for 1 month) |
frequency_texts | array of string , list of different texts corresponding to frequencies |
bounds_duration_text | string , text corresponding to the processing duration |
quantity_and_rate | QuantityAndRate , information on the quantity of medicine per dose/per unit of time |
BoundsDuration
Attribute | Description |
---|---|
unit | unit of treatment duration |
value | (minimum) duration of treatment |
max_value | maximum duration of treatment |
QuantityAndRate
Attribute | Description |
---|---|
value | quantity of units detected |
unit | normalized unit (among a list of entities) |
type | “QANTITY”, “DOSE” or “STRENGTH”. |
rate | Rate When a fraction is detected, the rate attribute is added to the value attribute with the values and units of the numerator and denominator. |
Missed
Attribute | Description |
---|---|
numerator | quantity of the numerator |
denominator | quantity of denominator |
numerator_unit | numerator unit |
denominator_unit | denominator unit |
Example of prescription
Original file
Structured API response
full-bundle.json
{
"fhirBundle": {
"resourceType": "Bundle",
"type": "transaction",
"entry": [
{
"resource": {
"resourceType": "Patient",
"identify": [
{
"system": "id://partner"
}
]
},
"fullUrl": "urn:uuid:68ff0a08-89f5-408b-9d78-1106cba4c44d",
"request": {
"method": "POST",
"url": "Patient"
}
},
{
"resource": {
"resourceType": "Practitioner",
"identify": [
{
"system": "id://partner",
"value": "partner-id"
},
{
"system": "id://posos"
}
]
},
"fullUrl": "urn:uuid:a3e2ce74-ff1f-443f-86b0-f9c53417749b",
"request": {
"method": "POST",
"url": "Practitioner"
}
},
{
"resource": {
"resourceType": "RequestGroup",
"identify": [
{
"system": "id://posos",
"value": "145e8b78-8757-4b06-9fdc-a695b0d96add"
}
],
"text": {
"status": "generated",
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\"><ul><li>cellcept - 1 tab morning and evening for 15 days</li><li> cortancyl - 60 mg per day in the morning with breakfast for 3 weeks then 50 mg/day in the morning for 3 weeks then 40 mg/day in the morning for 3 weeks then 30 mg/day in the morning for 3 weeks</li></ ul></div>"
},
"authoredOn": "2023-01-31",
"status": "draft",
"intent": "order",
"subject": {
"reference": "urn:uuid:68ff0a08-89f5-408b-9d78-1106cba4c44d"
},
"author": {
"reference": "urn:uuid:a3e2ce74-ff1f-443f-86b0-f9c53417749b"
},
"contained": [
{
"resourceType": "Medication",
"id": "2af172dd-77e9-4f97-979f-c570c09abc57",
"coded": {
"coding": [
{
"system": "http://posos.on.fhir/dci",
"code": "mycophenolic acid",
"display": "mycophenolic acid"
},
{
"system": "http://www.whocc.no/atc",
"code": "L04AA06",
"display": "MYCOPHENOLIC ACID"
},
{
"system": "http://posos.on.fhir/form",
"code": "film-coated tablet",
"display": "film-coated tablet"
}
]
},
"ingredient": [
{
"itemCodeableConcept": {
"coding": [
{
"system": "http://posos.on.fhir/dci",
"code": "mycophenolic acid",
"display": "mycophenolic acid"
}
]
}
}
],
"extension": [
{
"url": "http://fhir.posos.co/extensions/medication/isStrengthInMedicalDb",
"valueBoolean": false
}
]
},
{
"resourceType": "Medication",
"id": "0f6aa3bb-11c7-482e-ae68-034064ef0974",
"coded": {
"coding": [
{
"system": "http://posos.on.fhir/shortname",
"code": "cortancyl",
"display": "cortancyl"
},
{
"system": "http://posos.on.fhir/dci",
"code": "prednisone",
"display": "prednisone"
},
{
"system": "http://www.whocc.no/atc",
"code": "H02AB07",
"display": "PREDNISONE"
},
{
"system": "http://bdpm/cis",
"code": "62390849",
"display": "CORTANCYL 20 mg, scored tablet"
},
{
"system": "http://posos.on.fhir/dose",
"code": "20 mg",
"display": "20 mg"
}
]
},
"ingredient": [
{
"itemCodeableConcept": {
"coding": [
{
"system": "http://posos.on.fhir/dci",
"code": "prednisone",
"display": "prednisone"
}
]
}
}
],
"extension": [
{
"url": "http://fhir.posos.co/extensions/medication/isStrengthInMedicalDb",
"valueBoolean": true
}
]
},
{
"resourceType": "MedicationRequest",
"id": "f9d47860-9f29-4c09-b458-f5bdf0e10a6b",
"subject": {
"reference": "urn:uuid:68ff0a08-89f5-408b-9d78-1106cba4c44d"
},
"text": {
"status": "generated",
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">cellcept - 1 tab morning and evening for 15 days</div>"
},
"status": "draft",
"intent": "order",
"medicationReference": {
"reference": "#2af172dd-77e9-4f97-979f-c570c09abc57"
},
"dosageInstruction": [
{
"timing": {
"repeat": {
"boundsDuration": {
"unit": "day",
"value": 15
},
"frequency": 2,
"period": 1,
"periodUnit": "d",
"when": ["EVE", "MORN"]
}
},
"doseAndRate": [
{
"doseQuantity": {
"unit": "tablet(s)",
"value": 1
}
}
],
"asNeededBoolean": false,
"text": "1 teaspoon morning and evening for 15 days"
}
]
},
{
"resourceType": "MedicationRequest",
"id": "dbbd4fb9-d331-48bb-9bfc-3d22d9355318",
"subject": {
"reference": "urn:uuid:68ff0a08-89f5-408b-9d78-1106cba4c44d"
},
"text": {
"status": "generated",
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">cortancyl - 60 mg per day in the morning with breakfast for 3 weeks then 50 mg/day in the morning for 3 weeks then 40 mg/day in the morning for 3 weeks then 30 mg/day in the morning for 3 weeks</div>"
},
"status": "draft",
"intent": "order",
"medicationReference": {
"reference": "#0f6aa3bb-11c7-482e-ae68-034064ef0974"
},
"dosageInstruction": [
{
"timing": {
"repeat": {
"boundsDuration": {
"unit": "week",
"value": 3
},
"frequency": 1,
"period": 1,
"periodUnit": "d",
"when": ["CM"]
}
},
"doseAndRate": [
{
"doseQuantity": {
"unit": "mg",
"value": 60
}
}
],
"asNeededBoolean": false,
"text": "60 mg per day in the morning with breakfast for 3 weeks then 50 mg/day in the morning for 3 weeks then 40 mg/day in the morning for 3 weeks then 30 mg/day in the morning for 3 weeks"
},
{
"timing": {
"repeat": {
"boundsDuration": {
"unit": "week",
"value": 3
},
"frequency": 1,
"period": 1,
"periodUnit": "d",
"when": ["MORN"]
}
},
"doseAndRate": [
{
"doseQuantity": {
"unit": "mg",
"value": 50
}
}
],
"asNeededBoolean": false,
"text": "60 mg per day in the morning with breakfast for 3 weeks then 50 mg/day in the morning for 3 weeks then 40 mg/day in the morning for 3 weeks then 30 mg/day in the morning for 3 weeks"
},
{
"timing": {
"repeat": {
"boundsDuration": {
"unit": "week",
"value": 3
},
"frequency": 1,
"period": 1,
"periodUnit": "d",
"when": ["MORN"]
}
},
"doseAndRate": [
{
"doseQuantity": {
"unit": "mg",
"value": 40
}
}
],
"asNeededBoolean": false,
"text": "60 mg per day in the morning with breakfast for 3 weeks then 50 mg/day in the morning for 3 weeks then 40 mg/day in the morning for 3 weeks then 30 mg/day in the morning for 3 weeks"
},
{
"timing": {
"repeat": {
"boundsDuration": {
"unit": "week",
"value": 3
},
"frequency": 1,
"period": 1,
"periodUnit": "d",
"when": ["MORN"]
}
},
"doseAndRate": [
{
"doseQuantity": {
"unit": "mg",
"value": 30
}
}
],
"asNeededBoolean": false,
"text": "60 mg per day in the morning with breakfast for 3 weeks then 50 mg/day in the morning for 3 weeks then 40 mg/day in the morning for 3 weeks then 30 mg/day in the morning for 3 weeks"
}
]
}
],
"action": [
{
"resource": {
"reference": "#f9d47860-9f29-4c09-b458-f5bdf0e10a6b"
}
},
{
"resource": {
"reference": "#dbbd4fb9-d331-48bb-9bfc-3d22d9355318"
}
}
]
},
"fullUrl": "urn:uuid:64b96df4-774b-47ab-a8f2-7075f211dbee",
"request": {
"method": "POST",
"url": "RequestGroup"
}
}
]
}
}