.. _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 2 restful APIs for mapping (``/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`.

Mappings
--------
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 following endpoints:

.. 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: <canonical json>

   .. sourcecode:: http

      POST /openfhir/tofhir?templateId=dataset_poc_rso-zl_acp HTTP/1.1
      Content-Type: application/json
      Body: <flat json>


   :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: <fhir resource>


   :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: 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"

.. 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: "category.coding.code"
                    operator: "one of"
                    criteria: "[weight]"
            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: "category.coding.code"
                    operator: "one of"
                    criteria: "[weight]"
            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:
            <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
            <template xmlns="http://schemas.openehr.org/v1">
                <language>
                    <terminology_id>
                        <value>ISO_639-1</value>
                    </terminology_id>
                    <code_string>en</code_string>
                </language>
                <description>
                    <original_author id="date">2020-09-17</original_author>
                    <original_author id="name">test</original_author>....

.. http:put:: /opt/(uuid:opt_unique_id)

   Update an existing operational template

   **Example request**:

   .. sourcecode:: http

      PUT /opt/d07ca1b7-0d1b-4aac-82b4-cb76b9dd55e0 HTTP/1.1
      Content-Type: application/xml
      Body:
            <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
            <template xmlns="http://schemas.openehr.org/v1">
                <language>
                    <terminology_id>
                        <value>ISO_639-1</value>
                    </terminology_id>
                    <code_string>en</code_string>
                </language>
                <description>
                    <original_author id="date">2020-09-17</original_author>
                    <original_author id="name">test</original_author>....

.. http:get:: /opt/(uuid:opt_unique_id)

   Read an existing operational template

   **Example request**:

   .. sourcecode:: http

      GET /opt/d07ca1b7-0d1b-4aac-82b4-cb76b9dd55e0 HTTP/1.1
      Accept: application/xml

Mapping Insights
----------------
.. note::
    See more about mappings insights: :ref:`insights`.

.. http:post:: /openfhir/insights

   Get all mapping insights that suit provided filter

   **Example request**:

   .. sourcecode:: http

      POST /openfhir/insights HTTP/1.1
      Content-Type: application/json
      Body:
        {
            "requestId": "456",
            "direction": "TO_FHIR"
        }

.. http:get:: /openfhir/insights/payload/{payloadId}

   Get specific payload of a mapping insight

   **Example request**:

   .. sourcecode:: http

      GET /openfhir/insights/payload/123 HTTP/1.1
      Accept: application/json