Integrator > Integration Builder >   Scripting reference

Integration Builder scripting reference

The Integration Builder includes an editor that allows you to modify the default transformation scripts for your integrations from within the communication plan builder.

Scripting Language

Transformation scripts are written in JavaScript, designed for execution within the Nashorn JavaScript engine, and should be compliant with ECMAScript 5.1. For security reasons, the instantiation of Java classes from within the scripting runtime is explicitly disallowed.

Scripting Features

Incoming request object

The request object is used to describe the HTTP request posted to the integration service URL. You can use the transformation scripts to access the request headers, parameters, body, etc. The easiest way to examine the content of an incoming request is to send an HTTP request to your integration and then view the details in the Activity Stream. In outbound integration scripts, the request object is referred to as the callback.

Request object properties
Property Description
body

This is the body of the request posted to the integration service URL, and usually contains the JSON or XML payload of an HTTP POST.

  • If the body contains JSON, you can use JSON.parse(request.body) in the script to convert it to a JavaScript object.
  • If the body contains XML, you can use one of the included XML libraries to manipulate the data.
  • If the body is in a query parameter, you can use request.parameters.
headers The HTTP headers of the incoming request. Note the Content-Type parameter that defines the payload type.
parameters

A JavaScript object featuring key-value pairs for any querystring parameters

If the Content-Type in the header is application/x-www-form-urlencoded, this section also contains the POST body parameters.

requestId The unique identifier (UUID) assigned to this request by the integration service when the request is received. This identifier is returned in the response, making it possible to match a request with the results of the script processing.
xtrace

An xMatters internal use ID that allows tracking of the request through the system.

The following is a sample request object:

{
	"body": "<incident importance=\"High\">\n    <ticket>16931</ticket>\n    <summary>Mail server is down</summary>\n    <recipients>\n        <username>bsmith</username>\n        <username>mmcbride</username>\n    </recipients>\n</incident>",
	"headers": {
		"Accept": "*/*",
		"Authorization": "Basic lmht9e46Yo9tc3xleA==",
		"Content-Length": "217",
		"Content-Type": "application/xml",
		"Host": "lugh.xmatters.com:8080",
		"User-Agent": "curl/7.40.0"
	},
	"method": "POST",
	"parameters": {},
	"remoteAddr": "127.0.0.1",
	"requestId": "afc9498a-ba47-418b-912f-d977091b7d2a",
	"timestamp": 1440001619011,
	"url": "http://lugh.xmatters.com:8080/integrations/6FE66C95-81C0-4DDC-B932-0D3609E234BA",
	"xtrace": "afc9498a-ba47-418b-912f-d977091b7d2a"
}

 

^ Back to top

 

 

Form and trigger objects

When working with scripts for "Transform content to create a new xMatters event" integrations, you can use the form object to refer to the default form chosen when building the integration. The form object has a single method, post, which accepts the trigger object as an argument, and posts it to xMatters to create an event. Both the form and trigger objects are predefined and available from within the script. The trigger object should be equivalent to the request body posted to the POST trigger REST API method. You can use the trigger object to set the recipients, priority, form properties, response options, conference bridge status, response counts and callbacks. It accepts the format described in the POST trigger REST API method.

The following example illustrates how to use these objects to specify form properties and recipients based on request body content, and then trigger an event.

// Set a property on the trigger
trigger.properties.building = request.body.site_id;
trigger.properties['Incident ID'] = request.body.ticketnumber;
 
// Set the priority
trigger.priority = request.body.importance;
 
// Manually set the recipients...
trigger.recipients = [ {"targetName": "bsmith"}, {"targetName": "alicea"}, {"targetName": "tobym", "devices": ["Email","Voice Phone"]} ];
// ...or use the helper methods:
// 1. Add recipient using targetName:
trigger.addRecipient('bsmith');
trigger.addRecipient('alicea');
// 2. Or add recipient object, including device filters:
trigger.addRecipient({'targetName': 'tobym', 'devices': ['Email', 'Voice Phone']});
 
// Add a callback
trigger.addCallback({"url":"http://mydomain.com/path/to/my/service/event/status", "type":"status"});
 
// Add a conference
trigger.addConferenceName('P1M1');
 
// Add response options
trigger.addResponse("a1b73279-465f-4f18-a44b-47993c3f75b9");
trigger.addResponse("75f789c2-87b2-4c63-91de-ea6e5834e91d");
 
form.post(trigger);
 

^ Back to top

 

 

HTTP Client requests

Integration scripts can make outbound HTTP requests to an HTTP endpoint using the HTTP client. In the scripts, the outgoing request must specify one of the endpoints by its name, and may include the request method (GET, POST, etc.), a path to append to the URL, and any request headers, parameters, or body data.

The HTTP client

You can use the HTTP client from any transformation script. To make a request, use the global HTTP object's request function to create a request object, then use that object's write method to perform the request. A successful request will return a response object that you can inspect for details such as response headers, response body, and response status.

The following example illustrates a GET request using the HTTP object's request function and write method:

var params = request.parameters;
 
// Prepare the HTTP request
var req = http.request({
  'endpoint' : 'weatherAPI',
  'method' : 'GET',
  'path' : '/data/2.5/weather?q=' + params['location'],
  'headers' : {
    'x-api-key' : 'a3b5f9ca-5fea-4cf6-ae38-e6c1e4afeba9'
  }
});
 
// Send the request and retrieve the response
var resp = req.write();
 
// Post the form, if the request succeeded
if (resp.statusCode == 200) {
  var currentWeather = JSON.parse(resp.body);
  console.log("Current weather in " + currentWeather['name'] + " is " + currentWeather['weather'][0]['description']);
  trigger.properties['Location'] = currentWeather['name'];
  trigger.properties['Description'] = currentWeather['weather'][0]['description'];
  trigger.properties['Weather'] = currentWeather['weather'][0]['main'];
  trigger.addRecipient('companyadmin');
  form.post(trigger);
} else {
  console.log("Unable to post event: failed to get current weather conditions for " + params['location']);
}
 

HTTP request object and write function

The following function returns an HTTP request object that can later be sent using its write() function:

http.request(options)

The request function accepts a JavaScript object representing its options. The following table describes the available options:

Option Type Required Purpose
endpoint string yes

Name of the pre-configured endpoint (case-sensitive) that the request is targeting.

NoteSlack endpoints require an additional function call to add the Slack token to API requests.

method string   HTTP request method to use; default is GET
path string   Path to append to the URL defined in the pre-configured endpoint. Querystring parameters may be included.
headers object   HTTP headers to send with the request.
autoEncodeURI boolean/string  

By default, legal but unsafe characters in the provided path are auto encoded to URI standards. Include the autoEncodeURI property to override this default behavior:

  • false, 'false', or any other value will not automatically encode any components of the given URI.
  • true or 'true' will auto encode legal but unsafe characters in the provided path.

The request.write() function sends the HTTP request and returns the response if the request succeeds. Success includes any completed HTTP request, even if the response is a 404 "Not Found or 500 "Server Error". A failure means the HTTP request was not able to be made all; for example, due to an invalid host name or the connection refused by the remote server.

request.write([data])
 

If the HTTP request is a POST or other type that sends a request body, that body may be sent as the optional data parameter. If data is not a string, it will be encoded as a string using JSON.stringify. If the data is not intended to be sent as JSON, transform the body into a string and set the correct Content-Type header on the request object.

// Prepare the HTTP request
var req = http.request({
  'endpoint' : 'myEndPoint',
  'method' : 'POST',
  'path' : 'path/to/my/service',
  'headers': {
    'Content-Type': 'application/json'
  }
});
 
// Prepare the HTTP request body
var data = {};
data.ticket = {};
data.ticket.subject = 'Update from xMatters';
 
// Submit the request and capture the response
var response = request.write(data);

Response object

If the HTTP request is successful, the request.write() function returns an object describing the HTTP response with the following properties:

Property Data Type Description
httpVersion string HTTP version used to make the request; usually HTTP/1.1
statusCode integer HTTP status, such as 200, 404, or 500
statusMessage string The description of the statusCode, such as "OK", "Not Found", or "Server Error"
headers object The response headers
body string The response content

^ Back to top

 

 

HTTP/HTTPS webhooks

xMatters makes HTTP webhooks by sending a POST request to the specified URL, and passes information about the event as a JSON object in the request body. This section describes the content of the JSON payload that you can extract and use in your web application. This same data format is used for the request.body payload when an outbound integration calls a script. For more information about webhooks, see Outbound Integration Webhooks.

The following sections describe the properties included in the JSON payloads for status, delivery, and response webhooks.

Common webhook properties

These properties are included in status, delivery, and response webhooks.

Parameter Type Value Example
eventIdentifier Number ID of the event. You can locate the event ID in the tracking report of the event. "eventIdentifier":53443019
date String Date and time the action occurred in UTC format: yy-MM-dd HH:mm:ss.SSS "date":"14-11-03 23:20:59.561"
event properties Array of mixed object types

An array of form properties included in webhooks.

Hierarchy properties use the -> characters to delimit values at different levels of the hierarchy.

List properties separate selected values with the comma (',') character.

 

"eventProperties"[
{"hierarchyProperty":"USA -> California -> Los Angeles"},
{"stringProperty":"Some text"},{"numberProperty":2346},
{"comboBoxProperty":"Medium"}
{"passwordProperty":"password123"},
{"listProperty":"this, that"}
]}

 

Event status webhooks

Event status webhooks are created when an event is initiated, terminated, or when the status of an event changes. It contains the status of the event and the ID of the user who initiated the status change.

Parameter Type Value Example
username String The ID of the user who initiated the event or changed the event status. "username":"mmcbride"

status

String

The status of the event. Available values include the following:

  • active
  • suspended
  • terminated
  • terminated_by_user
  • terminated_by_err
  • terminated_external
  • terminated_ext_passfill
  • terminated_ext_failfill

"status":"suspended"

"status":"terminated_external"

Example event status payload

This example shows the body of a webhook that occured when an event started by the user mmcbride terminated. The form that was used to create this event contains a field named "note" that is included in webhooks.

{
  "status":"terminated",
  "username":"mmcbride",
  "eventIdentifier":53443022,
  "date":"14-11-03 23:30:04.470",
  "eventProperties":[
    {"note":"This is a test."}
  ]
}

 

Device delivery webhooks

Device delivery webhooks are created when a notification is delivered to a recipient. They contain the delivery status and the user and device the notification was delivered to.

Parameter Type Value Example
recipient String ID of the targeted user. "recipient":"mmcbride"
device String Name of the targeted device. "device":"Work Email"
deliveryStatus String

The delivery status. One of:

  • Delivered
  • Failed
  • Unchanged
"deliveryStatus":"Delivered"
deviceID Number Numeric identifier of the device the notification was sent to. "deviceId":2300367
eventType String

The type of delivery event.  For a list of eventType values, see the Event Types table.

"eventType" : "LIVE_NOTIFICATION_DEVICE_ATTEMPT_DISCONNECT"
message String A description of the delivery event, which may include error codes.  "message" : "Recipient hung up before playback was complete"
Event Types

The following table describes the values that may appear in the eventType field.

Device Delivery Status Event Type Description
Delivered LIVE_NOTIFICATION_DEVICE_VOICEMAIL_CALLBACK The notification was delivered to the device and reached voice mail. xMatters left a voice mail message with call-back information because the voice mail option was set to "Callback Info Only". The notification is considered delivered.
LIVE_NOTIFICATION_DEVICE_VOICEMAIL_CONTENT The notification was delivered to the device and reached voice mail. xMatters left a voice mail message with the content of the notification because the voice mail option was set to "Message Content Only". The notification is considered delivered.
LIVE_NOTIFICATION_DEVICE_VOICEMAIL_CONTENT_AND_CALLBACK The notification was delivered to the device and reached voice mail. xMatters left a voice mail message with call-back information and the content of the notification because the voice mail option was set to "Content and Callback Info". The notification is considered delivered.
LIVE_NOTIFICATION_DEVICE_VOICEMAIL_HANG_UP The notification was delivered to the device and reached voice mail. xMatters did not leave a voice mail message because the voice mail option was set to "Do Not Leave Message". The notification is considered delivered.
Failed LIVE_NOTIFICATION_CNS_FAILED_DELIVERED The notification was not delivered to the provider. A message that describes the error is included in the message field.
LIVE_NOTIFICATION_CNS_FAILED_DELIVERED_WITH_CODE The notification was not delivered to the provider. A message that describes the error and an error code from the provider is included in the message field.
LIVE_NOTIFICATION_DEVICE_ATTEMPT_FAILURE The notification was not delivered. A message that describes the error is included in the message field.
LIVE_NOTIFICATION_DEVICE_ATTEMPT_FAILURE_FAX_OR_MODEM_DETECT The notification was not delivered because a fax or modem was detected. The message field states whether it detected a fax or modem.
LIVE_NOTIFICATION_DEVICE_ATTEMPT_FAILURE_PROVIDER_RESPONDED The notification was not delivered, and the provider responded with an error. The provider's error message is included in the message field.
LIVE_NOTIFICATION_FAILURE_WITH_ERROR_CODE The notification failed. An error code from the provider is included in the message field.
LIVE_NOTIFICATION_VOICEMAIL_RETRY

The notification was delivered to the device and reached voice mail. xMatters did not leave a voice mail message because the voice mail options are set to "Retry". The notification is not considered delivered.

The message field describes when xMatters will attempt to retry this notification.

Unchanged LIVE_NOTIFICATION_DEVICE_ATTEMPT_DISCONNECT

The notification was delivered but the call was disconnected before playback was completed.

Example device delivery payload

This webhook shows that a notification was successfully delivered to the Work Email device of mmcbride. The form properties are included in the eventProperties list.

{
  "recipient":"mmcbride",
  "device":"Work Email",
  "deliveryStatus":"Delivered",
  "deviceId":2300367,
  "eventType" : "LIVE_NOTIFICATION_DEVICE_ATTEMPT_DISCONNECT",
 "message" : "Recipient hung up before playback was completed",
  "eventIdentifier":53443021,
  "date":"14-11-03 23:24:16.521",
  "eventProperties":[
    {"comboBoxProperty":"Medium"},
    {"booleanProperty":false},
    {"hierarchyproperty":"USA -> California -> Redding"},
    {"numberProperty":4522},
    {"listProperty":"bananas, apples"},
    {"textProperty":"This is a note."}
  ]
}

 

Response webhook properties

Notification response webhooks are created when a recipient responds to a notification. They include the ID of the recipient, the device they responded on, their response, and any comments they made when they responded to the notification.

Parameter Type Value Example
recipient String ID of the recipient who responded to the notification. "recipient":"kclark"
device String Name of the device the recipient used when responding to the notification. "device":"iPhone"
response String The response the recipient selected. "response":"Accept"
annotation String

The annotation included with the response, or "null" if no annotation is included.

Captures the value of a comments included with responses from the mobile apps.

"annotation":"I'm on my way"

Example notification response payload

This webhook shows that the user mmcbride responded "Accept" on her iPhone and annotated her response with the message "I'm on my way".

{
  "recipient":"mmcbride",  
  "device":"iPhone",
  "response":"Accept",
  "annotation":"I am on my way",
  "eventIdentifier":53443021,
  "date":"14-11-03 23:25:06.424",
  "eventProperties":[]
}

^ Back to top

 

 

Logging

You can use the console object to write messages from the script to the log file in the Activity Stream.

For example:

console.log("About to post to xMatters");

Stringify

If you want to write out the value of a JavaScript object, use JSON.stringify to serialize it to JSON; otherwise, it will appear in the log as "[object Object]".

For example:

// To log a JavaScript object in a readable format:
console.log(JSON.stringify(trigger));

^ Back to top

 

 

Shared Libraries

Shared libraries allow utility functions written in JavaScript code to be factored out of integration scripts and shared between integrations in the same communication plan.

The following example illustrates a shared library called 'String Utilities' that contains several functions and a variable. For functions or variables to be available from transformation scripts, they must be assigned to properties of the exports object that is available within the shared library:

/**
 * Remove trailing and leading whitespace from a string
 */
function trim(str) {
  return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
}
 
/**
 * Remove trailing whitespace from a string
 */
var removeTrailingWhitespace = function(str) {
  return str.replace(/\s\s*$/, '');
};
 
// This function will not be available to integration scripts because
// it is not included in the exports below
 function ltrim(str) {
  return str.replace(/^\s\s*/, '');
}
 
var EMPTY_STRING = '';
 
// Export a function by name
exports.trim = trim;
// Export a function that was assigned to a variable
exports.rtrim = removeTrailingWhitespace;
// Export a value
exports.EMPTY_STRING = EMPTY_STRING;
// Export a function without assigning to a variable
exports.isBlank = function(str) {
  return (str == null || trim(str) == EMPTY_STRING);
};
 

To use functions that are defined in a shared library in your transformation script, import the shared library using the require() function:

// Import the shared library by name (case-sensitive)
var StringUtils = require('String Utilities');
 
var data = JSON.parse(request.body);
 
// Reference exported functions and values using the variable
// returned from the require function
var targetName = StringUtils.trim(data.username);
if (StringUtils.isBlank(targetName)) {
  console.log("no username given");
  targetName = StringUtils.EMPTY_STRING;
}

You can also use the require() function to import shared libraries into another shared library. For more information on creating shared libraries, see Shared libraries.

Library names are case sensitive.

^ Back to top

 

 

Constants

Integration developers can use constants to help non-technical users manipulate variables within integration scripts. Constants can be defined and implemented within the scripts when the integration is created, and users can update the values for the constants without needing to edit the scripts.

For more information about creating and managing constants, see Constants.

The following examples illustrate how to reference a constant from within the transformation script:

// Access and log a constant
console.log(constants.constantName);
console.log(constants.NameOfConstant);
 
// Access and log a constant with a non-compatible name
console.log(constants["constant-name"]);
console.log(constants["Date and Time Constant"]);
 
// Log all constants
console.log(JSON.stringify(constants));
 
// Access a constant containing JSON information
var jsonobj = JSON.parse(constants.json);
console.log("Hello, " + jsonobj.firstname + " " + jsonobj.lastname);
 
// Access a constant containing XML 
var xmlobj = JXON.parse(constants.xml);
console.log(JSON.stringify(xmlobj));
 
// Evaluate the code within a constant
eval(constants.evaluableCode);

^ Back to top

 

 

XML manipulation

The Integration Builder includes the following libraries that allow you to manipulate XML payloads. These are pure-JavaScript libraries sourced from "npm" (the package manager for Node.js), and packaged for use by the Nashorn engine using "browserify".

Library Description
XMLUtils.DOMParser

This is an implementation of the W3C DOM parser specification. The source library is XMLDOM (https://github.com/jindw/xmldom).

The DOMParser is a low-level parser used by the JXON and xpath libraries below, but can also be used directly.

XMLUtils.xpath This library allows you to read values from an XML DOM using the xpath syntax. The source library is xpath (https://github.com/yaronn/xpath.js).
XMLUtils.JXON

This library can be used to convert an XML document object into a native JavaScript object for further manipulation. The source library is jxon (https://github.com/tyrasd/jxon).

The Integration Builder provides a simplifying wrapper object for XMLUtils.JXON that takes an XML-formatted string and returns a JavaScript object using a single method, parse.

The wrapper takes this:

var obj = XMLUtils.JXON.build(new XMLUtils.DOMParser().parseFromString(xml));
 

And allows you to do this:

var obj = JXON.parse(xml);
 

By default, JXON case-folds all tag and attribute names to lowercase. For example, both <username> and <USERNAME> would be converted to a property called username in the JavaScript. To retain the exact case of tags and attributes, enable the following option in the script prior to calling JXON.parse:

XMLUtils.JXON.config({'lowerCaseTags': false});

Examples

The following examples illustrate how to use the included libraries to manipulate incoming XML payloads.

Incoming XML Manipulation
<incident importance="High">
    <ticket>1234</ticket>
    <summary>Mail server is down</summary>
    <recipients>
        <username>bsmith</username>
        <username>mmcbride</username>
    </recipients>
</incident>

Using DOMParser

var xml = request.body;
 
var doc = new XMLUtils.DOMParser().parseFromString(xml);
 
trigger.properties['Incident ID'] = doc.getElementsByTagName("ticket")[0].firstChild.data;
 
trigger.properties.Summary = doc.getElementsByTagName("summary")[0].firstChild.data;
 
var recipients = [];
var recips = doc.getElementsByTagName("username");
for (var i = 0; i < recips.length; i++) {
    recipients.push({"targetName": recips.item(i).firstChild.data});
}
trigger.recipients = recipients;
 
trigger.priority = doc.getElementsByTagName("incident")[0].getAttribute("importance");
 
form.post(trigger);

Using xpath:

var str = request.body;
// Build the XML document from the request
var doc = new XMLUtils.DOMParser().parseFromString(str, 'text/xml');
 
// Get the ticket number
var ticket = XMLUtils.xpath.select('//ticket/text()', doc)[0].data;
trigger.properties['Incident ID'] = ticket;
console.log("Ticket: " + ticket);
 
// Get the summary
var summary = XMLUtils.xpath.select('//summary/text()', doc)[0].data;
trigger.properties.Summary = summary;
console.log("Summary: " + summary);
 
// Loop over the recipients objects
var recipients = XMLUtils.xpath.select('//recipients/username', doc);
for (var i in recipients) {
    var recipientUsername = recipients[i].firstChild.data;
    console.log("Adding recipient " + recipientUsername);
    trigger.addRecipient(recipientUsername);
}
 
// Get the priority
var importance = XMLUtils.xpath.select('//incident/@importance', doc)[0].value;
console.log("Priority: " + importance);
trigger.priority = importance;
 
// Post the trigger to the form
form.post(trigger);

Using JXON:

var xml = request.body;
var obj = JXON.parse(xml);
console.log(JSON.stringify(obj));
/* The following data gets logged:
{
    "incident": {
        "@importance": "High",
        "recipients": {
            "username": [
                "bsmith",
                "mmcbride"
            ]
        },
        "summary": "Mail server is down",
        "ticket": 1234    }
}
*/
var data = obj.incident;
trigger.properties['Incident ID'] = data.ticket;
trigger.properties.Summary = data.summary;
var recipients = [];
for (var i in data.recipients.username) {
    recipients.push({"targetName": data.recipients.username[i]});
}
trigger.recipients = recipients;
trigger.priority = data['@importance'];
form.post(trigger);
<soap:Envelope
 xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
 xmlns:sch="http://www.xmatters.com/webservices/schema#5.5.47">
   <soap:Header/>
   <soap:Body>
      <sch:AddEvent>
         <sch:user>user1010</sch:user>
         <sch:password>tester</sch:password>
         <sch:clientTimestamp xsi:nil="true"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
         <sch:clientIP xsi:nil="true"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
         <sch:clientOSUser xsi:nil="true"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
         <sch:company>mustafar</sch:company>
        <sch:eventTokens>
            <sch:eventToken>
               <sch:name>Incident ID</sch:name>
               <sch:value>12345</sch:value>
            </sch:eventToken>
            <sch:eventToken>
               <sch:name>Impact</sch:name>
               <sch:value>High</sch:value>
            </sch:eventToken>
            <sch:eventToken>
               <sch:name>Summary</sch:name>
               <sch:value>testing SOAP endpoint</sch:value>
            </sch:eventToken>
         </sch:eventTokens>
      </sch:AddEvent>
   </soap:Body>
</soap:Envelope>

Using xpath with namespace:

var doc = new XMLUtils.DOMParser().parseFromString(request.body);
var select = XMLUtils.xpath.useNamespaces({"sch": "http://www.xmatters.com/webservices/schema#5.5.47"});
var tokens = select('//sch:eventTokens/sch:eventToken', doc);
 
// Iterate the event tokens to build the form properties
for (var i in tokens) {
  var nameToken = select('sch:name/text()', tokens[i])[0].data;
  var valueToken = select('sch:value/text()', tokens[i])[0].data;
  console.log("Adding property: " + nameToken + " = " + valueToken);
  trigger.properties[nameToken] = valueToken;
}
 
// Extract the target name from the incoming request and add to the trigger
var targetName = select('//sch:user/text()', doc)[0].data;
console.log("Adding Recipients: " + targetName);
var recipients = [];
recipients.push({
    'targetName': targetName
});
trigger.recipients = recipients;
console.log(JSON.stringify(trigger));
 
// Post the form to xMatters
form.post(trigger);

^ Back to top