Appearance
REST
This extension enables you to query JSON-based REST APIs and post messages with content to them.
It provides various options regarding methods of transport, headers and authentication, and is an open-ended way to cover as many use cases as possible. JSON objects are directly converted into Arden Syntax objects, and the other way around when written.
Configuration
The following basic options can be configured for the REST extension:
- Base URL: The base URL that is prepended to all URLs specified within an MLM
- Timeout: Amount of milliseconds the extension will wait on any query until it returns
NULL - Headers: List of headers by name and value that are always sent with every request
Authentication
For Authentication, Authentication Type can be set to one of three values, which each require their own different options:
- Basic: Simple HTTP Basic Username/Password authentication
- Username
- Password
- Bearer: For use with fixed authentication tokens
- Token
- OAuth: Authentication by the OAuth
client_credentialsmethod- Base URL: Base URL of the OAuth API
- Grant Type: Only supports the
client_credentialsflow - Client ID: ID of your registered client with this application
- Client Secret: Secret of your registered client with this application
Example configuration

Usage
The extension can be used from an MLM in three basic ways:
- READ can be used for retrieval like
GEToperations. It can query an API in a single line and is more readable than an INTERFACE call, but can only be used in the data slot. Use it if you only perform a query in a data slot once. - WRITE can be used for posting data to an API via
POST,PATCH, etc. It is the preferred way to write a final result and can only be used in the action slot. - INTERFACE can be used to define a REST operation in the data slot and be
CALLed anytime. Use it if you need to do calls in the logic slot.
READ
Every call made by read is a GET request without any content allowed, and responses are expected to be JSON formatted.
Parameters
| Name | Required | Example | Description |
|---|---|---|---|
path | Yes | path "/api/resource?incl=true&limit=15" | Path to call, may include query parameters, is appended to the Base URL. No absolute URLs are allowed. |
header | No, can be provided multiple times | header X-Clacks-Overhead "GNU Terry Pratchett" | Set any custom header. If the same header is allready set in extension configurations, this mapping clause overwrites the header. Allows variable injection of the header value or literal strings as content |
timeout | No | timeout 30000 | How many milliseconds until a request is failed with NULL. Overwrites configuration. |
Examples
READ with custom headers and query parameter filters only
arden-syntax
data:
all_diagnoses := READ {FROM rest-configuration WITH path "/patient/01/diagnoses?not-before=2023-01-01" AND header Accept-Language "de-AT,de-DE,de"};
;;READ with post-request filter
INFO
Unlike FHIR operations, the data returned here is first fetched and then filtered by Arden Syntax.
arden-syntax
data:
all_diagnoses := READ {FROM rest-configuration WITH path "/patient/01/diagnoses"} WHERE it.first_symptom_ts >= 2023-01-01;
;;READ with custom path and headers using variable injection
arden-syntax
data:
dynamic_path := "/patient/" | ARGUMENTS | "/diagnoses";
acceptable_languages_header := "de-AT,de-DE,de";
all_diagnoses := READ {FROM rest-configuration WITH path $dynamic_path AND header Accept-Language $acceptable_languages_header};
;;WRITE
WRITE operations can only be invoked in an action slot, concluding a successful MLM execution. The response body is discarded in the WRITE statement, as it is intended to write a result and conclude the MLM. It supports the common HTTP methods for that purpose (PUT, POST, PATCH or DELETE).
Parameters
WRITE operations follow the schema WRITE <content> AT <destination>. A DESTINATION is required for the destination and contains path, method and the other common parameters. For content, either a variable or a MESSAGE can be provided (see below). When a variable is provided, two rules dictate serialization to JSON:
- An object or a list are serialized to JSON
- A string is directly passed on as HTTP message
DESTINATION parameters:
| Name | Required | Example | Description |
|---|---|---|---|
path | Yes | path "/api/resource?incl=true&limit=15" | Path to call, may include query parameters, is appended to the Base URL. No absolute URLs are allowed. |
timeout | No | timeout 30000 | How many milliseconds until a request is failed with NULL. Overwrites configuration. |
method | Yes | method PUT | HTTP method to sent the request. Allowed are PUT, POST, PATCH, or DELETE |
MESSAGE (discouraged) parameters:
| Name | Required | Example | Description |
|---|---|---|---|
content | No | content $variable_injected | Content to send to a server. Only Arden Objects (will be converted to json) and Strings (encode to UTF-8 byte content in the Http request) are allowed contents. Allows variable injection ($ + variable name, which exists at time of CALL invokation) or literal strings as content. |
header | No, can be provided multiple times | header X-Clacks-Overhead "GNU Terry Pratchett" | Set any custom header. If the same header is already configured in the REST configuration, this mapping clause overrides it. Allows variable injection of the header value or literal strings as content |
INFO
The message mapping clause is mainly supported to comply with the Arden standard and allow custom headers. If content were the only parameter in your clause, we actually encourage to supply the content directly, either as string or variable, inside the WRITE statement. It is much more readable (see examples below).
Examples
WRITE object as JSON with POST request
arden-syntax
data:
record_diagnosis_destination := DESTINATION {FROM rest-configuration WITH method POST AND path "/diagnosis"};
diagnosis := NEW Condition WITH [ code := "disease" ];
;;
logic: CONCLUDE TRUE; ;;
action:
WRITE diagnosis AT record_diagnosis_destination;
;;WRITE object with custom headers and variable injection, using MESSAGE statement
TIP
If possible, it is recommended to supply the request content as object variable inside the WRITE statement, as it reduces the implementer-specific logic you have to deal with in an MLM
arden-syntax
data:
diagnosis := NEW Condition WITH [ code := "disease" ];
never_forgotten := "GNU Terry Pratchett"
record_diagnosis_destination := DESTINATION {FROM rest-configuration WITH method POST AND path "/diagnosis"};
diagnosis_request := MESSAGE { FROM rest-configuration WITH content $diagnosis AND header Set-Cookie "credentials=u1234" AND header X-Clacks-Overhead $never_forgotten};
;;
logic: CONCLUDE TRUE; ;;
action:
WRITE diagnosis_request AT record_diagnosis_destination;
;;WRITE literal JSON string body, without MESSAGE statement
arden-syntax
data:
record_diagnosis_destination := DESTINATION {FROM rest-configuration WITH method POST AND path "/diagnosis"};
diagnosis_request_json := "[ { \"code\": \"diagnosis\", \"val\": 0.92 }, { \"code\": "npa" } ]";
;;
logic: CONCLUDE TRUE; ;;
action:
WRITE diagnosis_request_json AT record_diagnosis_destination;
;;WRITE object with literal JSON string body, using MESSAGE statement
TIP
If possible, we recommend to supply the request content as object variable inside the WRITE statement, as it reduces the implementer-specific logic you have to deal with in an MLM
arden-syntax
data:
record_diagnosis_destination := DESTINATION {FROM rest-configuration WITH method POST AND path "/diagnosis"};
diagnosis_request := MESSAGE { FROM rest-configuration WITH content "{ "code": "diagnosis", "val": 0.92 }" };
;;
logic: CONCLUDE TRUE; ;;
action:
WRITE diagnosis_request AT record_diagnosis_destination;
;;INTERFACE
Arden Syntax INTERFACE operations can be used to define any REST call, which may be executed at any time (or multiple times) within an MLM. For singular calls for data preparation or result writing in the data and action slots, it is recommended to use READ or WRITE instead for brevity and to signal intentionality.
Parameters
| Name | Required | Example | Description |
|---|---|---|---|
path | Yes | path "/api/resource?incl=true&limit=15" | Path to call, may include query parameters, is appended to the Base URL. No absolute URLs are allowed. |
header | No, can be provided multiple times | header X-Clacks-Overhead "GNU Terry Pratchett" | Set any custom header. If the same header is allready set in extension configurations, this mapping clause overwrites the header. Allows variable injection of the header value or literal strings as content |
timeout | No | timeout 30000 | How many milliseconds until a request is failed with NULL. Overwrites configuration. |
method | Yes | method PUT | HTTP method to sent the request. Allowed are PUT, POST, PATCH, DELETE, and GET |
content | No | content $variable_injected | Content to send to a server. Only Arden Objects (will be converted to json) and Strings (encode to UTF-8 byte content in the Http request) are allowed contents. Allows variable injection ($ + variable name, which exists at time of CALL invokation) or literal strings as content. |
Using CALL operation arguments as content body
Arden Syntax allows CALL INTERFACE operations with parameters supplied as operation arguments on call, like this: var := CALL rest_interface WITH variable_name;. This option can be used with a REST configuration to supply the content outside of the mapping clause. The following rules apply:
- If no argument is supplied, no content is sent.
- If one argument is supplied, it is sent as complete body (
Objectbeing parsed as JSON body,Listbeing parsed as JSON list,Stringbeing sent literally) - If more than one argument is supplied, all are sent within a JSON list. Each argument is parsed to the same rules as above
- If both mapping clause
contentand arguments are defined, the REST extension returnsNULL(intent error)
Examples
CALL GET interface conditionally
arden-syntax
data:
rest_read_call := INTERFACE {FROM rest-configuration WITH method GET AND path "/clinic/patient/01"};
called_by_patient_status := ARGUMENTS;
;;
logic:
IF called_by_patient_status.is_sick IS TRUE THEN
patient := CALL rest_read_call;
ENDIF
;;CALL POST resource with mapping clause variable injection
arden-syntax
data:
rest_write_call := INTERFACE {FROM rest-configuration WITH method POST AND path "/clinic/patient" AND content $patient};
;;
logic:
LET patient BE NEW Patient WITH [ name := "Dr. Example" ];
patient_created_response := CALL rest_write_call;
// overwrite patient, but re-use interface method
LET patient BE NEW Patient WITH [ name := "Thomas Example" ];
patient_created_response := CALL rest_write_call;
;;CALL PUT resource with CALL arguments
arden-syntax
data:
rest_put_call := INTERFACE {FROM rest-configuration WITH method PUT AND path "/clinic/patient/01"};
;;
logic:
LET patient BE NEW Patient WITH [ name := "Dr. Example" ];
patient_created_response := CALL rest_put_call WITH patient;
;;CALL GET resource with mapping clause Http-Headers variable injection
arden-syntax
data:
rest_read_call := INTERFACE {FROM rest-configuration WITH method POST AND path "/clinic/patient" AND header X-Clacks-Overhead $never_forgotten};
;;
logic:
LET never_forgotten BE "GNU" | " Terry Pratchett";
patient_response := CALL rest_read_call;
;;