The CDA Exchange Module endpoint can be used to create, update, delete, and view CDA document templates.
Additionally, once a template has been stored, it can be used to generate CDA documents, Fhir Documents, and Fhir Compositions.
This section of the docs contains all the details for the REST endpoints available to use with this module. You can find a high level overview of the Smile CDR CDA Exchange Module here.
Upon successful creation, this method will return a 200 "ok" status with the contents of your new template in the response body.
To invoke:
POST http://localhost:9000/cda/{module_id}/template/{template_id}
Content-Type: application/json
{
"script": "string",
"params": [
"string"
],
"description": "string"
}
Required:
module_id
: The name of your CDA Exchange moduletemplate_id
: Desired name of your new cda templateOptional:
You may also add the following body parameter:
script
: The contents of your ES5 JavaScript script. Note, that this script must include a function with signature:
Composition generateCdaExchangeComposition(inputMap)
where the return is a Composition that was created using ResourceBuilder.build('Composition')
.
inputMap
is a JavaScript Object of input parameters that is your source of externally declared variable values.params
: The list of parameters your script accepts / expects. This field has no effect on the actual script but rather serves as a hint for potential users of the template.description
: A human readable description of the purpose and/or functionality of the included script. If any of your params are not self explanatory, this is a great place to explain their expectation / usage.Response:
Upon successful replacement/creation, this method will return a 200 "ok" status with the contents of your new template as the response body.
Can be used just like the POST method, but if the template_id
already exists, this route will update the fields of your template with whichever arguments are included in your json post body.
To invoke:
PUT http://localhost:9000/cda/{module_id}/template/{template_id}
Content-Type: application/json
{
"description": "a new description. params and script remain unchanged."
}
Required:
module_id
: The name of your CDA Exchange moduletemplate_id
: Desired name of your new cda templateOptional:
You may also add the following body parameters:
script
: The contents of your ES5 JavaScript script. Note, that this script must include a function with signature:
Composition generateCdaExchangeComposition(inputMap)
where the return is a Composition that was created using ResourceBuilder.build('Composition')
.
inputMap
is a JavaScript Object of input parameters that is your source of externally declared variable values.params
: The list of parameters your script accepts / expects. This field has no effect on the actual script but rather serves as a hint for potential users of the template.description
: A human readable description of the purpose and/or functionality of the included script. If any of your params are not self explanatory, this is a great place to explain their expectation / usage.Response:
If successful, the server will respond with a 201 with the contents of your new template as the response body (including unmodified fields).
The create method and JSON update method will only accept your script if you have escaped your new lines, tabs, and double quotes. You are likely creating your scripts with a text editor or JavaScript IDE and you may prefer to not have to convert your script to an escaped version.
This route takes your raw script and updates the "script" field of your CDA template. If the template_id
does not yet exist,
it creates a new template with your script with empty description
and params
fields which you can fill in with the JSON update method
To invoke:
PUT http://localhost:9000/cda/{module_id}/template/{template_id}/script
Content-Type: application/javascript
Body:
function generateCdaExchangeComposition(inputMap) {
var composition = ResourceBuilder.build('Composition');
composition.setType("ContinuityOfCareDocument");
composition.setSubject(inputMap['PATIENT']);
return composition;
}
To invoke:
GET http://localhost:9000/cda/{module_id}/template/{template_id}
Required:
module_id
: The name of your CDA Exchange moduleOptional:
template_id
: The name of the template to view. If omitted, then all templates are returned.The server will produce a response resembling the following:
if template_id is included:
{
"script" : "function generateCdaExchangeComposition(inputMap) {\n var composition = ResourceBuilder.build('Composition');\n return composition;\n}",
"params" : [],
"description" : "A very basic cda template script example"
}
if template_id is omitted:
{
"templates": [
{
"script" : "function generateCdaExchangeComposition(inputMap) {\n var composition = ResourceBuilder.build('Composition');\n return composition;\n}",
"params" : [],
"description" : "A very basic cda template script example",
"id": "example_template"
},
{
"script": "...",
"params": [],
"description": "...",
"id": "..."
}
],
"count": 2
}
To invoke:
DELETE http://localhost:9000/cda/{module_id}/template/{template_id}
Required:
module_id
: The name of your CDA Exchange moduletemplate_id
: The name of the template to deleteResponse:
If successful, the server will respond with a 200 and return the contents of your deleted template as the response body. The response body will be empty if there was no template with that id.
For a step by step tutorial on how to create a CDA template, please refer to the JavaScript Templates documentation.
For detailed documentation on what can be included in a CDA template, please refer to the JavaScript Execution Environment documentation.
Here is an example of a CDA template. To add it to your CDA module, you would have to use one of the POST or PUT routes at the top of this document.
Your post body would look like the following if you use the JSON POST method.
{
"description": "Subject is the only mandatory parameter and should be populated with a reference to a Patient such as 'Patient/123'. You can leave the other parameters blank and still generate a CDA document",
"script": "{the script as shown below, but with special characters escaped}"
}
You could alternatively PUT the script in a separate request
function generateCdaExchangeComposition(inputMap) {
// create the composition for our document
var composition = ResourceBuilder.build('Composition');
// setting the composition type auto-populates the known boilerplate for that C-CDA document type
composition.setType('ContinuityOfCareDocument');
var subject = inputMap['SUBJECT'];
composition.setSubject(subject);
// since we informally specified non-subject fields as optional
// in the description, we prevent errors by checking for their inclusion
if (inputMap['AUTHOR']) {
composition.setAuthor(inputMap['AUTHOR']);
}
if (inputMap['CUSTODIAN']) {
composition.setCustodian(inputMap['CUSTODIAN']);
}
if (inputMap['ENCOUNTER']) {
composition.setEncounter(inputMap['ENCOUNTER']);
}
// get current timeStamp for use in auto-generated IDs and timestamps
var currentDate = Date.now();
composition.setDate(currentDate);
// boilerplate fields for this document-generation template
composition.language = 'en-US';
composition.identifier.system = '1.23.456.7.890123.4.5678';
var splitSubject = subject.split('/');
if (splitSubject.length > 1) {
composition.identifier.value = subject.split('/')[1] + currentDate;
} else {
composition.identifier.value = subject + currentDate;
}
composition.title = 'My Organization - Continuity of Care Document';
var problemSection = composition.addSection('problem');
var problemList = Fhir
.search()
.forResource('Condition')
.where('subject', subject)
.asList();
problemSection.populate(problemList);
var medicationSection = composition.addSection('medication');
var medicationList = Fhir
.search()
.forResource('MedicationRequest')
.where('subject', subject)
.asList();
var medicationList2 = Fhir
.search()
.forResource('MedicationAdministration')
.where('subject', subject)
.asList();
medicationSection
.populate(medicationList)
.populate(medicationList2);
var resultSection = composition.addSection('result');
var resultList = Fhir
.search()
.forResource('DiagnosticReport')
.where('subject', subject)
.asList();
resultSection.populate(resultList);
// using JavaScript's native Date object
var thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
// this will be of the form 'ge2018-07-31'
var thirtyDaysAgoIsoString = 'ge' + thirtyDaysAgo.toISOString().slice(0,10);
// the date here ensures we only get vital signs from the past 30 days
// you could also create a parameter instead of
// hard coding 30 to make your script more versatile
var vitalSection = composition.addSection("vitalsign");
var vitalList = Fhir
.search()
.forResource('Observation')
.where('subject', subject)
.where('category', 'vital-signs')
.where('date', thirtyDaysAgoIsoString)
.asList();
vitalSection.populate(vitalList);
var allergySection = composition.addSection('allergyIntolerance');
var allergyList = Fhir
.search()
.forResource('AllergyIntolerance')
.where('patient', subject)
.asList();
allergySection.populate(allergyList);
var socialHistorySection = composition.addSection('socialHistory');
var historyList = Fhir
.search()
.forResource('Observation')
.where('subject', subject)
.where('category', 'social-history')
.asList();
socialHistorySection.populate(historyList);
return composition;
}