.. _restful: RESTful APIs ================ .. note:: Swagger API overview is available on base openFHIR context. If one is set up locally on port 8080 without and context, this would be http://localhost:8080. For sandbox example see https://sandbox.open-fhir.com Overview -------- openFHIR Engine is a standalone component that exposes FHIR Operations-framework endpoints for mapping (``/$tofhir`` and ``/$toopenehr``, as defined by the FHIRconnect REST API specification, plus the legacy ``/openfhir/tofhir`` and ``/openfhir/toopenehr``) and 3 restful APIs for state configuration (``/opt``, ``/fc/context`` and ``/fc/model``). Additional APIs are exposed for :ref:`terminology` and :ref:`multitenancy`. FHIRconnect operations ---------------------- Once operational templates, context mappers and model mappers are correctly set up (i.e. state of the engine has been configured), you can run your mappings by invoking the FHIR operations. Requests and responses use the R4 FHIR envelope (``application/fhir+json``); errors are returned as an ``OperationOutcome``. .. http:post:: /$tofhir Map an openEHR Composition to FHIR. Body is a FHIR (R4) ``Parameters`` resource with a ``composition`` parameter (stringified openEHR Composition, flat or canonical), an optional ``templateId`` parameter (required when the composition is flat) and an optional nested ``context`` parameter (parts: ``ehr_id``, ``patient``, ``who``, ``onBehalfOf``). Short context fields may also be passed as query parameters; the body takes precedence on conflict. **Example request**: .. sourcecode:: http POST /$tofhir?templateId=Growth%20chart HTTP/1.1 Content-Type: application/fhir+json Body: { "resourceType": "Parameters", "parameter": [ { "name": "composition", "valueString": "" } ] } :query templateId: Required when the composition is flat (may alternatively be passed as a ``templateId`` parameter in the body). The response is a FHIR Bundle with the mapped resources, an engine-generated ``Provenance`` entry and, when some elements could not be mapped, an ``OperationOutcome`` entry with warnings. .. http:post:: /$toopenehr Map a FHIR Bundle to an openEHR Composition. Body is the FHIR Bundle itself (no ``Parameters`` wrapper; a single resource is also accepted). **Example request**: .. sourcecode:: http POST /$toopenehr?templateId=Growth%20chart&format=flat HTTP/1.1 Content-Type: application/fhir+json Body: :query templateId: Template id used to select the mapping context; when omitted, the engine tries to deduce it from the available contexts. :query format: ``canonical`` (default) or ``flat``. The response is a FHIR (R4) ``Parameters`` resource with a ``composition`` parameter (``valueString``) and, when gaps were reported during mapping, an ``outcome`` parameter holding an ``OperationOutcome`` — a partial result may coexist with issues. Mappings (legacy) ----------------- The following endpoints predate the FHIRconnect operations above and remain available: .. http:post:: /openfhir/tofhir Map an openEHR Composition to a FHIR Resource. Body can either be a FLAT representation of the openEHR Composition or a Canonical JSON. FLAT examples: https://github.com/ehrbase/openEHR_SDK/tree/develop/test-data/src/main/resources/composition/flat/simSDT/conformance Canonical JSON examples: https://github.com/ehrbase/openEHR_SDK/tree/develop/test-data/src/main/resources/composition/canonical_json **Example request**: .. sourcecode:: http POST /openfhir/tofhir HTTP/1.1 Content-Type: application/json Body: .. sourcecode:: http POST /openfhir/tofhir?templateId=dataset_poc_rso-zl_acp HTTP/1.1 Content-Type: application/json Body: :query templateId: If an engine can not deduce a template it (i.e. if body is NOT a canonical json), then you need to provide a template id in a query parameter. When body of the request is a canonical json, this information is present within the canonical json and a templateId query param is not required. Response is a FHIR Resource. .. http:post:: /openfhir/toopenehr Map a FHIR Resource to an openEHR Composition. Body needs to be a valid FHIR Resource in a JSON format. Response is an openEHR Composition in either a FLAT format or a Canonical JSON. **Example request**: .. sourcecode:: http POST /openfhir/toopenehr HTTP/1.1 Content-Type: application/json Body: :query flat: If you'd like to receive response in a FLAT format instead of a canonical JSON. default is false. :query templateId: For the purpose of using the correct context for mapping, the engine needs to know a template id. Template id can either come as an input query parameter or it can be deduced based on all available context mappings. If no templateId is provided in the request, the engine will check all available contexts (that were persisted as part of the state configuration) and try to find one that is able to map the incoming FHIR Resource. If more than 1 is available, it will log a message and take the first one it finds. State configuration ------------------- .. note:: An alternative state configuration option is via a Bootstrapping mechanism. See more at: :ref:`state-configuration` Context mappers ^^^^^^^^^^^^^^^ Context mappers are yaml files representing context on which a mapping takes place. See more at :doc:`fhirconnect`. Structure needs to comply to a schema available at https://github.com/better-care/fhir-connect-mapping-spec. Body when creating/updating a context mapper is plain text, directly yaml itself. .. http:post:: /fc/context Create a new context mapper. **Example request**: .. sourcecode:: http POST /fc/context HTTP/1.1 Content-Type: application/x-yaml Body: grammar: FHIRConnect/v0.0.1 type: context metadata: name: "Growth chart" version: 1.0.0 spec: system: FHIR version: R4 context: profile: url: "Observation" template: id: "Growth chart" archetypes: - "openEHR-EHR-OBSERVATION.body_weight.v2" - "openEHR-EHR-OBSERVATION.height.v2" start: "openEHR-EHR-OBSERVATION.body_weight.v2" .. http:put:: /fc/context/(uuid:context_mapper_unique_id) Update an existing context mapper. **Example request**: .. sourcecode:: http PUT /fc/context/6b7fe776-e4de-49ce-849e-406b280e5338 HTTP/1.1 Content-Type: text/plain Body: grammar: FHIRConnect/v0.0.1 type: context metadata: name: "Growth chart" version: 1.0.0 spec: system: FHIR version: R4 context: profile: url: "Observation" template: id: "Growth chart" archetypes: - "openEHR-EHR-OBSERVATION.body_weight.v2" - "openEHR-EHR-OBSERVATION.height.v2" start: "openEHR-EHR-OBSERVATION.body_weight.v2" Model mappers ^^^^^^^^^^^^^ Model mappers are yaml files representing model mappings. See more at :doc:`fhirconnect`. Structure needs to comply to a schema available at https://github.com/better-care/fhir-connect-mapping-spec. Body when creating/updating a model mapper is plain text, directly yaml itself. .. http:post:: /fc/model Create a new model mapper. **Example request**: .. sourcecode:: http POST /fc/model HTTP/1.1 Content-Type: text/plain Body: grammar: FHIRConnect/v0.0.1 type: model metadata: name: "openEHR-EHR-OBSERVATION.body_weight.v2" version: 1.0.0 spec: system: FHIR version: R4 openEhrConfig: archetype: "openEHR-EHR-OBSERVATION.body_weight.v2" fhirConfig: structureDefinition: http://hl7.org/fhir/StructureDefinition/Observation condition: - targetRoot: "$resource" targetAttribute: "code.coding.code" operator: "one of" criteria: "29463-7" mappings: - name: "weight" with: fhir: "$resource.value" openehr: "$archetype/data[at0002]/events[at0003]/data[at0001]/items[at0004]" type: "QUANTITY" fhirCondition: targetRoot: "$resource" targetAttribute: "code.coding.code" operator: "one of" criteria: "[$loinc.29463-7, $snomed.27113001]" - name: "time" with: fhir: "$resource.effective" openehr: "$archetype/data[at0002]/events[at0003]/time" type: "DATETIME" - name: "comment" with: fhir: "$resource.note.text" openehr: "$archetype/data[at0002]/events[at0003]/data[at0001]/items[at0024]" type: "STRING" .. http:put:: /fc/model/(uuid:model_mapper_unique_id) Update an existing model mapper. **Example request**: .. sourcecode:: http PUT /fc/model/9ae2278a-c02b-4165-96fc-79dd91495db3 HTTP/1.1 Content-Type: text/plain Body: grammar: FHIRConnect/v0.0.1 type: model metadata: name: "openEHR-EHR-OBSERVATION.body_weight.v2" version: 1.0.0 spec: system: FHIR version: R4 openEhrConfig: archetype: "openEHR-EHR-OBSERVATION.body_weight.v2" fhirConfig: structureDefinition: http://hl7.org/fhir/StructureDefinition/Observation condition: - targetRoot: "$resource" targetAttribute: "code.coding.code" operator: "one of" criteria: "29463-7" mappings: - name: "weight" with: fhir: "$resource.value" openehr: "$archetype/data[at0002]/events[at0003]/data[at0001]/items[at0004]" type: "QUANTITY" fhirCondition: targetRoot: "$resource" targetAttribute: "code.coding.code" operator: "one of" criteria: "[$loinc.29463-7, $snomed.27113001]" - name: "time" with: fhir: "$resource.effective" openehr: "$archetype/data[at0002]/events[at0003]/time" type: "DATETIME" - name: "comment" with: fhir: "$resource.note.text" openehr: "$archetype/data[at0002]/events[at0003]/data[at0001]/items[at0024]" type: "STRING" Operational Templates ^^^^^^^^^^^^^^^^^^^^^ If openFHIR Engine is not integrated (see :doc:`integrations`) with an existing openEHR repository where it's fetching/searching templates for, then they need to exist within the database of the engine itself. .. http:post:: /opt Create a new operational template **Example request**: .. sourcecode:: http POST /opt HTTP/1.1 Content-Type: application/xml Body: