First-Class Extensions

First-class extension as Zen profile

In order to define first-class extension as zen profile you should follow the steps below:
  1. 1.
    ​Initialize zen project and add additional IGs if necessary
  2. 2.
    Define your custom first-class extension
    1
    {ns my-zen-project
    2
    import #{zen.fhir hl7-fhir-r4-core.string}
    3
    ​
    4
    MyPatientProfile
    5
    {:zen/tags #{zen/schema zen.fhir/profile-schema}
    6
    :zen.fhir/version "0.5.8"
    7
    :confirms #{zen.fhir/Resource}
    8
    :zen.fhir/type "Patient"
    9
    :zen.fhir/profileUri "urn:profile:MyPatientProfile"
    10
    :type zen/map
    11
    :keys
    12
    {:meta {:type zen/map
    13
    :keys
    14
    {:tenant-id
    15
    {:confirms #{hl7-fhir-r4-core.string/schema}
    16
    :fhir/extensionUri "http://tenant-id-extension-url"}}}}}}
    Copied!
  3. 3.
    Fix :zen.fhir/version errors if needed
    In order to fix this error, provide IG bundle with the matching zen FHIR version.
    Error message example
    1
    Expected '0.5.8', got '0.4.9'
    2
    path: [:zen.fhir/version]
    Copied!
  4. 4.
    :fhir/extensionUrl property value
    Note: :fhir/extensionUri "http://tenant-id-extension-url" it is equivalent of the extensionUrl field of the Attribute resource it is used to form FHIR extension. And also it is important to use FHIR type instead of plain zen type, i.e. use :confirms #{hl7-fhir-r4-core.string/schema} instead of :type zen/string.

Define new extension

In Aidbox, you can define first-class extensions using the custom resource Attribute.
Let's create an extension definition of type Reference in the REST Console of Aidbox:
Create new extension in the Aidbox format:
1
PUT /Attribute/ServiceRequest.requestedOrganizationDepartment
2
​
3
description: Department in the organization that made the service request
4
resource: {id: ServiceRequest, resourceType: Entity}
5
path: [requestedOrganizationDepartment]
6
type: {id: Reference, resourceType: Entity}
7
refers:
8
- Organization
9
extensionUrl: urn:extension:requestedOrganizationDepartment
Copied!
  • description - string.
    Attribute text description
  • resource - required, Reference(Entity).
    Reference to a target resource type
  • path - required, array of strings.
    Path to a new attribute location in the target resource type
  • type - Reference(Entity).
    Type of data stored in this attribute. Can be any primitive or complex type.
    If omitted, treated as BackboneElement, i.e. a complex-type object with structure defined via other Attributes relying on this attribute in their path
  • isCollection - boolean.
    Whether the attribute is a collection, i.e. if true sets attribute cardinality to ..*
  • isRequired - boolean.
    Whether the attribute is required, i.e. if true sets attribute cardinality to 1..
  • refers - Reference(Entity).
    Only for type=Reference. Specifies to which resourceTypes this reference can refer to
  • extensionUrl - string.
    URL which will be used to create extension element in FHIR format. If omitted, Attribute won't be transformed in FHIR format

Use your extension

Now, you can create the ServiceRequest resource using the new attribute requestedOrganizationDepartment in the root of the resource:
Create resource in the Aidbox format:
1
PUT /ServiceRequest/servicerequest-with-aidbox-native-extensions
2
​
3
requestedOrganizationDepartment:
4
resourceType: Organization
5
display: City Hospital Neurology Department
6
identifier: {system: 'urn:oid:1.2.3.4.5.6.7.8', value: '456'}
7
category:
8
- coding:
9
- {code: '183829003',
10
system: 'http://snomed.info/sct',
11
display: "Refer for imaging"}
12
authoredOn: '2020-01-18T15:08:00'
13
resourceType: ServiceRequest
14
requester:
15
resourceType: PractitionerRole
16
display: Din Morgan
17
identifier: {value: "1760", system: 'urn:oid:1.2.3.4.5.6.7.6'}
18
priority: routine
19
status: active
20
intent: original-order
21
performer:
22
- resourceType: Organization
23
display: Aga Khan University Hospital Laboratory
24
identifier: {value: "1514", system: 'urn:oid:1.2.3.4.5.6.7.8'}
25
subject:
26
resourceType: Patient
27
display: Jack Black, 10.12.1941
28
identifier: {value: '2155800871000065', system: 'urn:oid:1.2.3.4.5.6.7.9'}
Copied!

FHIR Format

You can get the resource in the FHIR format where our new attribute is rendered as the extension element:
Note that the URL is different:GET /fhir/ServiceRequest/
Request
Response
Get the resource in the FHIR format:
1
GET /fhir/ServiceRequest/servicerequest-with-aidbox-native-extensions
Copied!
1
extension:
2
- url: urn:extension:requestedOrganizationDepartment
3
valueReference:
4
type: Organization
5
identifier: {value: '456', system: 'urn:oid:1.2.3.4.5.6.7.8'}
6
display: City Hospital Neurology Department
7
category:
8
- coding:
9
- {code: '183829003',
10
system: 'http://snomed.info/sct',
11
display: "Refer for imaging"}
12
meta:
13
lastUpdated: '2020-02-04T09:15:18.664293Z'
14
versionId: '32'
15
extension:
16
- {url: 'ex:createdAt', valueInstant: '2020-02-04T09:12:20.103301Z'}
17
authoredOn: '2020-01-18T15:08:00'
18
resourceType: ServiceRequest
19
requester:
20
type: PractitionerRole
21
identifier: {value: '1760', system: 'urn:oid:1.2.3.4.5.6.7.6'}
22
display: Din Morgan
23
priority: routine
24
status: active
25
id: servicerequest-with-aidbox-native-extensions
26
intent: original-order
27
subject:
28
type: Patient
29
identifier: {value: '2155800871000065',
30
system: 'urn:oid:1.2.3.4.5.6.7.9'}
31
display: Jack Black, 10.12.1941
32
performer:
33
- type: Organization
34
identifier: {value: '1514', system: 'urn:oid:1.2.3.4.5.6.7.8'}
35
display: Aga Khan University Hospital Laboratory
Copied!

Other extension examples

Let's create an extension of type Reference and list allowed resource types (Organization in that case) in the refers property.
managingOrganization
1
PUT /Attribute/ServiceRequest.managingOrganization
2
​
3
resourceType: Attribute
4
description: Organization that made the service request
5
resource: {id: ServiceRequest, resourceType: Entity}
6
path: [managingOrganization]
7
id: ServiceRequest.managingOrganization
8
type: {id: Reference, resourceType: Entity}
9
refers:
10
- Organization
11
extensionUrl: urn:extension:requestedOrganization
Copied!
Extension of type Coding:
paymentType
1
PUT /Attribute/ServiceRequest.paymentType
2
​
3
resourceType: Attribute
4
description: Payment type for the service request, e.g. government health insurance
5
id: ServiceRequest.paymentType
6
resource:
7
id: ServiceRequest
8
resourceType: Entity
9
path:
10
- paymentType
11
type:
12
id: Coding
13
resourceType: Entity
14
extensionUrl: urn:extension:paymentType
Copied!
Create resource using these extensions:
1
PUT /ServiceRequest/servicerequest-with-aidbox-native-extensions
2
​
3
managingOrganization:
4
resourceType: Organization
5
display: City Hospital
6
identifier: {value: "123", system: 'urn:oid:1.2.3.4.5.6.7.8'}
7
requestedOrganizationDepartment:
8
resourceType: Organization
9
display: City Hospital Neurology Department
10
identifier: {system: 'urn:oid:1.2.3.4.5.6.7.8', value: '456'}
11
paymentType: {system: 'urn:CodeSystem:paymentType',
12
code: "1",
13
display: "Government Health Insurance"}
14
resourceType: ServiceRequest
15
status: active
16
intent: original-order
17
subject:
18
resourceType: Patient
19
display: Jack Black, 10.12.1941
20
identifier: {value: '2155800871000065', system: 'urn:oid:1.2.3.4.5.6.7.9'}
Copied!
Request
Response
Get resource in the FHIR format:
1
GET /fhir/ServiceRequest/servicerequest-with-aidbox-native-extensions
Copied!
1
resourceType: ServiceRequest
2
extension:
3
- url: urn:extension:requestedOrganization
4
valueReference:
5
type: Organization
6
identifier: {value: '123', system: 'urn:oid:1.2.3.4.5.6.7.8'}
7
display: City Hospital
8
- url: urn:extension:requestedOrganizationDepartment
9
valueReference:
10
type: Organization
11
identifier: {value: '456', system: 'urn:oid:1.2.3.4.5.6.7.8'}
12
display: City Hospital Neurology Department
13
- url: urn:extension:paymentType
14
valueCoding: {code: '1',
15
system: 'urn:CodeSystem:paymentType',
16
display: Government Health Insurance}
17
status: active
18
id: servicerequest-with-aidbox-native-extensions
19
intent: original-order
20
subject:
21
type: Patient
22
identifier: {value: '2155800871000065', system: 'urn:oid:1.2.3.4.5.6.7.9'}
23
display: Jack Black, 10.12.1941
Copied!

Nested extensions

Let's create a structure of nested attributes:
performerInfo
1
PUT /Attribute/ServiceRequest.performerInfo
2
​
3
resourceType: Attribute
4
description: Information filled in by performer
5
resource: {id: ServiceRequest, resourceType: Entity}
6
path: [performerInfo]
7
id: ServiceRequest.performerInfo
8
extensionUrl: urn:extension:performerInfo
Copied!
performerInfo.performedBy
1
PUT /Attribute/ServiceRequest.performerInfo.performedBy
2
​
3
resourceType: Attribute
4
description: 'Information filled in by performer: performed by ["Practitioner" "PractitionerRole" "Organization" "CareTeam" "HealthcareService" "Patient" "Device" "RelatedPerson"]'
5
resource: {id: ServiceRequest, resourceType: Entity}
6
path: [performerInfo, performedBy]
7
id: ServiceRequest.performerInfo.performedBy
8
type: {id: Reference, resourceType: Entity}
9
isCollection: true
10
refers:
11
- Practitioner
12
- PractitionerRole
13
- Organization
14
- CareTeam
15
- HealthcareService
16
- Patient
17
- Device
18
- RelatedPerson
19
extensionUrl: urn:extension:performerInfo.performedBy
Copied!
performerInfo.actualLocationReference
1
PUT /Attribute/ServiceRequest.performerInfo.actualLocationReference
2
​
3
resourceType: Attribute
4
description: 'Information filled in by performer: actual location reference'
5
resource: {id: ServiceRequest, resourceType: Entity}
6
path: [performerInfo, actualLocationReference]
7
id: ServiceRequest.performerInfo.actualLocationReference
8
type: {id: Reference, resourceType: Entity}
9
isCollection: true
10
refers:
11
- Location
12
extensionUrl: urn:extension:performerInfo.actualLocationReference
Copied!
performerInfo.requestStatus
1
PUT /Attribute/ServiceRequest.performerInfo.requestStatus
2
​
3
resourceType: Attribute
4
description: 'Information filled in by performer: request status'
5
resource: {id: ServiceRequest, resourceType: Entity}
6
path: [performerInfo, requestStatus]
7
id: ServiceRequest.performerInfo.requestStatus
8
type: {id: code, resourceType: Entity}
9
enum:
10
- draft
11
- new
12
- in-progress
13
- suspended
14
- expanded
15
- completed
16
- archive
17
- cancelled
18
extensionUrl: urn:extension:performerInfo.requestStatus
Copied!
performerInfo.requestActionHistory
1
PUT /Attribute/ServiceRequest.performerInfo.requestActionHistory
2
​
3
resourceType: Attribute
4
description: 'Information filled in by performer: request action history'
5
resource: {id: ServiceRequest, resourceType: Entity}
6
path: [performerInfo, requestActionHistory]
7
id: ServiceRequest.performerInfo.requestActionHistory
8
isCollection: true
9
extensionUrl: urn:extension:performerInfo.requestActionHistory
Copied!
performerInfo.requestActionHistory.action
1
PUT /Attribute/ServiceRequest.performerInfo.requestActionHistory.action
2
​
3
resourceType: Attribute
4
description: 'Information filled in by performer: request action history - action'
5
resource: {id: ServiceRequest, resourceType: Entity}
6
path: [performerInfo, requestActionHistory, action]
7
id: ServiceRequest.performerInfo.requestActionHistory.action
8
type: {id: string, resourceType: Entity}
9
extensionUrl: urn:extension:performerInfo.requestActionHistory.action
Copied!
performerInfo.requestActionHistory.date
1
PUT /Attribute/ServiceRequest.performerInfo.requestActionHistory.date
2
​
3
resourceType: Attribute
4
description: 'Information filled in by performer: request action history - date'
5
resource: {id: ServiceRequest, resourceType: Entity}
6
path: [performerInfo, requestActionHistory, date]
7
id: ServiceRequest.performerInfo.requestActionHistory.date
8
type: {id: dateTime, resourceType: Entity}
9
extensionUrl: urn:extension:performerInfo.requestActionHistory.date
Copied!
performerInfo.requestActionHistory.subject
1
PUT /Attribute/ServiceRequest.performerInfo.requestActionHistory.subject
2
​
3
resourceType: Attribute
4
description: 'Information filled in by performer: request action history - subject'
5
resource: {id: ServiceRequest, resourceType: Entity}
6
path: [performerInfo, requestActionHistory, subject]
7
id: ServiceRequest.performerInfo.requestActionHistory.subject
8
type: {id: Reference, resourceType: Entity}
9
extensionUrl: urn:extension:performerInfo.requestActionHistory.subject
Copied!
performerInfo.requestActionHistory.note
1
PUT /Attribute/ServiceRequest.performerInfo.requestActionHistory.note
2
​
3
resourceType: Attribute
4
description: 'Information filled in by performer: request action history - note'
5
resource: {id: ServiceRequest, resourceType: Entity}
6
path: [performerInfo, requestActionHistory, note]
7
id: ServiceRequest.performerInfo.requestActionHistory.note
8
type: {id: string, resourceType: Entity}
9
extensionUrl: urn:extension:performerInfo.requestActionHistory.note
Copied!
performerInfo.requestActionHistory.author
1
PUT /Attribute/ServiceRequest.performerInfo.requestActionHistory.author
2
​
3
resourceType: Attribute
4
description: 'Information filled in by performer: request action history - author'
5
resource: {id: ServiceRequest, resourceType: Entity}
6
path: [performerInfo, requestActionHistory, author]
7
id: ServiceRequest.performerInfo.requestActionHistory.author
8
type: {id: Reference, resourceType: Entity}
9
extensionUrl: urn:extension:performerInfo.requestActionHistory.author
Copied!
Let's add a resource using created extensions:
Create resource in the Aidbox format:
1
PUT /ServiceRequest/servicerequest-with-aidbox-native-extensions
2
​
3
resourceType: ServiceRequest
4
performerInfo:
5
performedBy:
6
- resourceType: Organization
7
display: City Hospital
8
- resourceType: PractitionerRole
9
display: Mark Sloan
10
requestStatus: completed
11
requestActionHistory:
12
- date: '2020-01-14T12:15:22'
13
action: new
14
author: {display: Meredith Grey (Psychiatrist-narcologist), resourceType: PractitionerRole}
15
- date: '2020-01-14T12:15:36'
16
action: in-progress
17
author: {display: Derek Shepherd (General practitioner), resourceType: PractitionerRole}
18
- date: '2020-01-14T12:19:00'
19
action: in-progress
20
author: {display: Derek Shepherd (General practitioner), resourceType: PractitionerRole}
21
subject: {display: Mark Sloan (Dental surgeon), resourceType: PractitionerRole}
22
note: Referred to Dr. Mark Sloan (Dental surgeon)
23
- date: '2020-01-14T15:05:20'
24
action: meeting
25
author: {display: Mark Sloan (Dental surgeon), resourceType: PractitionerRole}
26
- date: '2020-01-14T15:22:46'
27
action: completed
28
author: {display: Mark Sloan (Dental surgeon), resourceType: PractitionerRole}
29
status: completed
30
intent: original-order
31
category:
32
- text: Telemedicine consultation referral
33
coding:
34
- {code: "TMC", system: 'urn:CodeSystem:servicerequest-category', display: "Telemedicine consultation"}
35
subject:
36
resourceType: Patient
37
display: Jack Black, 10.12.1941
38
identifier: {value: '2155800871000065', system: 'urn:oid:1.2.3.4.5.6.7.9'}
Copied!
Request
Response
Get resource in the FHIR format:
1
GET /fhir/ServiceRequest/servicerequest-with-aidbox-native-extensions
Copied!
1
resourceType: ServiceRequest
2
extension:
3
- url: urn:extension:performerInfo
4
extension:
5
- url: urn:extension:performerInfo.performedBy
6
valueReference: {display: City Hospital}
7
- url: urn:extension:performerInfo.performedBy
8
valueReference: {display: Mark Sloan}
9
- {url: 'urn:extension:performerInfo.requestStatus', valueCode: completed}
10
- url: urn:extension:performerInfo.requestActionHistory
11
extension:
12
- {url: 'urn:extension:performerInfo.requestActionHistory.date', valueDateTime: '2020-01-14T12:15:22'}
13
- {url: 'urn:extension:performerInfo.requestActionHistory.action', valueString: new}
14
- url: urn:extension:performerInfo.requestActionHistory.author
15
valueReference: {display: Meredith Grey (Psychiatrist-narcologist)}
16
- url: urn:extension:performerInfo.requestActionHistory
17
extension:
18
- {url: 'urn:extension:performerInfo.requestActionHistory.date', valueDateTime: '2020-01-14T12:15:36'}
19
- {url: 'urn:extension:performerInfo.requestActionHistory.action', valueString: in-progress}
20
- url: urn:extension:performerInfo.requestActionHistory.author
21
valueReference: {display: Derek Shepherd (General practitioner)}
22
- url: urn:extension:performerInfo.requestActionHistory
23
extension:
24
- {url: 'urn:extension:performerInfo.requestActionHistory.date', valueDateTime: '2020-01-14T12:19:00'}
25
- {url: 'urn:extension:performerInfo.requestActionHistory.note', valueString: Referred to Dr. Mark Sloan (Dental surgeon)}
26
- {url: 'urn:extension:performerInfo.requestActionHistory.action', valueString: in-progress}
27
- url: urn:extension:performerInfo.requestActionHistory.author
28
valueReference: {display: Derek Shepherd (General practitioner)}
29
- url: urn:extension:performerInfo.requestActionHistory.subject
30
valueReference: {display: Mark Sloan (Dental surgeon)}
31
- url: urn:extension:performerInfo.requestActionHistory
32
extension:
33
- {url: 'urn:extension:performerInfo.requestActionHistory.date', valueDateTime: '2020-01-14T15:05:20'}
34
- {url: 'urn:extension:performerInfo.requestActionHistory.action', valueString: meeting}
35
- url: urn:extension:performerInfo.requestActionHistory.author
36
valueReference: {display: Mark Sloan (Dental surgeon)}
37
- url: urn:extension:performerInfo.requestActionHistory.subject
38
valueReference: {display: '2020-01-08'}
39
- url: urn:extension:performerInfo.requestActionHistory
40
extension:
41
- {url: 'urn:extension:performerInfo.requestActionHistory.date', valueDateTime: '2020-01-14T15:22:46'}
42
- {url: 'urn:extension:performerInfo.requestActionHistory.action', valueString: completed}
43
- url: urn:extension:performerInfo.requestActionHistory.author
44
valueReference: {display: Mark Sloan (Dental surgeon)}
45
status: completed
46
id: servicerequest-with-aidbox-native-extensions
47
intent: original-order
48
category:
49
- text: Telemedicine consultation referral
50
coding:
51
- {code: TMC, system: 'urn:CodeSystem:servicerequest-category', display: Telemedicine consultation}
52
subject:
53
identifier: {value: '2155800871000065', system: 'urn:oid:1.2.3.4.5.6.7.9'}
54
display: Jack Black, 10.12.1941
Copied!

Using FHIR extensions

FHIR extensions defined in the specification can be found in the registry http://hl7.org/fhir/extensibility-registry.html.
Let's create an attribute for the servicerequest-precondition extension:
1
PUT /Attribute/ServiceRequest.precondition
2
​
3
resourceType: Attribute
4
description: "The condition or state of the patient, prior or during
5
the diagnostic procedure or test, for example, fasting, at-rest,
6
or post-operative. This captures circumstances that may influence
7
the measured value and have bearing on the interpretation of the result."
8
resource: {id: ServiceRequest, resourceType: Entity}
9
path: [precondition]
10
id: ServiceRequest.precondition
11
type: {id: CodeableConcept, resourceType: Entity}
12
isCollection: true
13
extensionUrl: "http://hl7.org/fhir/StructureDefinition/servicerequest-precondition"
Copied!
Let's create a resource in the FHIR format:
Create resource in the FHIR format:
1
PUT /fhir/ServiceRequest/servicerequest-with-aidbox-native-extensions
2
​
3
resourceType: ServiceRequest
4
status: active
5
intent: original-order
6
subject:
7
type: Patient
8
display: Jack Black, 10.12.1941
9
extension:
10
- url: http://hl7.org/fhir/StructureDefinition/servicerequest-precondition
11
valueCodeableConcept:
12
text: After calorie fasting
13
coding:
14
- code: "726055006"
15
system: http://snomed.info/sct
16
display: After calorie fasting
17
- url: http://hl7.org/fhir/StructureDefinition/servicerequest-precondition
18
valueCodeableConcept:
19
text: At rest
20
coding:
21
- code: "263678003"
22
system: http://snomed.info/sct
23
display: At rest
Copied!
Let's get the resource in the Aidbox format:
Request
Response
Get resource in the Aidbox format:
1
GET /ServiceRequest/servicerequest-with-aidbox-native-extensions
Copied!
1
resourceType: ServiceRequest
2
id: servicerequest-with-aidbox-native-extensions
3
intent: original-order
4
status: active
5
subject: {type: Patient, display: 'Jack Black, 10.12.1941'}
6
precondition:
7
- text: After calorie fasting
8
coding:
9
- {code: '726055006',
10
system: 'http://snomed.info/sct',
11
display: After calorie fasting}
12
- text: At rest
13
coding:
14
- {code: '263678003',
15
system: 'http://snomed.info/sct',
16
display: At rest}
Copied!

Request headers

If you are using some HTTP-client like Postman, you will need to specify some headers.
Header
Value
Authorization
Bearer <your value>
Content-Type
text/yaml