Mapper module provides a way to convert data with arbitrary schema to FHIR resource(s) and store results in Aidbox.

Most of real-world healthcare applications are integrated with 3rd-party systems to ingest data from them. Using Mapping resource you can describe how 3rd-party data is being converted to the FHIR format. Mappings are written using JUTE language.

Mapping is an Aidbox resource, so all CRUD operations are applicable to it. Mapping's schema is pretty straightforward:

resourceType: Mapping
id: mapping-id-here
# Executable part of the mapping written in JUTE language (required)
# JSON schema for the incoming data (optional)

If scopeSchema attribute is provided, incoming mapping data (also called a scope) will be validated against it first. Then a JUTE template from body will be executed. Mapping should return a valid Transaction Bundle, so when it will be applied, it will be able to operate with multiple resources, not just single one.


Let's do a simple mapping which will create a Patient resource from following data structure:

firstName: John
lastName: Smith
birthDate: 2000-01-02

Following request will create a mapping resource:

If you're not familiar with JUTE, please check out JUTE Tutorial to understand basic concepts.

PUT /Mapping/example
Content-Type: text/yaml
resourceType: Mapping
id: example
# JSON schema describing incoming data structure
type: object
required: ["firstName", "lastName", "birthDate"]
type: string
type: string
type: string
pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
# JUTE template which transforms incoming data to Transaction Bundle
resourceType: Bundle
type: transaction
- request:
url: /fhir/Patient
method: POST
resourceType: Patient
birthDate: $ birthDate
- given: ["$ firstName"]
family: $ lastName

When template was created, you can invoke $apply operation on it to generate Patient resource and save it into the database:

POST /Mapping/example/$apply
Content-Type: text/yaml
firstName: John
lastName: Smith
birthDate: 2010-12-12

$apply Endpoint

To execute Mapping and to store it's result in Aidbox database do a POST request to the $apply endpoint. Request's body will be passed to a JUTE as an incoming data (scope):

POST /Mapping/<mapping-id>/$apply
Content-Type: application/json
{ "foo": 42, "bar": "hello" }

Make sure that your Mapping returns a Transaction Bundle, otherwise it's result won't be persisted in the database.

$debug Endpoint

To check Mapping's result without actually persisting it, you can do a POST request to the $debug endpoint:

POST /Mapping/<mapping-id>/$debug
Content-Type: text/yaml
foo: 42
bar: hello

Response will contain a mapping result or an error if evaluation failed for some reason.

Global $debug Endpoint

There is a way to check mapping result without persisting it as a resource:

POST /Mapping/$debug
Content-Type: text/yaml
mul: $ 2 * foo
str: $ "hello, " + name
type: object
required: ["foo", "name"]
type: integer
type: string
foo: 4
name: "Bob"

You pass both Mapping and incoming data (scope) in a request body. Request response will contain mapping result or an error information.

Including Mapping inside other Mapping

In Aidbox there is an $include directive which allows you to include a Mapping within another one:

PUT /Mapping/index
Content-Type: text/yaml
resourceType: Mapping
id: index
$switch: $ type
$include: "patient"
$include: "practitioner"
$default: null

This template will pass execution to either /Mapping/patient or /Mapping/practitioner depending on value of type key. Current evaluation scope will be passed to the included Mapping.

Because potentially there is a way to create infinite recursion using a $include directive, there is a inclusion depth limit which equals 5 for now.

Mapping Editor in the Aidbox UI

Mapping Editor UI

There is a Mapping Editor in the Aidbox UI with built-in syntax checker and Debug capabilities. Search for a "Mappings" item in the left menu.