# APIs

The ArdenSuite Server provides three interfaces to enable service-oriented access for arbitrary client applications and to integrate the ArdenSuite into existing environments. The following interfaces are supported:

NOTE

Read our instruction manual How to Call Arden Syntax MLMs on an ArdenSuite Server Using REST and SOAP—SIRS Notification as an Example for a practical guide on how to use REST and SOAP with the ArdenSuite Server. Find more how-to instruction manuals as well as the files to accompany the manuals in our Learning Center.

To illustrate how to call an MLM using web service protocols, we supply you with a working example. In this example, we implemented an MLM that performs a simplified body mass index (BMI) calculation and a subsequent classification based on the calculated BMI. The MLM can be found here. To work with this example, create a new project in the ArdenSuite IDE, copy this MLM into the project, compile it, and deploy the compiled MLM on the ArdenSuite Server.

# REST

The ArdenSuite Server provides a REST application programing interface. The URL to access this interface is:

http://{server}:8080/REST/

To access the REST interfaces, a basic authentication is required.

The following endpoints are available:

http://{server}:8080/REST/CALLMLM

This endpoint is used to execute MLMs. To execute an MLM, the URL parameters mlmName and mlmInstitution are required to identify the MLM. The mlmVersion is optional. If no version is specified, the MLM with the highest version number is used.

Usage: POST

http://{server}:8080/REST/CALLMLM?mlmName=FHIRRead&mlmInstitution=Medexter

or

http://{server}:8080/REST/CALLMLM?mlmName=FHIRRead&mlmInstitution=Medexter&mlmVersion=1.0

Parameters: via REST body

# Call Event

http://{server}:8080/REST/CALLEVENT

This endpoint is used to trigger all MLMs which listen for a given event. These events can be specified inside MLMs. This endpoint also includes the STOPEVENT endpoint functionality. When called, the ArdenSuite Server first checks which MLMs should be executed due to the event and after that it checks if there are MLMs where the event was registered as a stop event—the STOPEVENT endpoint checks for stop events only.

Usage: POST http://{server}:8080/REST/CALLEVENT?event=eventname

Parameters: via REST body

# Stop Event

http://{server}:8080/REST/STOPEVENT

This endpoint is used to execute stop events. If MLMs are written to be executed periodically, there is an option to specify an event as UNTIL parameter. Using this endpoint, MLMs bound to a certain stop event are stopped.

Usage: POST http://{server}:8080/REST/STOPEVENT?event=eventname

Parameters: via REST body

# List Server Protocol

http://{server}:8080/REST/LISTSERVERPROTOCOL

This endpoint returns a list of protocol logs generated by the server.

Usage: GET

Parameters: no parameters

# Details Server Protocol

http://{server}:8080/REST/DETAILSERVERPROTOCOL?protocolID=<protocolID>

This endpoint returns a list of protocol log entries of a given protocol ID.

Usage: GET

Parameters: The returned id from starting the endpoint or any id from the list

# Get Server Protocol status

http://{server}:8080/REST/GETPROTOCOLSTATUS

This endpoint returns the current protocol session id, if there is an active protocol session. When there is no active protocol session, No active protocol session is returned.

Usage: GET

Parameters: no parameters

# Start Server Protocol

http://{server}:8080/REST/STARTSERVERPROTOCOL?TTL=<hours>

This endpoint starts a new protocol session, and returns its id. A previously active protocol session will then be closed.

When TTL (full hours) is given, it stops automatically after the given time. When TTL is not provided, the session runs until the next start / stop protocol call.

Usage: GET

Parameters: : optional argument

# Stop Server Protocol

http://{server}:8080/REST/STOPSERVERPROTOCOL

This endpoint stops the current protocol session. When no protocol session is active, No active protocol session is returned.

Usage: GET

Parameters: no parameters

# Remove Server Protocol

http://{server}:8080/REST/REMOVESERVERPROTOCOL?protocolID=<protocolID>

This endpoint removes a given protocol session. When the protocol session is not found, <protocolID> not found is returned.

Usage: GET

Parameters: the protocol session, that should be removed.

# Get the server logs

http://{server}:8080/REST/GETLOGZIPS

This endpoint can (when the user has rest.log permissions) collect and send the logs of the server as zip file.

Usage: GET

Parameters: no parameters

# Create a new user

http://{server}:8080/REST/ADDUSER

This endpoint can (when the user has rest.service permissions and is in the Admin group) create a new user. The user is activated on creation. The restrictions of the normal user-creation (encoding + format of password) are also checked.

Neither name nor pass nor passRe may contain the : char.

Usage: GET

Parameters:

  • name Username of the new user (required)
  • pass Password of the new user (required)
  • passRe Reenter the password of the new user (required)
  • group The group of the new user (required)
  • fName First name of the new user (optional)
  • lName Last name of the new user (optional)

# Change current password

http://{server}:8080/REST/CHPASSWD

This endpoint can (when the user has rest.service permissions) change the current password of an authenticated user. The restrictions of the normal user-creation (encoding + format of password) are also checked.

Neither pass nor passRe may contain the : char.

Usage: GET

Parameters:

  • newPass The new password of the current user
  • passRe Reenter the new password of the current user

All parameters are required.

# How to Use Start and Stop Events

The ArdenSuite Server supports starting and stopping periodic MLM calls via events. To this end, it is possible to specify events inside MLMs like the following and use them inside the evoke slot:

    admission_event := event {admission}; // admission
    discharge_event := event {discharge}; // discharge
    evoke: EVERY 10 seconds FOR 1 day STARTING time of admission_event UNTIL discharge_event;;

To support starting and stopping periodic MLMs for e.g., different patients, the input parameters are taken into account. Otherwise, if a periodic MLM was started for patient 1 and 2 respectively, a discharge event would stop both periodic jobs (MLM calls). However, as the input parameters are taken into account when starting and stopping periodic jobs (MLM calls), we can stop periodic jobs for MLMs which were called with a specific input. E.g., an event call was executed (admission) with the following parameter. In this case, the input could represent patient id 1.

    {
      "type": "number",
      "applicability": 1,
      "primaryTime": null,
      "value": 1
    }

The MLM bound to this event will start as a periodic job and will be executed e.g., every 10 seconds for this input (patient id 1). After that we execute the same event call with a different input (e.g., patient id 2):

    {
      "type": "number",
      "applicability": 1,
      "primaryTime": null,
      "value": 2
    }

If we want to stop the MLM execution for patient 1, we will have to execute a discharge event call using the same input as when the admission event was fired. The ArdenSuite Server will stop all periodic MLM jobs which listen to the discharge event and where the input parameter was:

    {
      "type": "number",
      "applicability": 1,
      "primaryTime": null,
      "value": 1
    }

# Input Parameter Specification

MLMs can get external data in multiple ways: Connectors using READ statements and data input via REST/SOAP body.

To provide the evaluated MLM with an input parameter, data are structured and sent in JSON format as body to the web service methods.

Arden Syntax Value: In Arden Syntax there are several data types available to be used as input parameters: number, string, boolean, time, duration, dayofweek, timeofday, truthvalue, null. In JSON format those are written as follows:

{
    "type": "string",
    "primaryTime": null,
    "applicability": 1,
    "value": "text value"
}

Arden Syntax List: An Arden Syntax list includes all other data types, including objects:

{
    "type": "list",
    "primaryTime": null,
    "applicability": 1,
    "values": [
        {
            "type": "string",
            "primaryTime": null,
            "applicability": 1,
            "value": "text value 1"
        },
        {
            "type": "string",
            "primaryTime": null,
            "applicability": 1,
            "value": "text value 2"
        }
    ]
}
                    

Arden Syntax Object: An Arden Syntax object may have several fields of any other data type. Inside MLMs, these fields are accessed using the . operator:

{
    "type": "object",
    "primaryTime": "2016-08-22T09:30:27",
    "applicability": 1,
    "declaration": "Patient",
    "fields":
    {
        "entry": [{
        "key": "PaCO2",
        "value": {
          "type": "number",
          "primaryTime": "2016-08-22T09:30:27",
          "applicability": 1,
          "value": 34
        }
        },
        {
        "key": "heartRate",
        "value": {
          "type": "number",
          "primaryTime": "2016-08-22T09:30:27",
          "applicability": 1,
          "value": 88
        }
        },
        {
        "key": "immatureBand",
        "value": {
          "type": "number",
          "primaryTime": "2016-08-22T09:30:27",
          "applicability": 1,
          "value": 6
        }
        }
        }]
    }
}
                    

# SOAP

In addition to the REST interface, the ArdenSuite Server also provides a SOAP interface described by a Web Service Description Language (WSDL) file.

NOTE

Read our instruction manual How to Call Arden Syntax MLMs on anArdenSuite Server Using REST and SOAP―SIRS Notification as an Example for a practical guide on how to use REST and SOAP with the ArdenSuite Server. Find more how-to instruction manuals as well as the files to accompany the manuals in our Learning Center.

# WSDL

The WSDL file represents a platform-independent technical description of the corresponding web service. For each client application, the file generates the client stub that can access the remote service. The URL to this WSDL file is:

http://{server}:8080/AS_XML_Protocol/AS_XML_Protocol?wsdl

# Implementing a Java SOAP Client

# Generate Stubs from WSDL

First, the appropriate classes that abstract the access to the service need to be generated, so the programer does not have to worry about the actual network communication. For this, the wsimport tool from the JDK is required:

wsimport -p medexter.arden.server.serviceStubs -keep <WSDLUrl>

The above command creates Java classes in the folder where it was executed using the command line. These classes may be imported into a Java project, whereas <WSDLUrl> contains the URL or path to the WSDL service description, for example:

http://{server}:8080/AS_XML_Protocol/AS_XML_Protocol?wsdl

# Service Call

Once the Java classes have been integrated into the project, the web service can be called. The following sample code shows the invocation of services in Java, including basic authentication:

    public static void main(String[] args) {
        
        String url = "http://localhost:8080/AS_XML_Protocol/AS_XML_Protocol";
        String user = "admin";
        String password = "s3cret";
        String argument = "";

        // Get the service and the port
        ASXMLProtocol_Service service = new ASXMLProtocol_Service();
        ASXMLProtocol port = service.getASXMLProtocolPort();
        
        // Use the BindingProvider's context to set the endpoint
        BindingProvider bp = (BindingProvider)port;
        
        /* Optional if you to need to change the endpoint */
        bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url);
        /* Optional  credentials */
        bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, user);
        bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password);

        /* calling the web service method */
        String text = port.evaluateXMLRequest(argument);
        System.out.println(text);
    }

    final String argument = 
                            "<usecase>" +
                              "<callMlm>" +
                                "<key>" +
                                  "<mlmName>RS_SIRS-Notification1</mlmName>" +
                                  "<institution>Medexter Healthcare, Vienna, Austria</institution>" + 
                                "</key>" +
                                "<arguments" +
                                "</arguments>" +
                              "</callMlm>" +
                            "</usecase>";
                            

The above client calls the method evaluateXMLRequest of the ArdenSuite Server. The method evaluateXMLRequest calls the ArdenSuite Server to evaluate the given request. The request string (argument variable) must contain an XML document, corresponding to the ArdenSuite Server protocol. The XML schema for those messages is available here. The following operations are supported:

  • callMlm
  • callEvent

# CDS Hooks

The ArdenSuite provides a CDS Hooks API that was programed according to CDS Hooks specification version 1.0. The ArdenSuite Server allows to specify a Hook name and Hook prefetch data for each MLM individually via the ArdenSuite MLM management screen. The MLMs where these data slots are set will be taken into account by the CDS Hooks discovery endpoint.

# Add Hook to MLM

To add a Hook, please perform the following steps:

  1. Press the "Manage CDS Hooks" button ( ) in the MLM row on the right. A window will open:

    cds-hook-man
  2. You have 2 options: Either choose an already created Hook from the list on the right by clicking on it, or create a new Hook (see next step). MLMs with the same Hook can have different or no prefetch statements. Therefore, when selecting a Hook from the list, the prefetch field is empty.

  3. Create a new Hook:

    • Hook Name: Enter Hook name.
    • Hook Prefetch: This is optional and has to be set as JSON string e.g.,
      { 
        "patient" : {
          "resourceType" : "Patient",
          "gender" : "male",
          "birthDate" : "1925-12-23",
          "id" : "1288992",
          "active" : "true"
        }
      }
      
  4. Click Save to create the Hook, otherwise click Cancel.

You can easily spot MLMs with Hooks in the MLM Management screen, because their "Manage CDS Hooks" buttons ( ) on the right are in color.

# Edit Hook

To edit an MLM's existing Hook, perform the following steps:

  1. Press the Manage CDS Hooks button ( ) on the right of the MLM. A window will open:

    cds-hook-man-edit
  2. Edit any of the pre-filled fields or choose a different hook from the list instead.

  3. Click Save to save your changes, otherwise click Cancel.

# Delete Hook

To delete a Hook from an MLM, follow these steps:

  1. Press the "Manage CDS Hooks" button ( ) on the right of the MLM. A window will open.
  2. Empty the Fields "Hook Name" and "Hook Prefetch".
  3. Click Save to delete the Hook, otherwise click Cancel.

MLMs without a Hook are indicated with a grey "Manage CDS Hooks" button ( ) .

# CDS Service

Each MLM used for the CDS Hooks API is considered a CDS service according to the CDS Hooks specification. An MLM's name, institution, and version serve as the CDS service ID, e.g., there is an MLM with the name TestCDSHooks, the institution Medexter Healthcare, and version 1.0 for which the hook patient-view was assigned:

CDS Hooks Discovery Endpoint:

http://:8080/CDSHOOKS/cds-services

{
  "services": [
    {
      "hook": "patient-view",
      "description": "TestCDSHooks, Arden Version 2.9, Institution: Medexter Healthcare, Version: 1.0",
      "id": "TestCDSHooks?mlmInstitution=Medexter Healthcare&mlmVersion=1.0",
      "title": "TestCDSHooks"
    }
  ]
}

According to the CDS Hooks specification, this CDS service is available at the following URL:

http://localhost:8080/CDSHOOKS/cds-services/TestCDSHooks?mlmInstitution=Medexter >Healthcare&mlmVersion=1.0.

If a CDS service is called (see CDS Hooks specification), the whole request body is transformed into an Arden Syntax object and passed to the MLM as input parameter.

NOTE

Calling a CDS service via the CDS Hooks API, a FHIR server may be passed, which is used to retrieve data (see connector options and priority levels section). This server acts as a default connection.

{
  "hookInstance" : "d1577c69-dfbe-44ad-ba6d-3e05e953b2ea",
  "hook" : "patient-view",
  "context" : {
    "var1" : "test",
    "var2" : 2,
    "patientId" : "bd7cb541-732b-4e39-ab49-ae507aa49326"
  },
  "prefetch" : {
    "patientToGreet" : {
      "resourceType" : "Patient",
      "gender" : "male",
      "birthDate" : "1925-12-23",
      "id" : "bd7cb541-732b-4e39-ab49-ae507aa49326",
      "active" : "true"
    }
  }
}

Inside the MLM, this request body can be used like this:input := Argument; patient_birthdate := input.prefetch.patientToGreet.birthDate;

# Cards

To generate CDS Hooks cards, an object representing the specified cards hierarchy has to be created by the user inside the MLM. The object field names have to be chosen according to the CDS Hooks specification and in addition have to use CDSHOOKS_ as prefix. This is to avoid conflicts between Arden Syntax reserved names and CDS Hooks reserved names.

cardobj       := OBJECT [CDSHOOKS_summary, CDSHOOKS_detail, CDSHOOKS_indicator, CDSHOOKS_source, 
                            CDSHOOKS_suggestions, CDSHOOKS_selectionBehavior, CDSHOOKS_links];   
sourceobj     := OBJECT [CDSHOOKS_label, CDSHOOKS_url, CDSHOOKS_icon];
suggestionobj := OBJECT [CDSHOOKS_label, CDSHOOKS_uuid, CDSHOOKS_actions];   
actionobj     := OBJECT [CDSHOOKS_type, CDSHOOKS_description, CDSHOOKS_resource];
linkobj       := OBJECT [CDSHOOKS_label, CDSHOOKS_url, CDSHOOKS_type, CDSHOOKS_appContext];
resourceobj   := OBJECT [CDSHOOKS_resourceType, CDSHOOKS_id, CDSHOOKS_status, CDSHOOKS_date,    
                            CDSHOOKS_weekDay, CDSHOOKS_duration];

These objects can be used to build a CDS Hooks card response:

card := new cardobj;
        
context := input.context;
prefetch := input.prefetch;

cDetail := context.var1 || " " || context.var2 || " " || prefetch.patientToGreet.birthDate;
        
card.CDSHOOKS_summary := "This cards summary";
card.CDSHOOKS_detail := cDetail;
card.CDSHOOKS_indicator := "info";
card.CDSHOOKS_selectionBehavior := "at-most-one";
        
sourceObj := new sourceobj;
sourceObj.CDSHOOKS_label := "Source Label";
sourceObj.CDSHOOKS_url := "www.google.com";
sourceObj.CDSHOOKS_icon := "www.google.com";

card.CDSHOOKS_source := sourceObj;

resource := new resourceobj;
resource.CDSHOOKS_resourceType := "ProcedureRequest";
resource.CDSHOOKS_id := 1.1;
resource.CDSHOOKS_status := true;
resource.CDSHOOKS_date := 2018-11-28T13:30:00;
resource.CDSHOOKS_weekDay := Monday;
resource.CDSHOOKS_duration := 1 day + 2 hours;
        
action1 := new actionobj;
action1.CDSHOOKS_type := "create";
action1.CDSHOOKS_description := "Action 1";
action1.CDSHOOKS_resource := resource;

action2 := new actionobj;
action2.CDSHOOKS_type := "update";
action2.CDSHOOKS_description := "Action 2";
action2.CDSHOOKS_resource := resource;

actionList := (action1, action2);

suggestion1 := new suggestionobj;
suggestion1.CDSHOOKS_label := "Suggestion 1";
suggestion1.CDSHOOKS_uuid := "1";
suggestion1.CDSHOOKS_actions := actionList;

suggestion2 := new suggestionobj;
suggestion2.CDSHOOKS_label := "Suggestion 2";
suggestion2.CDSHOOKS_uuid := "2";
suggestion2.CDSHOOKS_actions := actionList;

suggestionList := (suggestion1, suggestion2);
card.CDSHOOKS_suggestions := suggestionList;

link1 := new linkobj;
link1.CDSHOOKS_label := "Link 1";
link1.CDSHOOKS_url := "www.google.com/link1";
link1.CDSHOOKS_type := "absolute";
link1.CDSHOOKS_appContext := "Context";

link2 := new linkobj;
link2.CDSHOOKS_label := "Link 2";
link2.CDSHOOKS_url := "www.google.com/link2";
link2.CDSHOOKS_type := "absolute";
link2.CDSHOOKS_appContext := "Context";

linkList := (link1, link2);

card.CDSHOOKS_links := linkList;

If an MLM like this is called, the JSON response would be as follows:

{
  "cards": [
      {
          "summary": "This cards summary",
          "indicator": "info",
          "selectionBehavior": "at-most-one",
          "suggestions": [
              {
                  "label": "Suggestion 1",
                  "uuid": "1",
                  "actions": [
                      {
                        "resource": {
                          "date": "2018-11-28T13:30:00+01:00",
                          "duration": "1 day 2 hours",
                          "weekDay": 1,
                          "id": 1.1,
                          "resourceType": "ProcedureRequest",
                          "status": true
                        },
                        "description": "Action 1",
                        "type": "create"
                      },
                      {
                        "resource": {
                          "date": "2018-11-28T13:30:00+01:00",
                          "duration": "1 day 2 hours",
                          "weekDay": 1,
                          "id": 1.1,
                          "resourceType": "ProcedureRequest",
                          "status": true
                        },
                        "description": "Action 2",
                        "type": "update"
                      }
                  ]
              },
              {
                "label": "Suggestion 2",
                "uuid": "2",
                "actions": [
                  {
                    "resource": {
                      "date": "2018-11-28T13:30:00+01:00",
                      "duration": "1 day 2 hours",
                      "weekDay": 1,
                      "id": 1.1,
                      "resourceType": "ProcedureRequest",
                      "status": true
                    },
                      "description": "Action 1",
                      "type": "create"
                  },
                  {
                    "resource": {
                      "date": "2018-11-28T13:30:00+01:00",
                      "duration": "1 day 2 hours",
                      "weekDay": 1,
                      "id": 1.1,
                      "resourceType": "ProcedureRequest",
                      "status": true
                    },
                    "description": "Action 2",
                    "type": "update"
                  }
                ]
            }
          ],
          "links": [
            {
              "appContext": "Context",
              "label": "Link 1",
              "type": "absolute",
              "url": "www.google.com/link1"
            },
            {
              "appContext": "Context",
              "label": "Link 2",
              "type": "absolute",
              "url": "www.google.com/link2"
            }
          ],
          "detail": "test 2 1925-12-23T00:00:00",
          "source": {
            "icon": "www.google.com",
            "label": "Source Label",
            "url": "www.google.com"
          }
      }
  ]
}
Last updated: March 8, 2022