Api
Form plug-in to execute a RESTful API
Table of Contents
The DataSystems.Plugins.Api plug-in allows you to make a web request to an external API. The plug-in is designed to work with REST APIs, but may work with any API that uses HTTP requests.
Configuring the Request
The most important part of configuring the Api plug-in is using the properties in the API Request category to configure the request to match the format of the API being used.
Specify the HTTP method of the request (GET, POST, PUT, or DELETE) with the Method property.
You configure the base URL using the URL property. Query string data (i.e. ?key=value
) can be added to this property directly or by using the Query String Mappings property.
HTTP headers can be sent using the Header Mappings property.
PUT or POST requests can send simple content by using the Content Mappings property and mapping the keys you want to send to elements on the form or other dynamic values (e.g. @UserID@). More complex content can be sent using the Content property instead (see below).
When making PUT or POST requests, the content will be formatted according to the Content Type property. URL-encoded content will be sent with a Content-Type
header of application/x-www-form-urlencoded
and will look something like key=value&key=value
(e.g. first=Homer&last=Simpson
). JSON content will be sent with a Content-Type
header of application/json
and will look something like {"key":"value","key":"value"}
(e.g. {"first":"Homer","last":"Simpson"}
).
Complex/Formatted Content
If the content requires more complex formatting, you can use the Content property instead of Content Mappings. Enter the content following the format of the API and using dynamic values enclosed in @ symbols. When replacing dynamic values, the values will automatically be escaped following the rules of the Content Type. For example, when sending JSON, a value containing quotes would have the "
replaced with \\"
.
You can use rules, formula fields, and/or RenderHTML elements to compose longer blocks of formatted content, then inject them into the API content by using the "raw-" prefix for the dynamic value (e.g. @raw-ElementInput@
).
Formatting Form Data Examples
Continuing from the above note on complex data the ClientTrack Formula plugin can be a great tool to use to format the data for use by the API Plugin when making requests. Below are examples of how the formula plugin could be the solution to getting data in the correct format for making API Requests using the API Plugin.
Format Date
Examples of how one could use the formula plugin to format a date. Adding the below JavaScript into the formula property of a formula plugin will allow you to format any date being passed into the formula.
/* Javascript Format Date in Formula Plugin */
if(@TDate@ != '') {
var t_date = new Date(@TDate@);
var dd = t_date.getDate();
var mm = t_date.getMonth()+1;
var yyyy = t_date.getFullYear();
if(dd < 10) {
dd='0'+dd;
}
if(mm < 10) {
mm='0'+mm;
}
return yyyy+'-'+mm+'-'+dd;
}
Format CSV
The below is an example of how you can pass either MulitSave Plugin users selections or MutltiSelect user selections into a JSON Array String format.
/* Format CSV Multisave/Select data into a JSON Array String */
/* These First two examples show how to do this on one single concise line. */
JSON.stringify((@CT_Route.RouteID@ + "").split(","));
// The below: spaces trimmed, empty values skipped
JSON.stringify((@CT_Route.RouteID@ + "").split(/[ ,]+/));
/* This example shows how this can be done programmatically step by step. */
var RouteString = (@CT_Route.RouteID@ + ""); /* Append + "" here to force the value to always be a string */
var RouteArray = (RouteString.split(","); /* Convert each value separated by a comma to an array. */
JSON.stringify(RouteArray); /* Converts the JavaScript Array object into a String */
Screenshots and gif of the above in action
Handling the Response
If the API returns data in JSON format, you can map the values returned back to elements on the form using the Result Mappings property. You specify which element should be set, then specify the result property you want to set it to. You can use nested properties by following the rules of JSON/JavaScript.
NOTE: You can also set an element’s value to the entire content returned by using the special key $content$
. Also note that you can view the constructed Request and Response when the api debug mode is turned on. See the section in this document on Logging and Debugging titled Logging/Auditing/Debugging for more information.
Example
Response Content
{
"firstName": "Homer",
"lastName": "Simpson",
"spouse": {
"firstName": "Marge",
"lastName": "Simpson"
},
"children": [
{
"firstName": "Bart",
"lastName": "Simpson"
},
{
"firstName": "Lisa",
"lastName": "Simpson"
},
{
"firstName": "Maggie",
"lastName": "Simpson"
}
],
"Favorite Ice Cream": "Neopolitan"
}
Property |
Value |
---|---|
firstName | Homer |
['lastName'] | Simpson |
spouse.firstName | Marge |
children[0].firstName | Bart |
["Favorite Ice Cream"] | Neopolitan |
Response headers can be mapped to form elements using the Result Header Mappings property.
A screenshot below shows an example of how the Result Header Mappings can be mapped:
The below example shows how to do three things:
1. Map a nested key/value pair: body.date. Inside of the body object is the key of date.
2. Map the entire Response: Using the syntax $content$ we can spill the entire response into a form element variable and display it.
3. Map nested Array Data: headers[0].date2[0].date. This example shows how to drill into a JSON Key/Value pair object nested inside two arrays. Within the headers array is an array called date2. Within that array exists a JSON Object with the key date.
Handling Errors
The API should return a response with a status code in the 200-299 range, indicating that it completed successfully. If it doesn’t, it’s considered invalid and won’t be processed by the Result Mappings/Result Header Mappings. Instead the form will display an error message. You can use the Error Messages to display a particular message for a particular response code (e.g. you might want to display "The item doesn’t exist" for a 404 response). The Invalid Message property configures the default message for an invalid response.
Some APIs return content in their response that may contain a message or other data. You can map this data to elements on the form using the Error Mappings property.
If the API takes too long to execute, as configured by the Timeout property, the request will be aborted and the form will display a message configured by the Timeout Message property, which defaults to "The API timed out."
If you haven’t configured a message or there’s an exception preventing the API from executing (e.g. there’s a network problem), the form will display a message configured by the Error Message property, which defaults to "There was a problem executing the API: @message@".
If you configure an error message to be NONE
, the form will not display the error message. Dynamic values within an error message will be replaced. @message@ is a special key that will be replaced with the error message of the Exception.
Executing the API
Once the API is configured, you need to execute it. Properties in the API Execution category control API execution.
You can use the Execute If property to set a condition that must evaluate to true for the API to execute.
You can limit the time an API is allowed to execute by setting the Timeout property. The default is 100 seconds. If the API fails to respond within the specified duration, the form will display an error message configured by the Timeout Message.
The behavior of the Api plug-in varies based on the chosen UI Type (note that UI Type is in the Appearance category).
Last the API Plugin can be triggered using a Refresh List Action. More on this below.
Interactive Mode (Button or Command Link)
When displayed as a Button or Command Link, the API will execute when the button is clicked.
On an Edit or Multi-Edit form, you can configure the Save Behavior property to also save the form when you click the button, before or after executing the API.
On a Report form, you can configure the Report Behavior property to run the report when you click the button, before or after executing the API.
On a Search or Multi-Edit form, you can configure the Search Behavior property to also load form results before or after you execute the API.
Passive Mode (Checkbox or None)
In passive mode, the execution is triggered by searching, saving, or running the report.
For the API to execute in Checkbox mode, the checkbox must be checked. When using None, the field must have a value of Y
.
On an Edit or Multi-Edit form, you can run the API before or after saving the form by setting the Save Behavior property.
On a Report form, you can run the API before or after you run the report by setting the Report Behavior property.
On a Search or Multi-Edit form, you can run the API before or after the form executes the query to load the search results by setting the Search Behavior property.
In some cases, multiple APIs need to be run in sequence, such as executing an API to authenticate and passing a token to another API to load or save a resource. In these cases, you can use the Chain After property to select the Api plug-in that must execute first. This API will execute after the selected API is successful. Please note that it must still be checked or have a value of Y and it will only execute if Execute If not set or evaluates to true. If that API sets cookies that should be sent to the subsequent request(s), you can also check the Chain Cookies checkbox.
Manually Execute the API Using Rules
Regardless of the UI Type, the API can be executed by targeting the element with a "Refresh List" rule action.
Refresh or Form Load
You can now trigger the Api plug-in via a Refresh List action. E.g., I set up a text box named "AutoEcho" and it triggers the Echo POST Api when the value changes.
Manage API Keys and Reference them as variables
When a user accesses the Form Designer Tool and also has been given Write access to the "System Integration" Tool Access Permission, they will see a link in the API Element description properties pane to "Manage API Keys" in the Plug-in’s help text or a user can navigate to the ~/integration/api-keys url (e.g. https://clienttrack.eccovia.com/integration/api-keys). This will allow a user to manage the values in the Customer.dbo.APIKey table via the UI.
Once key/value pairs are saved in the Customer.dbo.APIKey table, the value can be referenced as a variable in the API Plug-in properties by using the notation, @ApiKey-key@. In the example displayed in the below screengrabs, the "SubscriptionKey" was added to the Customer.dbo.APIKey table and the associated value is leveraged by the plug-in due to the variable specified in the Query String Mapping property (@ApiKey-SubscriptionKey@). This effectively hides API key values from users with Form Designer access that do not have System Integration access.
Logging/Auditing/Debugging
For auditing or debugging, you can log values using the Log Mappings property. These logs are stored with the other application request logs and are visible via the the log viewer (~/log/request/{requestId}) so DO NOT log sensitive information, such as PHI/PII. Note that the response of the form’s Submit request contains the ID of the request in the X-RequestId header; this will also be logged to the console when you’re in debug mode (the jsdebug cookie is set).
Advanced Debugging
If you have tool access to the Form Designer and Integration, you can view the API Request and Response by enabling advanced API debugging. To do this, hold Ctrl + Alt then click the help icon in order to open the browser settings page.
Alternately, you can open your browser tools (F12), go to the console, and set the api-debug cookie:
setCookie("api-debug", 1, 1);
When the Api plug-in executes, the full request and response will be logged to your console. Please note that this may contain sensitive information so be careful to remove any such information when sharing or saving.
NOTE: Even if the cookie is set, no data will be sent back to the console if the user does not have the System Integration user permission. This has to be set Globally on the user. If this is simply applied to the user within a single environment the ClientTrack servers will not send back any API data. This permission must instead be applied directly to your -99 Operations user account.
Extra: With some JavaScript you can inject into the existing Help(ctrl+alt) → Browser Settings ClientTrack page a new Check Box just under the existing JavaScript Debug Check Box that when checked will turn on/off the API Debug mode. You can also manually run the code in the below script file in the Dev Console as well. Update 03.02.22: (There is no longer a need for this as the base application core code now has the API Degug Mode built into the Browser Setting tab.
Examples
The EMPI Client Intake form (4574) has two Api plug-ins - one uses a POST request to register the client with the EMPI system while the other uses a PUT request to update the EMPI system with the information entered on the client intake form. Both are configured to send the data in JSON format. The register field also maps the id property of the result back into the Identifier.Value field on the form so it can be saved in the Identifier table.
In the QA 18 environment, I’ve configured form 1000001294, QA Alan API Tests to demonstrate chaining using the Echo API hosted on the dev server, that simply echoes back the request so you can see what you sent.
Properties
API Execution Properties
- Chain After - Choose another Api or ApiSearchResults element. This API will execute after the chosen element.
- Chain Cookies - Works with Chain After. If checked, this API will send any cookies set by the other API element.
- Execute If - An expression to determine when to execute the API. If set, the API will only execute if this evaluates to true.
-
Log Mappings - Values to write to the log, in the format
property=Element&property=Element
. The URL and method are logged automatically. - Save Behavior - When the UI Type is button or command link, setting this property will cause the form to save before or after executing the API. When using other UI types, setting this property will execute the API before or after you save the form, if this element has a value of Y.
- Timeout - The amount of time to wait for the API. This can be milliseconds or a timespan value (hh:mm:ss).
- Timeout Message - The message to display if the API times out.
API Request Properties
-
Content - The formatted text content to send in the PUT or POST request. This value will override the Content Mappings property.
Note: When needing to dynamically populate the content using a ClientTrack dynamic variable that contains special characters or complex data prefix the variable name within the @@ characters with the string ‘raw-’. For example, if generating a JSON array string based on user selected values within a Multiple Select List box or the MultiSaveList Plugin the input to pass into the content could like like this: @raw-UserSelectedValues@ or @raw-cmClient.Race@. -
Content Mappings - The values to send in the content of the PUT or POST API request, in the format
property=Element&property=Element
. - Content Type - The type of content for POST and PUT requests. The default is JSON.
-
Header Mappings - The values to send in the headers of the API request, in the format
header=Element&header=Element
. - Method - The HTTP method to use (default is GET).
-
Query String Mappings - The values to send in the query string of the API request, in the format
key=Element&key=Element
. Also referred to as URL Parameters. Note: When editing/adding the query strings using the Query String Mappings Designer via the Plugin Properties that these values must be mapped to an existing element. Values simply typed into the Element drop down box will not be mapped correctly. For static data that needs to be mapped create custom elements on the form and set the default values of those elements. If needing these values for existing records when editing be sure to set this also in the SQL Expression property of the custom element as well. - URL - The URL End Point of the API.
API Response Properties
-
Error Mappings - If there's an error response, maps the properties of the results of the API back to the elements on the form, in the format
Element=property&Element=property
. - Error Message - The message to display if there's an error executing the API. @message@ will be replaced with the actual message. Use NONE to ignore the error.
-
Error Messages - Error messages to display based on the response code from the API, in the format
responseCode=message
(e.g. 404=Not Found). - Invalid Message - The error message to display if the API returns an invalid response (e.g. a 400 response or 500 error).
-
Result Header Mappings - Maps the headers of the response of the API back to the elements on the form, in the format
Element=property&Element=property
. -
Result Mappings - Maps the properties of the results (Body of the Response) of the API back to the elements on the form, in the format
Element=property&Element=property
Appearance
-
UI Type - This parameter determines how the plug-in presents itself to the user.
- None displays no UI and simply executes the API after saving if the element has a value of "Y".
- Checkbox displays a checkbox. On Form Save the API will execute only if the checkbox is checked. The input of the API Plugin when set to a checkbox can be set to True or 1 via a rule.
- Button displays a button that executes the API when clicked.
- Command Link displays a full-width button that executes the API when clicked.