On this page:

20.4FHIR REST API

 

The Smile CDR JavaScript execution environment has two objects that can be used to interact with the REST API of a FHIR server.

The Fhir object can be used to connect to a local FHIR Storage module that is declared as a module dependency. This connection is internal and does not require authorization. For example, the following example shows an internal FHIR create operation.

Fhir.create(patient);

The FhirClientFactory object can be used to create a client with the ability to perform HTTP REST connections to external FHIR servers. An equivalent call to an external FHIR server might look like the following:

var client = FhirClientFactory.newClient('http://example.com/fhirBaseUrl');
client.create(patient);

Both of these APIs provide access to operations against a FHIR Persistence module (e.g. search, transaction, etc.). Note that most examples below show the API being used to access a local FHIR server using the Fhir API. Unless specified otherwise, it is possible to invoke all of the same functions on a client obtained from the FhirClientFactory.

20.4.1Method: create(resource)

 

Create a new resource.

Inputs:

  • resource – the resource to create. Note that when the method returns the resource will be updated to have the ID was was assigned during the create process.

Outputs:

  • This method does not return an output.

Example:

var patient = ResourceBuilder.build('Patient');
patient.name.family = 'Smith';
patient.name.given = 'John';
Fhir.create(patient);

20.4.2Method: read(url)

 

Read a resource at a particular url.

Inputs:

  • url – the location of the desired Resource.

Outputs:

  • Returns a Fhir Resource or null if the url is invalid or the resource is not found.

Example:

var myPatient = Fhir.read('Patient/123');

20.4.3Method: search().forResource(resourceType)

 

Fhir.search().forResource(resourceType) creates a Fhir search object which can be built up and eventually executed.

Inputs:

  • resourceType – the resource type to eventually perform the search on

Outputs:

  • Returns an IFhirTypedSearch object with the following methods:

where(paramName, paramValue)

Each .where call adds an And condition to your search. To use an Or list, separate values with a comma like you would in a Fhir search (example below).

Inputs:

  • paramName – the code of your desired Hapi Fhir SearchParameter
  • paramValue – the value to search for. Typically identical to how you would search Hapi Fhir in your browser, with a couple noted exceptions below.

Outputs:

  • Returns the same IFhirTypedSearch object this was applied to.
var conditionList = Fhir
    .search()
    .forResource('Observation')
    .where('subject', 'Patient/123')
    .asList();

where(resourceType, paramName, paramValue)

Only to be used on searches of type reference. Same as the 2-parameter version, but with optional resourceType declaration for more specific / efficient reference type searches.

var conditionList = Fhir
    .search()
    .forResource('Observation')
    .where('Encounter', 'context', 'Encounter/234')
    .asList();

where(tokenParam, 'system|code')

For comma separated Token searches, there is no need to repeat the same system multiple times. Instead, each comma-separated code will take on the most recently declared System.

As a result, if you want to include any codes with a wildcard system, you must list those first.

Example:

The following would return all Conditions for all of the 3 listed Patients where the Condition code is ABCDE in any code system, 123, 456, or 789 in Snomed, or 12345 in Loinc.

var conditionList = Fhir
    .search()
    .forResource('Condition')
    .where('subject', 'Patient/1386,Patient/1387,Patient/1388')
    .where('code', 'ABCDE,http://snomed.info/sct|123,456,789,http://loinc.org|12345')
    .asList();

Creating Token Parameter Values

You may also use the utility method whereToken(paramName, system, value) to generate a token.

Example:

var conditionList = Fhir
    .search()
    .forResource('Condition')
    .whereToken('code', 'http://snomed.info/sct', '425363002')
    .asList();

sort(sortParam)

Results from the search will be sorted according to the sort parameters specified. Your sort chain can be specified in a single comma separated sort call or in multiple calls to sort. Prepend your param with a dash - to sort in descending order.

Example usage: Sort such that the most recent entry is first and break ties by id ascending.

var conditionList = Fhir
    .search()
    .forResource('Observation')
    .sort('-date,_id')
    .asList();

count(resourceLimit)

Limit the maximum possible number of results. If this parameter is not specified, your search will return all matching results up to a maximum of 1000.

Example usage: Retrieve only the most recent Observation for a patient.

var conditionList = Fhir
    .search()
    .forResource('Observation')
    .where('subject', 'Patient/1386')
    .sort('-date')
    .count(1)
    .asList();

if (conditionList.length > 0) {
   Log.info(conditionList[0].toJson());
}

Chaining

The JavaScript environment supports chaining for reference parameters. To create a chained query, place a dot . between each chain.

When chaining, you can optionally add a resource type parameter for the expected resource type in the first chain. In the example below, by specifying Encounter, we ensure that Condition.context only matches resources of type Encounter before continuing the chain.

Example:

var conditionList = Fhir
    .search()
    .forResource('Condition')
    .where('subject.given', 'Ron')
    .where('Patient', 'subject.family', 'Howard')
    .where('Encounter', 'context.service-provider.type', 'prov')
    .asList();

Dates

To search by dates, use the same syntax as you would when making a Hapi Fhir query.

var problemList = Fhir
    .search()
    .forResource('Condition')
    .where('asserted-date', 'gt2018-06-01')
    .asList();

If you want to do a search relative to the current date, you have two options.

  1. Determine your desired search query outside of the JSEE and pass it in as a parameter to whichever module you are using.
  2. Use JavaScript's native Date object.
var oneYearAgo = new Date();
oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);

var problemList = Fhir
    .search()
    .forResource('Condition')
    .where('asserted-date', 'ge' + oneYearAgo.toISOString().slice(0,10))
    .asList();

asList()

Outputs:

  • Performs the search and returns an array of resources.

Note: no search is performed until the .asList() method is called. Everything before that just builds the query.

Usage

var conditionList = Fhir
    .search()
    .forResource('Condition')
    .where('subject', 'Patient/1386')
    .where('context', 'Encounter/1390')
    .asList();
    
for (var i = 0; i < conditionList.length; i++) {
  Log.info(conditionList[i].toJson());
}

20.4.4Method: transaction(IBundleBuilder theTransaction)

 

This method is used to persist the resources in a bundle built with the TransactionBuilder API.

var transaction = TransactionBuilder.newTransactionBuilder();

/* populate transaction as per the TransactionBuilder API */

// persist the resources in the transaction bundle
Fhir.transaction(transaction);

20.4.5Method: translate()

 

This method facilitates terminology mapping by translating a code from one CodeSystem to another. It makes use of an underlying implementation of the $translate operation for ConceptMap. Presently, only the three invocations detailed below are supported; however, more will be made available in future releases of Smile CDR.

Note that for these translations to occur, mappings must first be stored on the server in ConceptMap resources. These mappings can be imported using either a FHIR endpoint or available command-line tools.

Method Chain: translate()...andReturnCodeAsString()

Inputs:

  • srcSystem – The source CodeSystem.
  • srcCode – The code to be translated.
  • tgtSystem – The target CodeSystem.

Outputs:

  • Returns the mapped code in the target CodeSystem as a string.

Example:

var tgtCode = Fhir
   .translate()
   .fromSystemAndCode(srcSystem, srcCode)
   .toCodeSystem(tgtSystem)
   .andReturnCodeAsString();

Method Chain: translate()...andReturnCoding()

Inputs:

  • srcSystem – The source CodeSystem.
  • srcCode – The code to be translated.
  • tgtSystem – The target CodeSystem.

Outputs:

  • Returns the mapped code in the target CodeSystem as a Coding.

Example:

var tgtCoding = Fhir
   .translate()
   .fromSystemAndCode(srcSystem, srcCode)
   .toCodeSystem(tgtSystem)
   .andReturnCoding();

The various fields within a Coding can be accessed as follows:

var tgtSystem = tgtCoding.system;
var tgtCode = tgtCoding.code;
var tgtDisplay = tgtCoding.display;

20.4.6Method: update(resource)

 

Update an existing resource (can also be used to create a resource with a client assigned ID.

Inputs:

  • resource – the resource to update. Note that when the method returns the resource will be updated to have the ID was was assigned during the update process.

Outputs:

This method does not return an output.

Example:

var patient = ResourceBuilder.build('Patient');
patient.id = 'Patient/A123';
patient.name.family = 'Smith';
patient.name.given = 'John';
Fhir.update(patient);

20.4.7Authentication

 

When using the FhirClientFactory to access a remote HTTP server, the following methods may be used to add authentication headers to requests. Note that the Environment API may be useful in order to securely store credentials without needing to hard-code them in your JavaScript code.

HTTP Basic Auth

Use the withHttpBasicAuth(theUsername, thePassword) method to add HTTP Basic Auth credentials to your request. For example:

var client = FhirClientFactory.newClient('http://example.com/baseFhirUrl');
client = client.withHttpBasicAuth('username', 'password');
var patient = client.read('Patient/1');

Use the withBearerTokenAuth(theBearerToken) method to add a Bearer token to your request. For example:

var client = FhirClientFactory.newClient('http://example.com/baseFhirUrl');
client = client.withBearerTokenAuth('w88eoiewifsdg');
var patient = client.read('Patient/1');