# 9.11 - Services Workbench - Knowledge Base

Services Workbench - Knowledge Base — Knowledge Base articles.

# Service Suite Knowledge Base Overview

# Service Suite Knowledge Base Overview

This overview organizes Service Suite knowledge base content for current AIQ service and API testing. Remove or consolidate articles that are empty, duplicate, or tied only to obsolete examples.

## Keep articles that explain

- Reusable Service Suite patterns.
- Request setup, response extraction, assertions, and validation.
- Approved dependency and package usage.
- Integration troubleshooting that applies to current AIQ releases.

## Maintenance rules

1. Use current product names such as Service Suite and Scenario Editor where applicable.
2. Do not include real secrets, tokens, tenant URLs, or customer-specific payloads.
3. Prefer concise workflows and validation checklists over long one-off examples.

**Last updated:** September 8, 2026

# Convert XML Request to JSON

This example details how to convert XML responses generated from a Services Workbench script to JSON and then back to XML using Designer `.js` scripts.

- Custom `.js` functions are written for the conversion of XML to JSON and JSON to XML. in javascript (.js) file.
- In a Services Workbench script, the response data is stored in locker so that it can be retrieved and used in Designer `.js` script.
- The Designer `.js` script includes the previous two files, and once the data is retrieved from locker, uses the custom `.js` function to parse the XML back to JSON and perform the required validations.
 
### XML to JSON Function

Converts XML to JSON and JSON to XML.

 ![](https://docs.appvance.net/uploads/images/gallery/2026-07/scaled-1680-/jJlUPPPOmJGyAhyU-6afec973314d.png)

#### Sample Script

<div class="codeSnippet" id="bkmrk-copy-xmltojson%26objto"><div class="codeSnippetCaption">XMLtoJSON&amp;ObjtoXML.js</div><div class="codeSnippetBody">```
/**<br></br> * @aiq.webdesigner<br></br> * This script requires AIQ Web Designer<br></br>*/<br></br>function jsonToXml(obj) {<br></br>    // create xml string<br></br>    var xml = '';//'<?xml version="1.0" encoding="UTF-8"?>';<br></br>    //loop through and add each property as a an xml tag as well as sub properties<br></br>    for (var prop in obj) {<br></br>        if (!obj.hasOwnProperty(prop)) {<br></br>            continue;<br></br>        }<br></br>        if (obj[prop] == undefined)<br></br>            continue;<br></br>        xml += "<" + prop + ">";<br></br>        if (typeof obj[prop] == "object")<br></br>            xml += jsonToXml(new Object(obj[prop]));<br></br>        else<br></br>            xml += convertXMLString(obj[prop], 'xml');<br></br>        xml += "</" + prop + ">";<br></br>    }<br></br>    // searches the string for numbers surrounded by underscores and removes them; used for multiple properties in the json that are set up an an object instead of an array<br></br>    let reducedXML = xml.replace(/([_]\d)\w+/g, '');<br></br>    return reducedXML;<br></br>}<br></br>function convertXMLString(input, outputFormat){<br></br>  if(typeof input === 'string'){<br></br>    if(outputFormat === 'xml'){<br></br>      return input.replace(/(&)/g, '&amp;').replace(/(<)/g, '&lt;').replace(/(>)/g, '&gt;').replace(/(')/g, '&apos;')<br></br>    } else if(outputFormat === 'string'){<br></br>      return input.replace(/(&lt;)/g, '<').replace(/(&gt;)/g, '>').replace(/(&apos;)/g, "'").replace(/(&amp;)/g, '&')<br></br>    } else {<br></br>      // invalid outputFormat<br></br>      return input;<br></br>    }<br></br>  } else {<br></br>    // not a stringF<br></br>    return input;<br></br>  }<br></br>}<br></br>function parseXmlToJson(xmlString) {<br></br>  let xmlToParse = xmlString.replace(/[\r\n']/g, match => match === "'" ? "\\'" : ' '); // Replce all the new line and single quote<br></br>  const json = evalAndReturn(`<br></br>    const parser = new DOMParser();<br></br>    const xml = parser.parseFromString('${xmlToParse}', "application/xml");<br></br>    if (xml.getElementsByTagName("parsererror").length) {<br></br>      return 'Error';<br></br>    }<br></br>    const parseXmlToJson = (xml) => {<br></br>      let obj = {};<br></br>      let nodeName = xml.nodeName.includes(":") ? xml.nodeName.split(":")[1] : xml.nodeName;<br></br>      if (xml.childNodes.length === 1 && xml.firstChild.nodeType === 3) {<br></br>          return xml.textContent.trim();<br></br>      }<br></br>      for (let child of xml.childNodes) {<br></br>          if (child.nodeType === 3 && !child.textContent.trim()) {<br></br>              continue; // Ignore whitespace text nodes<br></br>          }<br></br>          let childName = child.nodeName.includes(":") ? child.nodeName.split(":")[1] : child.nodeName;<br></br>          let childJson = parseXmlToJson(child);<br></br>          if (obj[childName]) {<br></br>              if (!Array.isArray(obj[childName])) {<br></br>                  obj[childName] = [obj[childName]];<br></br>              }<br></br>              obj[childName].push(childJson);<br></br>          } else {<br></br>              obj[childName] = childJson;<br></br>          }<br></br>      }<br></br>      return obj;<br></br>    }<br></br>    const jsonObj = parseXmlToJson(xml);<br></br>    return JSON.stringify(jsonObj);<br></br>  `)<br></br>  return json;<br></br>}
```

 </div> </div>### Services Workbench Script

The response data is stored in locker so that it can be retrieved and used in a Designer `.js` script.

 ![](https://docs.appvance.net/uploads/images/gallery/2026-07/scaled-1680-/Yh0NRuE1UM38T7ax-6e23cbf1f0a7.png)

#### Sample Script

<div class="codeSnippet" id="bkmrk-copy-xmljson.js-%2F%2A%2A%C2%A0"><div class="codeSnippetCaption">XMLJSON.js</div><div class="codeSnippetBody">```
/**<br></br> * @aiq.servicesworkbench<br></br> * This script requires Services Workbench<br></br>*/<br></br>var resp = get("https://mocktarget.apigee.net/xml");<br></br>var responseData = resp.getDataString();<br></br>//log(responseData);<br></br>locker.put("XMLData",responseData);
```

 </div> </div>### Designer Script

Includes the previous two scripts, and once the data is retrieved from locker, uses the custom `.js` function to parse the XML back to JSON and perform the required validations.

 ![](https://docs.appvance.net/uploads/images/gallery/2026-07/scaled-1680-/vm8dUdVCbrUO1nmK-17deffe04ac0.png)

#### Sample Script

<div class="codeSnippet" id="bkmrk-copy-testxmltojson.j"><div class="codeSnippetCaption">TestXMLtoJSON.js</div><div class="codeSnippetBody">```
<span class="codeSnippetLineNumbers" style="border-right:#AAA 2px solid;">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</span>```
/**<br></br> * @aiq.webdesigner<br></br> * This script requires AIQ Web Designer<br></br>*/<br></br>include("{ds}/XMLtoJSON&ObjtoXML.js");<br></br>serviceSuite('{ds}/XMLJSON.js');<br></br>var xmlString = retrieve("XMLData");<br></br>log(xmlString);<br></br>var jsondata = parseXmlToJson(xmlString);<br></br>log(jsondata);<br></br>log(JSON.parse(jsondata));<br></br>var jsonD = JSON.parse(jsondata);<br></br>log(jsonToXml(JSON.parse(jsondata)));<br></br>assertEquals("John",jsonD.root.firstName);
```
```

 </div> </div>- Lines 5 through 8 : Includes the common JavaScript and Service Workbench scripts. Retrieves the data from the locker and store in a variable.
- Lines 9 through 11 : Uses the `parseXmlToJson` function to convert the response XML to JSON string. Next line it can be parsed and converted to JSON object, from which validations can be performed by extracting the required data.
- Line 13 : JSON to XML conversion is done using the `JsonToXml` function.
 
### Resources : Sample Scripts

You can download the sample scripts from these links.

- [XMLtoJSON&amp;ObjtoXML.js](../../Resources/Scripts/XMLtoJSON&ObjtoXML.js)
- [XMLJSON.js](../../Resources/Scripts/XMLJSON.js)
- [TestXMLtoJSON.js](../../Resources/Scripts/TestXMLtoJSON.js)
 
<div id="bkmrk-last-updated%3A-march-">---

Last updated: <span class="mc-variable General.NewDateTimeVariable variable">March 04, 2025</span>

If you have any feedback on this topic, please contact us at <documentation@appvance.ai>

</div>

# How to add DPL reference in-service suite script vs Scenario

Using the below syntax we can run the DPL enabled script from the service suite as well as from the scenario editor without having to change anything from the code.

<div class="codeSnippet" id="bkmrk-copy-setvariablesifn"><div class="codeSnippetBody">```
setVariablesIfNeeded(<span style="color:#dd1144;">'{ds}/globalProperties.csv'</span>,<span style="color:#dd1144;">'HashDPL'</span>,<span style="color:#008080;">0</span>);
```

 </div> </div> ![](https://docs.appvance.net/uploads/images/gallery/2026-07/scaled-1680-/4MmGbgYy78RXLA6f-a1fcfac447c6.png)

<div id="bkmrk-last-updated%3A-june-0">---

Last updated: <span class="mc-variable General.NewDateTimeVariable variable">June 02, 2023</span>

If you have any feedback on this topic, please contact us at <documentation@appvance.ai>

</div>

# How to use Path Parameters in Service Suite?

Path parameters are dynamic values that are included directly in the URL path of an API endpoint.

In Service Suite, you can construct an endpoint URL using JavaScript string concatenation. This allows you to insert variables, such as a client number or customer ID, into the URL.

### Example

The following example uses the `<span class="editor-theme-code">$clientNumber</span>` variable as a path parameter in a POST request:

```javascript
var $clientNumber = getLoggedClientNumber(); // Or read the value from a CSV file

var $url = $server + "/customer/" + $clientNumber + "/reports";

var $payload = {
    "action": "listinvoices",
    "from": "10/01/2020"
};

var $response = post($url, $payload);

var $list = JSON.parse($response.getDataString());
```

### How it works

If `<span class="editor-theme-code">$server</span>` contains:

```text
https://example.com
```

and `<span class="editor-theme-code">$clientNumber</span>` contains:

```text
12345
```

the resulting URL will be:

```text
https://example.com/customer/12345/reports
```

In this example:

- `<span class="editor-theme-code">$server</span>` contains the base URL of the API.
- `<span class="editor-theme-code">$clientNumber</span>` contains the dynamic value used as the path parameter.
- `<span class="editor-theme-code">/customer/</span>` and `<span class="editor-theme-code">/reports</span>` are static parts of the endpoint path.
- `<span class="editor-theme-code">post()</span>` sends the request to the dynamically constructed URL.
- `<span class="editor-theme-code">JSON.parse()</span>` converts the response data into a JavaScript object.

### Using a CSV Value

The path parameter can also come from test data, such as a CSV file:

```javascript
var $clientNumber = $clientNumberFromCSV;

var $url = $server + "/customer/" + $clientNumber + "/reports";

var $response = post($url, $payload);
```

This approach allows the same Service Suite script to execute the request for different client numbers without changing the endpoint manually.

### Summary

Use JavaScript string concatenation when a value in the API endpoint needs to change dynamically during execution:

```javascript
var $url = $server + "/customer/" + $clientNumber + "/reports";
```

This is useful for endpoints that follow patterns such as:

```text
/customer/{clientNumber}/reports
/customer/{customerId}/invoices
/orders/{orderId}/details
```

---

**Last updated:** August 17, 2026

If you have any feedback on this topic, please contact us at <documentation@appvance.ai>.

# How to use Query Parameters in Service Suite?

Query parameters are values added to the URL after the `<span class="editor-theme-code">?</span>` character. They are commonly used to provide optional parameters or filters to an API request.

In Service Suite, you can construct a URL dynamically using JavaScript string concatenation and variables.

### Example

The following example uses `<span class="editor-theme-code">$clientNumber</span>` as a query parameter in a GET request. It also adds a timestamp as a cache-busting parameter:

```javascript
var $clientNumber = getLoggedClientNumber(); // Or read the value from a CSV file

var $url = $server + "/common/getClientData/?clientNumber=" + $clientNumber + "&_=" + Date.now();

var $response = get($url);

var $json = JSON.parse($response.getDataString());

var $clientNumber = $json.clientNumber;
```

### How it works

If `<span class="editor-theme-code">$server</span>` contains:

```text
https://example.com
```

and `<span class="editor-theme-code">$clientNumber</span>` contains:

```text
12345
```

the resulting URL will look similar to:

```text
https://example.com/common/getClientData/?clientNumber=12345&_=1750000000000
```

The URL contains two query parameters:

- `<span class="editor-theme-code">clientNumber=12345</span>` — passes the client number to the API.
- `<span class="editor-theme-code">_=</span>` followed by the current epoch time — adds a unique value to help prevent the request from being served from a cached response.

`<span class="editor-theme-code">Date.now()</span>` returns the current time in milliseconds since the Unix epoch.

### Multiple Query Parameters

When an endpoint requires multiple query parameters, use `<span class="editor-theme-code">?</span>` before the first parameter and `<span class="editor-theme-code">&</span>` before each additional parameter.

For example:

```javascript
var $url = $server + "/common/getClientData/?clientNumber=" + $clientNumber + "&status=active";
```

This produces a URL such as:

```text
https://example.com/common/getClientData/?clientNumber=12345&status=active
```

### Query Parameters vs. Path Parameters

A **path parameter** is part of the URL path:

```text
/customer/12345/reports
```

A **query parameter** is included after `<span class="editor-theme-code">?</span>`:

```text
/customer/reports?clientNumber=12345
```

The API determines which format should be used for each endpoint.

### Summary

Use JavaScript string concatenation to dynamically construct URLs containing query parameters:

```javascript
var $url = $server + "/common/getClientData/?clientNumber=" + $clientNumber;
```

When adding more than one query parameter, separate them with `<span class="editor-theme-code">&</span>`:

```javascript
var $url = $server + "/common/getClientData/?clientNumber=" + $clientNumber + "&status=active";
```

---

**Last updated:** August 1, 2026

If you have any feedback on this topic, please contact us at <documentation@appvance.ai>.

# How to get DPL data in the service suite?

The below code iterates on the columns and fetches the DPL data we want to use in the script.

 ![](https://docs.appvance.net/uploads/images/gallery/2026-07/scaled-1680-/NeHbnIgXpJAD1fba-ddd56d2d354a.png)

<div class="codeSnippet" id="bkmrk-copy-setvariablesifn"><div class="codeSnippetBody">```
setVariablesIfNeeded(<span style="color:#dd1144;">'test.csv'</span>,<span style="color:#dd1144;">'HashDPL'</span>,<span style="color:#008080;">0</span>,<span style="color:#dd1144;">'en_US'</span>);<br></br><span style="color:#333333;font-weight:bold;">var</span> Length = <span style="color:#008080;">5</span>;<br></br><span style="color:#333333;font-weight:bold;">for</span> (j=<span style="color:#008080;">1</span>; j<=Length; j++) {<br></br>  <span style="color:#333333;font-weight:bold;">var</span> val = <span style="color:#0086b3;">eval</span>(<span style="color:#dd1144;">"$Test"</span>+j);<br></br>  log(val);<br></br>}
```

 </div> </div>## Example Code

[test.csv](../../../Resources/Code%20Samples/DPL_Data_Service_Suite/test.csv)

<div id="bkmrk-last-updated%3A-june-0">---

Last updated: <span class="mc-variable General.NewDateTimeVariable variable">June 02, 2023</span>

If you have any feedback on this topic, please contact us at <documentation@appvance.ai>

</div>

# How to Validate API Responses in Service Suite

When executing API requests in Service Suite, you can validate the response to verify that the request was successful.

You can validate information from the response body, such as a success flag or message, as well as HTTP response properties such as the status code.

## Validate a Response Using JavaScript

The following example parses the response body and throws an error if the API indicates that the operation was not successful:

```javascript
var $response = post($url, $payload);

var $jsonList = JSON.parse($response.getDataString());

if ($jsonList.isSuccess !== "true") {
    throw "Call was not successful. Message: " + $jsonList.message;
}
```

In this example:

- `<span class="editor-theme-code">post()</span>` sends the request to the endpoint.
- `<span class="editor-theme-code">$response</span>` contains the HTTP response.
- `<span class="editor-theme-code">getDataString()</span>` retrieves the response body as a string.
- `<span class="editor-theme-code">JSON.parse()</span>` converts the JSON response into a JavaScript object.
- The `<span class="editor-theme-code">isSuccess</span>` property is checked to determine whether the API call was successful.
- If the call was unsuccessful, `<span class="editor-theme-code">throw</span>` stops the execution and displays the message returned by the API.

## Validate a Response Using `<span class="editor-theme-code">assertEquals</span>`

Instead of using an `<span class="editor-theme-code">if</span>` statement, you can use an assertion to validate a value in the response:

```javascript
var $response = post($url, $payload);

var $jsonList = JSON.parse($response.getDataString());

assertEquals($jsonList.isSuccess, "true");
```

The assertion fails if `<span class="editor-theme-code">isSuccess</span>` does not equal `<span class="editor-theme-code">"true"</span>`.

## Validate the HTTP Status Code

You can also validate the HTTP status code returned by the server:

```javascript
assertEquals($response.status, 200);
```

This verifies that the response status is `<span class="editor-theme-code">200</span>` (OK).

For example, you can combine a status-code validation with a response-body validation:

```javascript
var $response = post($url, $payload);

assertEquals($response.status, 200);

var $jsonList = JSON.parse($response.getDataString());

assertEquals($jsonList.isSuccess, "true");
```

This allows you to verify both:

1. The HTTP request returned the expected status code.
2. The API response body contains the expected result.

## Summary

Service Suite provides multiple ways to validate API responses:

- Use `<span class="editor-theme-code">throw</span>` when you want to stop execution with a custom error message.
- Use `<span class="editor-theme-code">assertEquals()</span>` to validate values returned in the response body.
- Use `<span class="editor-theme-code">$response.status</span>` to validate the HTTP status code returned by the server.

Using these validations helps ensure that API requests not only execute successfully but also return the expected results.

---

**Last updated:** September 1, 2026

If you have any feedback on this topic, please contact us at <documentation@appvance.ai>.

# How is the Request and response POJO management?

Internally when you call a createPost() command (or createGet, createOptions, etc), it returns an HttpRequest object. In the following snippet, the $call variable is an instance of an HttpRequest object that when processed will trigger a POST call:

<div id="bkmrk-copy-var-%24call-%3D-cre" style="border-width:1px;"><div><div class="codeSnippet"><div class="codeSnippetBody">```
<span style="color:#333333;font-weight:bold;">var</span> $call = createPost($url, $payload);<br></br><span style="color:#333333;font-weight:bold;">var</span> $call.addHeader(<span style="color:#dd1144;">"Authorization"</span>,<span style="color:#dd1144;">"Basic "</span>+$TOKEN);<br></br><span style="color:#333333;font-weight:bold;">var</span> $response = process($call);<br></br>log(<span style="color:#dd1144;">"Status: "</span>+$response.status);
```

 </div> </div> </div> </div>And the variable $response is an instance of an HTTPResponse object.

Some of the most commonly used properties and methods can be found in the following examples.

## HttpRequest

<div class="codeSnippet" id="bkmrk-copy-var-%24data-%3D-%7B-%22"><div class="codeSnippetBody">```
<span style="color:#333333;font-weight:bold;">var</span> $data = { <span style="color:#dd1144;">"some"</span>:<span style="color:#dd1144;">"data"</span>};<br></br><span style="color:#333333;font-weight:bold;">var</span> $call = createPost(<span style="color:#dd1144;">"https://www.apple.com"</span>,$data);<br></br>$call.addHeader(<span style="color:#dd1144;">"someheader"</span>,<span style="color:#dd1144;">"somevalue"</span>);<br></br>log($call.getHeader(<span style="color:#dd1144;">"content-type"</span>));<br></br>log($call.postMimeType());<br></br>log($response.recreateHeader());  <span style="color:#999988;font-style:italic;">// returns request headers raw text</span><br></br>log($call.url());<br></br>log($call.contentLength());<br></br>log($call.getDataString());
```

 </div> </div>## HttpResponse

<div class="codeSnippet" id="bkmrk-copy-var-%24response-%3D"><div class="codeSnippetBody">```
<span style="color:#333333;font-weight:bold;">var</span> $response =get(<span style="color:#dd1144;">"http://worldclockapi.com/api/json/est/now"</span>);<br></br>log($response.status);       <span style="color:#999988;font-style:italic;">// 200</span><br></br>log($response.statusText);   <span style="color:#999988;font-style:italic;">// OK</span><br></br>log($response.getDataString());<br></br>log($response.getHeader(<span style="color:#dd1144;">"Server"</span>));<br></br>log($response.recreateHeader());  <span style="color:#999988;font-style:italic;">// returns response headers raw text</span><br></br>log($response.getResponseType()); <span style="color:#999988;font-style:italic;">// JSON</span><br></br>log($response.contentLength());<br></br>log($response.isBasic());<br></br>log($response.isNTLM());<br></br>log($response.isNegotiate());
```

 </div> </div><div id="bkmrk-" style="border-width:1px;"><div> </div> </div><div id="bkmrk-last-updated%3A-june-0">---

Last updated: <span class="mc-variable General.NewDateTimeVariable variable">June 02, 2023</span>

If you have any feedback on this topic, please contact us at <documentation@appvance.ai>

</div>

# How to validate status code that is returned in response header

If we want to validate the status code that is returned in the response header we can use the below approach.

<div class="codeSnippet" id="bkmrk-copy-var-%24response-%3D"><div class="codeSnippetBody">```
<span style="color:#333333;font-weight:bold;">var</span> $response = post($url, $payload );<br></br>assertEquals($response.status, <span style="color:#008080;">200</span>);
```

 </div> </div><div id="bkmrk-" style="border-width:1px;"><div> </div> </div><div id="bkmrk-last-updated%3A-june-0">---

Last updated: <span class="mc-variable General.NewDateTimeVariable variable">June 02, 2023</span>

If you have any feedback on this topic, please contact us at <documentation@appvance.ai>

</div>

# How to read specific row in service suite from CSV?

By providing the number after the csv, Service suite should be able to read from the specific row.

HashDPL(“{mds}/data/data.csv”,1);

<div id="bkmrk-last-updated%3A-februa">---

Last updated: <span class="mc-variable General.NewDateTimeVariable variable">February 17, 2023</span>

If you have any feedback on this topic, please contact us at <documentation@appvance.ai>

</div>

# Reading data from JSON/XML from Service Suite

You can read JSON data from a file and convert it into a JavaScript object using the following example:

```javascript
// Read the JSON file and convert its contents to a string.
var $aJsonString = new java.lang.String(
    readBytes("{mds}/somejsonfile.json")
);

// Parse the JSON string into a JavaScript object.
var jsonObj = JSON.parse($aJsonString);
```

The example performs two steps:

1. **Read the file:** `<span class="editor-theme-code">readBytes()</span>` reads the contents of the JSON file. The contents are converted to a Java `<span class="editor-theme-code">String</span>`.
2. **Parse the JSON:** `<span class="editor-theme-code">JSON.parse()</span>` converts the JSON string into a JavaScript object, allowing you to access individual values from the JSON data.

For example, if the JSON file contains:

```json
{
  "username": "mauricio",
  "environment": "QA"
}
```

You can access its values through the resulting object:

```javascript
log(jsonObj.username);
log(jsonObj.environment);
```

This produces:

```text
mauricio
QA
```

---

**Last updated:** August 13, 2026

If you have any feedback on this topic, please contact us at <documentation@appvance.ai>.

# How to add transaction names in Service Suite

You can use the `<span class="editor-theme-code">startStep()</span>` API to assign a descriptive name to a transaction or step in a Service Suite script. The transaction name is then displayed in the execution reports, making it easier to identify and analyze individual transactions.

### Example

The following example assigns the transaction name **"Open web page API simulation"** before executing the request:

```javascript
addGlobalHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36");

addGlobalHeader("cache-control", "no-cache");

startStep("Open web page API simulation");

var resp = open("https://www.apple.com");
```

### How it works

- `<span class="editor-theme-code">startStep("Open web page API simulation")</span>` starts a named transaction/step.
- The string passed to `<span class="editor-theme-code">startStep()</span>` is used as the transaction name in the reports.
- The `<span class="editor-theme-code">open()</span>` call executes the request associated with that transaction.

You can replace the transaction name with any meaningful description that helps identify the operation being measured.

For example:

```javascript
startStep("Login API");

var resp = open("https://example.com/login");
```

This allows the transaction to be easily identified as **"Login API"** in the corresponding reports.

---

**Last updated:** August 17, 2026

If you have any feedback on this topic, please contact us at <documentation@appvance.ai>.

# Generating thousands/millions of rows of Synthetic DPL data using Rest APIs

Below is the Service Suite script that can be used to generate synthetic data using Rest APIs, this would be useful when generating millions of data which might be difficult using the UI as UI will have its own limitations.

Start AIQ

Go to Service Suite

API editor

Open the below script

modify the quantity variable to 1000000 (or as desired)

Save and run

a file with 1000000 will be created.

Note: There are 2 parameters that might be required to change.

1. AIQ URL (Line 1) - `var $baseURL = "http://localhost:8080";`
2. Creds (Line 12 and 13) - Username and password.
 
<div class="codeSnippet" id="bkmrk-copy-var-%24baseurl-%3D-"><div class="codeSnippetBody">```
<span style="color:#333333;font-weight:bold;">var</span> $baseURL = <span style="color:#dd1144;">"http://localhost:8080"</span>;<br></br><br></br><span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">getTimestamp</span>() {<br></br>    <span style="color:#333333;font-weight:bold;">return</span> (<span style="color:#333333;font-weight:bold;">new</span> <span style="color:#0086b3;">Date</span>()).getTime();<br></br>}<br></br><br></br><span style="color:#999988;font-style:italic;">//</span><br></br><span style="color:#999988;font-style:italic;">// LOGIN</span><br></br><span style="color:#999988;font-style:italic;">//</span><br></br><span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">login</span>($baseURL) {<br></br>    <span style="color:#333333;font-weight:bold;">var</span> $loginForm = formData();<br></br>    $loginForm.put(<span style="color:#dd1144;">"username"</span>, <span style="color:#dd1144;">"appvance"</span>);<br></br>    $loginForm.put(<span style="color:#dd1144;">"password"</span>, <span style="color:#dd1144;">"appvance"</span>);<br></br>    <span style="color:#333333;font-weight:bold;">var</span> $call = createPost($baseURL + <span style="color:#dd1144;">"/AppvanceServer/rest/admin/logginForServices"</span>, $loginForm);<br></br>    <span style="color:#333333;font-weight:bold;">var</span> $resp = process($call).getDataString();<br></br>    <span style="color:#333333;font-weight:bold;">if</span> ($resp.indexOf(<span style="color:#dd1144;">"true"</span>) != <span style="color:#008080;">-1</span>) {<br></br>        <span style="color:#999988;font-style:italic;">//</span><br></br>        <span style="color:#999988;font-style:italic;">// GET JSESSIONID COOKIE</span><br></br>        <span style="color:#999988;font-style:italic;">//</span><br></br>        <span style="color:#333333;font-weight:bold;">var</span> $jsession = getCookieValue($baseURL, <span style="color:#dd1144;">"JSESSIONID"</span>);<br></br>        addGlobalHeader(<span style="color:#dd1144;">"cookie"</span>, <span style="color:#dd1144;">"JSESSION = "</span> + $jsession);<br></br>        log(<span style="color:#dd1144;">"Login successful, JSESSION:"</span> + $jsession)<br></br>        <span style="color:#333333;font-weight:bold;">return</span> <span style="color:#008080;">true</span>;<br></br>    } <span style="color:#333333;font-weight:bold;">else</span> {<br></br>        <span style="color:#333333;font-weight:bold;">return</span> <span style="color:#008080;">false</span>;<br></br>    }<br></br>}<br></br><br></br><span style="color:#333333;font-weight:bold;">var</span> $resp = login($baseURL);<br></br><span style="color:#333333;font-weight:bold;">var</span> quantity = <span style="color:#008080;">100000</span>;<br></br><span style="color:#333333;font-weight:bold;">var</span> fileName = <span style="color:#dd1144;">"REPOSITORY/HOME/DPL.csv"</span>;<br></br><br></br><span style="color:#333333;font-weight:bold;">if</span> ($resp === <span style="color:#008080;">true</span>) {<br></br><br></br>    log(<span style="color:#dd1144;">"Is Logged"</span>);<br></br>    <span style="color:#333333;font-weight:bold;">var</span> data = [[<span style="color:#dd1144;">"qty"</span>, <span style="color:#dd1144;">"test"</span>],[<span style="color:#dd1144;">"syn.random.number(10)"</span>,<span style="color:#dd1144;">"syn.random.number(100)"</span>]];<br></br>    <span style="color:#333333;font-weight:bold;">var</span> call = createPost($baseURL + <span style="color:#dd1144;">"/AppvanceServer/rest/syntheticDPL/evaluate?lines="</span>+quantity+<span style="color:#dd1144;">"&locale=en_US"</span>, data);<br></br>    <span style="color:#333333;font-weight:bold;">var</span> stringJson = process(call).getDataString();  <br></br>    <span style="color:#333333;font-weight:bold;">var</span> payload = <span style="color:#0086b3;">JSON</span>.parse(stringJson.replace(/\n|\r/g, <span style="color:#dd1144;">""</span>).trim());<br></br>    <span style="color:#333333;font-weight:bold;">var</span> callSave = createPost($baseURL + <span style="color:#dd1144;">'/AppvanceServer/rest/file/updateCSVFile?commitMessage=&path='</span> + fileName, payload);    <br></br>    <span style="color:#333333;font-weight:bold;">var</span> stringJsonSave = process(callSave).getDataString();  <br></br>    <span style="color:#333333;font-weight:bold;">var</span> response = <span style="color:#0086b3;">JSON</span>.parse(stringJsonSave);<br></br>    log(fileName + <span style="color:#dd1144;">" was saved: "</span> + response.status); <br></br>}<br></br><span style="color:#999988;font-style:italic;">//</span><br></br><span style="color:#999988;font-style:italic;">// LOGOUT</span><br></br><span style="color:#999988;font-style:italic;">//</span><br></br><span style="color:#333333;font-weight:bold;">var</span> $resp = get($baseURL + <span style="color:#dd1144;">"/AppvanceServer/rest/admin/logout"</span>);<br></br>log(<span style="color:#dd1144;">"logout: "</span> + $resp.getDataString());
```

 </div> </div><div id="bkmrk-" style="border-width:1px;"><div> </div> </div><div id="bkmrk-last-updated%3A-june-0">---

Last updated: <span class="mc-variable General.NewDateTimeVariable variable">June 02, 2023</span>

If you have any feedback on this topic, please contact us at <documentation@appvance.ai>

</div>

# Run Approved OS Commands from Service Suite

**Last reviewed:** September 30, 2026

Use this article only when a Service Suite scenario must run an approved operating-system command through AIQ in a controlled execution environment.

## What changed in this article

- Reframed command-prompt execution as a controlled Service Suite capability instead of a general command-running shortcut.
- Added security checks for command allowlisting, execution host, working directory, quoting, secrets handling, stdout/stderr review, timeout behavior, and least-privilege permissions.
- Removed unsafe sample-command emphasis and replaced it with validation guidance that avoids encouraging arbitrary local command execution.

## Validation workflow

1. Confirm the command is approved for the target AIQ environment and cannot expose credentials or modify unintended files.
2. Validate the working directory, arguments, permissions, expected output, timeout, and failure behavior in a non-production run.
3. Review stdout, stderr, exit status, and Service Suite logs before using the command in a scheduled or shared workflow.

**Review note:** This page is now intentionally cautious because OS command execution can affect the execution host.

---

Last updated: September 30, 2026

If you have feedback on this topic, contact <documentation@appvance.ai>.

# Validate CAPTCHA Text Capture in Approved Test Environments

# Validate CAPTCHA Text Capture in Approved Test Environments

Use this article only for approved test environments where CAPTCHA images are provided as controlled test fixtures. Do not use AIQ automation to bypass CAPTCHA or defeat anti-bot protections on production systems.

## Safe testing approach

- Use a sandbox CAPTCHA, static fixture, or customer-approved test mode.
- Validate OCR or text-extraction behavior only when the CAPTCHA provider and application owner permit it.
- Keep expected values in test data, not in production user flows.
- Record whether the test is validating OCR quality, application handling, or a downstream business rule.
- Use Service Suite or Scenario Editor assertions to verify the expected result without weakening real security controls.

## Validation workflow

1. Confirm written approval or documented test-mode support for the CAPTCHA scenario.
2. Run the test with a known fixture and expected extracted value.
3. Validate success and failure behavior separately.
4. Review logs to ensure no real user credentials, session data, or sensitive images are captured.

**Security note:** CAPTCHA is a security control. This content must not be used as a guide for bypassing CAPTCHA on live systems.

*Last updated: October 8, 2026*

# Gmail App Password Use in Service Suite Tests

**Last reviewed:** September 24, 2026

This legacy article applies only when a Google account is explicitly allowed to use app passwords for automated Service Suite mail validation.

## What changed in this article

- Prefer Gmail API/OAuth or an approved test-mail service for current implementations.
- Use a dedicated test account; do not automate a personal mailbox or production user account.
- Treat the app password as a secret and remove it from logs, screenshots, exported results, and sample code.

## Validation workflow

1. Confirm that the Google Workspace policy permits app passwords for the selected test account.
2. Create the password outside AIQ and store it only in the approved secret manager.
3. Run the Service Suite script with a small mailbox test and verify no secret value appears in output.

**Review note:** Marked the Gmail app-password flow as legacy/security-sensitive and added OAuth/test-mail alternatives.

---

Last updated: September 24, 2026

If you have feedback on this topic, contact <documentation@appvance.ai>.

# Outlook App Password Use in Service Suite Tests

**Last reviewed:** September 24, 2026

This legacy article applies only when an Outlook or Microsoft 365 account still allows app passwords for automated Service Suite login flows.

## What changed in this article

- Prefer Microsoft Graph, OAuth, or an approved test-mail API when available; app passwords should not be the default recommendation.
- Never store the app password in the article, screenshots, source control, or reusable sample scripts.
- Use a dedicated test mailbox and rotate the app password according to the customer security policy.

## Validation workflow

1. Confirm with the Microsoft 365 administrator that app passwords are allowed for the tenant and test account.
2. Generate the app password outside AIQ and store it only in the approved secret location.
3. Run the Service Suite script against a non-production mailbox and remove any captured secret from logs.

**Review note:** Marked the Outlook app-password approach as legacy/security-sensitive and replaced the long title with a concise scope-focused title.

---

Last updated: September 24, 2026

If you have feedback on this topic, contact <documentation@appvance.ai>.

# Validating Emails using Service Suite Scripts

1. Create a Script in Service suite as shown below:
    
     ![](https://docs.appvance.net/uploads/images/gallery/2026-07/scaled-1680-/Ut7KUVbVwYyBR4fe-f665db7dcdc9.png)
2. Please refer the below document if the outlook account as 2FA authentication:
    
    [How to create an App Password for an Outlook account and use in service suite script to login to account with 2FA enabled. ](/books/services-workbench-knowledge-base/page/create-an-app-password-for-an-outlook-account-and-use-in-service-suite-script-to-login-to-account-with-2fa-enabled)
 
Note: Below is the spec on AIQ mail client

### Mail Client

&gt;createMailClient(String host, String userMail, String password, String protocol)

returns a MailService object.

&gt;MailService object has the following available methods:

- login()
- setFromFolder(String:folder)
- logout()
- getLastUnreadMessages(int:quantity)
- getAllRecipients();
- getFrom();
- message.getSentDate();
- message.getFolder()
- MailMessage byte\[\] getAttachedFile(String fileName)
 
· List&lt;String&gt; getAttachments() //You can get a list with all the names of the attachments from a MailMessage and you can get the file (byte\[\]) using the file name.

### Sample code snippet

<div class="codeSnippet" id="bkmrk-copy-var-mailclient-"><div class="codeSnippetBody">```
var mailClient = <span style="color:#795da3;">createMailClient</span><span style="color:#000000;">(</span><span style="color:#df5000;">"imap.gmail.com"</span><span style="color:#000000;">,</span> <span style="color:#df5000;">"myEmail@gmail.com"</span><span style="color:#000000;">,</span> <span style="color:#df5000;">"App Password"</span><span style="color:#000000;">,</span> <span style="color:#df5000;">"IMAP"</span><span style="color:#000000;">)</span>;<br></br><br></br><span style="color:#0086b3;font-weight:bold;">try</span><span style="color:#000000;">{</span><br></br>  mailClient<span style="color:#000000;">.</span><span style="color:#795da3;">login</span><span style="color:#000000;">()</span>;<br></br><span style="color:#000000;">}</span><br></br><span style="color:#0086b3;font-weight:bold;">catch</span> <span style="color:#000000;">(</span>e<span style="color:#000000;">){</span><br></br>  mailClient<span style="color:#000000;">.</span><span style="color:#795da3;">login</span><span style="color:#000000;">()</span>;<br></br><span style="color:#000000;">}</span><br></br><span style="color:#795da3;">log</span><span style="color:#000000;">(</span><span style="color:#df5000;">"Login Outlook Account"</span><span style="color:#000000;">)</span>;<br></br>mailClient<span style="color:#000000;">.</span><span style="color:#795da3;">setFromFolder</span><span style="color:#000000;">(</span><span style="color:#df5000;">"Inbox"</span><span style="color:#000000;">)</span>;<br></br><span style="color:#795da3;">log</span><span style="color:#000000;">(</span><span style="color:#df5000;">"Navigate to the Inbox folder"</span><span style="color:#000000;">)</span>;<br></br><span style="color:#969896;">//mailClient.setFromFolder("Junk Email");</span><br></br><br></br>var lastUnreadMails = mailClient<span style="color:#000000;">.</span><span style="color:#795da3;">getLastUnreadMessages</span><span style="color:#000000;">(</span><span style="color:#008080;">5</span><span style="color:#000000;">)</span>;<br></br>var url;<br></br>var attachments;<br></br><br></br><span style="color:#969896;">//log(lastUnreadMails.size());</span><br></br><br></br><span style="color:#a71d5d;font-weight:bold;">for</span><span style="color:#000000;">(</span>var i = <span style="color:#008080;">0</span>; i <span style="color:#000000;"><</span> lastUnreadMails<span style="color:#000000;">.</span><span style="color:#795da3;">size</span><span style="color:#000000;">()</span>; i<span style="color:#000000;">++){</span><br></br>  <span style="color:#a71d5d;font-weight:bold;">if</span><span style="color:#000000;">(</span>lastUnreadMails<span style="color:#000000;">.</span><span style="color:#795da3;">get</span><span style="color:#000000;">(</span>i<span style="color:#000000;">).</span> <span style="color:#795da3;">getFrom</span><span style="color:#000000;">().</span>  <span style="color:#795da3;">contains</span><span style="color:#000000;">(</span><span style="color:#df5000;">"Appvance"</span><span style="color:#000000;">)){</span><br></br>      <span style="color:#795da3;">log</span><span style="color:#000000;">(</span><span style="color:#df5000;">"Fetch the url from this subject"</span> <span style="color:#000000;">+</span> lastUnreadMails<span style="color:#000000;">.</span><span style="color:#795da3;">get</span><span style="color:#000000;">(</span>i<span style="color:#000000;">).</span><span style="color:#795da3;">getSubject</span><span style="color:#000000;">())</span>;<br></br>      <span style="color:#795da3;">log</span><span style="color:#000000;">(</span><span style="color:#df5000;">"From "</span><span style="color:#000000;">+</span>lastUnreadMails<span style="color:#000000;">.</span><span style="color:#795da3;">get</span><span style="color:#000000;">(</span>i<span style="color:#000000;">).</span><span style="color:#795da3;">getFrom</span><span style="color:#000000;">())</span>;  <br></br>      <span style="color:#795da3;">log</span><span style="color:#000000;">(</span><span style="color:#df5000;">"Date "</span><span style="color:#000000;">+</span>lastUnreadMails<span style="color:#000000;">.</span><span style="color:#795da3;">get</span><span style="color:#000000;">(</span>i<span style="color:#000000;">).</span><span style="color:#795da3;">getSentDate</span><span style="color:#000000;">())</span>;<br></br>      <span style="color:#795da3;">log</span><span style="color:#000000;">(</span><span style="color:#df5000;">"Folder "</span><span style="color:#000000;">+</span>lastUnreadMails<span style="color:#000000;">.</span><span style="color:#795da3;">get</span><span style="color:#000000;">(</span>i<span style="color:#000000;">).</span><span style="color:#795da3;">getFolder</span><span style="color:#000000;">())</span>;<br></br>      <span style="color:#795da3;">log</span><span style="color:#000000;">(</span><span style="color:#df5000;">"getRecipients "</span><span style="color:#000000;">+</span>lastUnreadMails<span style="color:#000000;">.</span><span style="color:#795da3;">get</span><span style="color:#000000;">(</span>i<span style="color:#000000;">).</span><span style="color:#795da3;">getRecipients</span><span style="color:#000000;">())</span>;<br></br>      <span style="color:#795da3;">log</span><span style="color:#000000;">(</span><span style="color:#df5000;">"Fetch the url from this body"</span> <span style="color:#000000;">+</span> lastUnreadMails<span style="color:#000000;">.</span><span style="color:#795da3;">get</span><span style="color:#000000;">(</span>i<span style="color:#000000;">).</span><span style="color:#795da3;">getBody</span><span style="color:#000000;">())</span>;<br></br>      attachments = lastUnreadMails<span style="color:#000000;">.</span><span style="color:#795da3;">get</span><span style="color:#000000;">(</span>i<span style="color:#000000;">).</span><span style="color:#795da3;">getAttachments</span><span style="color:#000000;">()</span>;<br></br>      <span style="color:#a71d5d;font-weight:bold;">for</span><span style="color:#000000;">(</span>var j = <span style="color:#008080;">0</span>; j <span style="color:#000000;"><</span> attachments<span style="color:#000000;">.</span><span style="color:#795da3;">size</span><span style="color:#000000;">()</span>; j<span style="color:#000000;">++){</span><br></br>          <span style="color:#795da3;">log</span><span style="color:#000000;">(</span><span style="color:#df5000;">"Attachment name: "</span><span style="color:#000000;">+</span>attachments<span style="color:#000000;">.</span><span style="color:#795da3;">get</span><span style="color:#000000;">(</span>j<span style="color:#000000;">))</span>;<br></br>          var bytes =  lastUnreadMails<span style="color:#000000;">.</span><span style="color:#795da3;">get</span><span style="color:#000000;">(</span>i<span style="color:#000000;">).</span><span style="color:#795da3;">getAttachedFile</span><span style="color:#000000;">(</span>attachments<span style="color:#000000;">.</span><span style="color:#795da3;">get</span><span style="color:#000000;">(</span>j<span style="color:#000000;">))</span>;<br></br>          locker<span style="color:#000000;">.</span><span style="color:#795da3;">put</span><span style="color:#000000;">(</span><span style="color:#df5000;">"bytes"</span><span style="color:#000000;">,</span>bytes<span style="color:#000000;">)</span>;<br></br>          <span style="color:#795da3;">writeBytes</span><span style="color:#000000;">(</span><span style="color:#df5000;">"newBytes.pdf"</span><span style="color:#000000;">,</span> bytes<span style="color:#000000;">)</span>;<br></br>      <span style="color:#000000;">}</span><br></br>    <span style="color:#969896;">//code = urlify(lastUnreadMails.get(i).getBody());</span><br></br>  <span style="color:#000000;">}</span><br></br> <span style="color:#969896;">// log("Fetch the url from this body" + lastUnreadMails.get(i).getSubject());</span><br></br><span style="color:#000000;">}</span><br></br>mailClient<span style="color:#000000;">.</span><span style="color:#795da3;">logout</span><span style="color:#000000;">()</span>;
```

 </div> </div>Note: Replace the valid Email account to test the above methods.

### Outlook Sample

<div class="codeSnippet" id="bkmrk-copy-var-mailclient--1"><div class="codeSnippetBody">```
var mailClient = <span style="color:#795da3;">createMailClient</span><span style="color:#000000;">(</span><span style="color:#df5000;">"imap.outlook.com"</span><span style="color:#000000;">,</span> <span style="color:#df5000;">"aiqtest@outlook.com"</span><span style="color:#000000;">,</span> <span style="color:#df5000;">"password"</span><span style="color:#000000;">,</span> <span style="color:#df5000;">"IMAP"</span><span style="color:#000000;">)</span>;<br></br><br></br>mailClient<span style="color:#000000;">.</span><span style="color:#795da3;">login</span><span style="color:#000000;">()</span>;<br></br><br></br>mailClient<span style="color:#000000;">.</span><span style="color:#795da3;">setFromFolder</span><span style="color:#000000;">(</span><span style="color:#df5000;">"Inbox"</span><span style="color:#000000;">)</span>;<br></br><br></br>var lastUnreadMails = mailClient<span style="color:#000000;">.</span><span style="color:#795da3;">getLastUnreadMessages</span><span style="color:#000000;">(</span><span style="color:#008080;">1</span><span style="color:#000000;">)</span>;<br></br><br></br>var url = <span style="color:#df5000;">""</span>;<br></br><br></br>var from=lastUnreadMails<span style="color:#000000;">.</span><span style="color:#795da3;">get</span><span style="color:#000000;">(</span><span style="color:#008080;">0</span><span style="color:#000000;">).</span><span style="color:#795da3;">getFrom</span><span style="color:#000000;">().</span><span style="color:#795da3;">contains</span><span style="color:#000000;">(</span><span style="color:#df5000;">"Appvance"</span><span style="color:#000000;">)</span>;<br></br><br></br><span style="color:#795da3;">log</span><span style="color:#000000;">(</span>from<span style="color:#000000;">)</span>;
```

 </div> </div><div id="bkmrk-last-updated%3A-june-0">---

Last updated: <span class="mc-variable General.NewDateTimeVariable variable">June 02, 2023</span>

If you have any feedback on this topic, please contact us at <documentation@appvance.ai>

</div>

# Microsoft Graph: Send, Read, Reply, and Delete Email in Service Suite

# Microsoft Graph: Send, Read, Reply, and Delete Email in Service Suite

Use this article when a Service Suite workflow needs to validate Microsoft Graph email operations in an approved test mailbox. Do not run destructive email actions against real customer or employee mailboxes unless the customer has explicitly approved the test.

## Configuration checklist

- Use a dedicated test mailbox and a Microsoft Entra ID app registration approved for the workflow.
- Grant only the Graph permissions required for send, read, reply, or delete operations.
- Store client secrets, certificates, or tokens in secured variables or an approved secret store.
- Use test subjects, correlation IDs, or message metadata so the workflow finds the correct email.
- Separate read-only validation from delete or cleanup steps.

## Validation workflow

1. Confirm token acquisition and Graph endpoint access with the test mailbox.
2. Send or locate a controlled test message.
3. Validate the response status, message ID, subject, recipient, and body fields needed by the test.
4. Reply or delete only the controlled message created for the test run.
5. Review logs to confirm secrets and message content are not exposed unnecessarily.

*Last updated: October 8, 2026*

# Sample Service Suite Scripts

Here are some Service Suite samples scripts that can be used as a reference.

### Basic Authentication

<div class="code panel pdl conf-macro output-block" id="bkmrk-copy-%2F%2A%2A%C2%A0%2A-btoa%C2%A0%2A-%40p" style="border-width:1px;"><div class="codeContent panelContent pdl">```

```

<div class="codeSnippet"><div class="codeSnippetBody">```
<span style="color:#999988;font-style:italic;">/**</span><br></br><span style="color:#999988;font-style:italic;"> * btoa</span><br></br><span style="color:#999988;font-style:italic;"> * @param st</span> <br></br><span style="color:#999988;font-style:italic;"> * @returns base64 encoded string</span><br></br><span style="color:#999988;font-style:italic;"> */</span><br></br> <span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">btoa</span>(st) {<br></br>    <span style="color:#333333;font-weight:bold;">return</span> Java.type(<span style="color:#dd1144;">"java.util.Base64"</span>).getEncoder().encode(st);<br></br>}<br></br><br></br><span style="color:#333333;font-weight:bold;">var</span> $username = <span style="color:#dd1144;">"admin"</span>;<br></br><span style="color:#333333;font-weight:bold;">var</span> $password = <span style="color:#dd1144;">"Password@1"</span>;<br></br><span style="color:#333333;font-weight:bold;">var</span> $TOKEN = <span style="color:#dd1144;">"Basic "</span>+btoa($username+<span style="color:#dd1144;">":"</span>+$password);<br></br><br></br>addGlobalHeader(<span style="color:#dd1144;">"authorization"</span>, $TOKEN);<br></br><br></br><span style="color:#333333;font-weight:bold;">var</span> url = <span style="color:#dd1144;">"https://someServer.com/api/somecall"</span>;<br></br><span style="color:#333333;font-weight:bold;">var</span> data = {<span style="color:#dd1144;">"short_description"</span>:<span style="color:#dd1144;">"some data"</span>,<br></br>    <span style="color:#dd1144;">"description"</span>:<span style="color:#dd1144;">"some description"</span>};<br></br><br></br><span style="color:#333333;font-weight:bold;">var</span> call = createPost(url, data);<br></br>call.addHeader(<span style="color:#dd1144;">"Content-Type"</span>, <span style="color:#dd1144;">"application/json"</span>);<br></br><br></br><span style="color:#333333;font-weight:bold;">var</span> resp = process(call);
```

 </div> </div>```

```

 </div> </div>### Demosite

<div class="codeSnippet" id="bkmrk-copy-var-formpage-%3D-"><div class="codeSnippetBody">```
<span style="color:#333333;font-weight:bold;">var</span> formPage = get(<span style="color:#dd1144;">"https://demosite.appvance.com/products/ruby-on-rails-tote"</span>);<br></br>log(getCookies(<span style="color:#dd1144;">"https://demosite.appvance.com/"</span>));<br></br><span style="color:#333333;font-weight:bold;">var</span> token = extract(<span style="color:#dd1144;">"html"</span>,formPage,<span style="color:#dd1144;">'//form[@action="/orders/populate"]/input[@name="authenticity_token"]/@value'</span>);<br></br>log(<span style="color:#dd1144;">"Extracted token: "</span>+token);<br></br> <br></br><span style="color:#333333;font-weight:bold;">var</span> form = formData();<br></br>form.put(<span style="color:#dd1144;">"authenticity_token"</span>,token);<br></br>form.put(<span style="color:#dd1144;">"utf-8"</span>,<span style="color:#0086b3;">decodeURIComponent</span>(<span style="color:#dd1144;">"%E2%9C%93"</span>));<br></br>form.put(<span style="color:#dd1144;">"variant_id"</span>,<span style="color:#dd1144;">"1"</span>);<br></br>form.put(<span style="color:#dd1144;">"quantity"</span>,<span style="color:#dd1144;">"1"</span>);<br></br>form.put(<span style="color:#dd1144;">"button"</span>,<span style="color:#dd1144;">""</span>);<br></br> <br></br><span style="color:#333333;font-weight:bold;">var</span> postData = createPost(<span style="color:#dd1144;">"https://demosite.appvance.com/orders/populate"</span>,form);<br></br><span style="color:#333333;font-weight:bold;">var</span> purchaseResults = process(postData);<br></br> <br></br>log(<span style="color:#dd1144;">"response:\n"</span>+purchaseResults.getDataString());<br></br> <br></br>assertContains(get(<span style="color:#dd1144;">"https://demosite.appvance.com/cart?variant_id=1"</span>).getDataString(),<span style="color:#dd1144;">"Ruby on Rails Tote"</span>);<br></br>assertContains(get(<span style="color:#dd1144;">"https://demosite.appvance.com/cart_link"</span>).getDataString(),<span style="color:#dd1144;">"$15.99"</span>);
```

 </div> </div><div class="code panel pdl conf-macro output-block" id="bkmrk-" style="border-width:1px;"><div class="codeContent panelContent pdl"> </div> </div>### Login to AIQ

<div class="codeSnippet" id="bkmrk-copy-%24baseurl-%3D-%22htt"><div class="codeSnippetBody">```
$baseURL = <span style="color:#dd1144;">"http://localhost:8080"</span>;<br></br><span style="color:#333333;font-weight:bold;">var</span> $loginForm = formData();<br></br><br></br>$loginForm.put(<span style="color:#dd1144;">"username"</span>,<span style="color:#dd1144;">"appvance"</span>);<br></br>$loginForm.put(<span style="color:#dd1144;">"password"</span>,<span style="color:#dd1144;">"appvance"</span>);<br></br><br></br><span style="color:#333333;font-weight:bold;">var</span> $call = createPost($baseURL+<span style="color:#dd1144;">"/AppvanceServer/rest/admin/loggin"</span>, $loginForm);<br></br><span style="color:#333333;font-weight:bold;">var</span> $resp = process($call);<br></br><span style="color:#333333;font-weight:bold;">var</span> $json = <span style="color:#0086b3;">JSON</span>.parse($resp.getDataString());<br></br><br></br><span style="color:#333333;font-weight:bold;">if</span> ($json.logged) {<br></br>  <span style="color:#333333;font-weight:bold;">var</span> $jsession = getCookieValue($baseURL,<span style="color:#dd1144;">"JSESSIONID"</span>);<br></br>  addGlobalHeader(<span style="color:#dd1144;">"cookie"</span>,<span style="color:#dd1144;">"JSESSIONID="</span>+$jsession);  <span style="color:#999988;font-style:italic;">// adding global cookie for JSESSIONID</span><br></br>  log(<span style="color:#dd1144;">"Logged In, JSESSIONID: "</span>+$jsesssion);<br></br>} <span style="color:#333333;font-weight:bold;">else</span> {<br></br>  log(<span style="color:#dd1144;">"Unsuccessful login"</span>);<br></br>}
```

 </div> </div><div class="code panel pdl conf-macro output-block" id="bkmrk--1" style="border-width:1px;"><div class="codeContent panelContent pdl"> </div> </div>### ServiceSuite and XML

<div class="codeSnippet" id="bkmrk-copy-var-payload-%3D-%22"><div class="codeSnippetBody">```
<span style="color:#333333;font-weight:bold;">var</span> payload = <span style="color:#dd1144;">"<xml><username>John</username><id>123-1341-123</id></xml>"</span>;<br></br><span style="color:#333333;font-weight:bold;">var</span> call = createPost(<span style="color:#dd1144;">"https://example.com/getAddress"</span>, payload, <span style="color:#dd1144;">"text/xml"</span>);<br></br><span style="color:#333333;font-weight:bold;">var</span> result = process(call);<br></br><span style="color:#333333;font-weight:bold;">var</span> address1 = extract(<span style="color:#dd1144;">"XML"</span>, result, <span style="color:#dd1144;">"//Address1"</span>);<br></br><span style="color:#333333;font-weight:bold;">var</span> city = extract(<span style="color:#dd1144;">"XML"</span>, result, <span style="color:#dd1144;">"//City"</span>);<br></br><span style="color:#333333;font-weight:bold;">var</span> state = extract(<span style="color:#dd1144;">"XML"</span>, result, <span style="color:#dd1144;">"//ST"</span>);
```

 </div> </div><div class="code panel pdl conf-macro output-block" id="bkmrk--2" style="border-width:1px;"><div class="codeContent panelContent pdl"> </div> </div>### Upload a file to AIQ repository

<div class="codeSnippet" id="bkmrk-copy-const-%24boundary"><div class="codeSnippetBody">```
<span style="color:#333333;font-weight:bold;">const</span> $boundary = <span style="color:#dd1144;">"AIQ-DS-BOUNDARY"</span>;<br></br><br></br><span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">login</span>($baseURL, $username, $password) {<br></br>    <span style="color:#333333;font-weight:bold;">var</span> $loginForm = formData();<br></br>    $loginForm.put(<span style="color:#dd1144;">"username"</span>,$username);<br></br>    $loginForm.put(<span style="color:#dd1144;">"password"</span>,$password);<br></br>    <span style="color:#333333;font-weight:bold;">var</span> $call = createPost($baseURL + <span style="color:#dd1144;">"/AppvanceServer/rest/admin/logginForServices"</span>, $loginForm);<br></br>    <span style="color:#333333;font-weight:bold;">var</span> $resp = process($call).getDataString();<br></br>    <span style="color:#333333;font-weight:bold;">if</span> ($resp.indexOf(<span style="color:#dd1144;">"true"</span>) != <span style="color:#008080;">-1</span>) { <br></br>        <span style="color:#333333;font-weight:bold;">var</span> $jsession = getCookieValue($baseURL,<span style="color:#dd1144;">"JSESSIONID"</span>);<br></br>        addGlobalHeader(<span style="color:#dd1144;">"cookie"</span>,<span style="color:#dd1144;">"JSESSION="</span> + $jsession);<br></br>        log(<span style="color:#dd1144;">"Login successful"</span>)<br></br>        <span style="color:#333333;font-weight:bold;">return</span> <span style="color:#008080;">true</span>;<br></br>    } <span style="color:#333333;font-weight:bold;">else</span> {<br></br>        log(<span style="color:#dd1144;">"Login was NOT successful"</span>)<br></br>        <span style="color:#333333;font-weight:bold;">return</span> <span style="color:#008080;">false</span>;<br></br>    }<br></br>}<br></br><br></br><br></br><span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">createMultipartPayload</span>($filename) {<br></br>    <span style="color:#333333;font-weight:bold;">var</span> header = <span style="color:#dd1144;">'--'</span> + $boundary + <span style="color:#dd1144;">'\n'</span> +<br></br>        <span style="color:#dd1144;">'Content-Disposition: form-data; name="file"; filename="'</span> + $filename + <span style="color:#dd1144;">'"\r\n'</span> +<br></br>        <span style="color:#dd1144;">'Content-Type: application/octet-stream\r\n\r\n'</span>;<br></br>    <span style="color:#333333;font-weight:bold;">var</span> headerBytes = <span style="color:#333333;font-weight:bold;">new</span> <span style="color:#0086b3;">Array</span>(header.length);<br></br>    <span style="color:#333333;font-weight:bold;">for</span> (<span style="color:#333333;font-weight:bold;">var</span> i = <span style="color:#008080;">0</span>; i < header.length; ++i) {<br></br>        headerBytes[i] = header.charCodeAt(i);<br></br>    }<br></br>    <span style="color:#333333;font-weight:bold;">var</span> docBytes = readBytes($filename);<br></br>    <span style="color:#333333;font-weight:bold;">var</span> footer = <span style="color:#dd1144;">'\r\n--'</span> + $boundary + <span style="color:#dd1144;">"--\r\n"</span>;<br></br>    <span style="color:#333333;font-weight:bold;">var</span> footerBytes = <span style="color:#333333;font-weight:bold;">new</span> <span style="color:#0086b3;">Array</span>(footer.length);<br></br>    <span style="color:#333333;font-weight:bold;">for</span> (<span style="color:#333333;font-weight:bold;">var</span> i = <span style="color:#008080;">0</span>; i < footer.length; ++i) {<br></br>        footerBytes[i] = footer.charCodeAt(i);<br></br>    }<br></br>    <span style="color:#333333;font-weight:bold;">return</span> headerBytes.concat(docBytes).concat(footerBytes);<br></br>}<br></br><br></br><br></br><span style="color:#333333;font-weight:bold;">var</span> $filename = <span style="color:#dd1144;">"test2.js"</span>;    <span style="color:#999988;font-style:italic;">// CHANGE FOR YOUR FILE TO UPLOAD</span><br></br><span style="color:#333333;font-weight:bold;">var</span> $repositoryName = <span style="color:#dd1144;">"test"</span>;  <span style="color:#999988;font-style:italic;">// CHANGE FOR YOUR REPO NAME, THIS CONF MUST BE IN THE USER ACCOUNT USED TO LOGIN</span><br></br><span style="color:#333333;font-weight:bold;">var</span> $username = <span style="color:#dd1144;">"appvance"</span>;<br></br><span style="color:#333333;font-weight:bold;">var</span> $password = <span style="color:#dd1144;">"appvance"</span>;<br></br><br></br>login(<span style="color:#dd1144;">"http://my-aiq-controller.appvance.com:8080"</span>, $username, $password);   <span style="color:#999988;font-style:italic;">// CHANGE FOR YOUR AIQ SERVER DNS</span><br></br><br></br><span style="color:#333333;font-weight:bold;">var</span> data = createMultipartPayload($filename);<br></br>log(data.length, $username, $password);<br></br><br></br><span style="color:#333333;font-weight:bold;">var</span> call= createPost(<span style="color:#dd1144;">"http://localhost:8080/AppvanceServer/rest/file/uploadFile?&commitMessage=Appvance+skip+commit&path=REPOSITORY/"</span>+$repositoryName+<span style="color:#dd1144;">"/"</span>+$filename, data, <span style="color:#dd1144;">"multipart/form-data"</span>, <span style="color:#dd1144;">" boundary="</span> + $boundary);<br></br><br></br><span style="color:#333333;font-weight:bold;">var</span> resp = process(call);<br></br>log(resp.getDataString())<br></br>
```

 </div> </div><div class="code panel pdl conf-macro output-block" id="bkmrk--3" style="border-width:1px;"><div class="codeContent panelContent pdl"> </div> </div>### Upload the File to an application

<div class="codeSnippet" id="bkmrk-copy-%2F%2A%2A%C2%A0%2A-creates-a"><div class="codeSnippetBody">```
<span style="color:#999988;font-style:italic;">/**</span><br></br><span style="color:#999988;font-style:italic;"> * Creates a multipart payload from file contentes</span><br></br><span style="color:#999988;font-style:italic;"> **/</span><br></br><span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">createMultipartPayload</span>($filename) {<br></br>    <span style="color:#333333;font-weight:bold;">var</span> header = <span style="color:#dd1144;">'--'</span> + $boundary + <span style="color:#dd1144;">'\n'</span> +<br></br>        <span style="color:#dd1144;">'Content-Disposition: form-data; name="file"; filename="'</span> + $filename + <span style="color:#dd1144;">'"\r\n'</span> +<br></br>        <span style="color:#dd1144;">'Content-Type: application/octet-stream\r\n\r\n'</span>;<br></br>    <span style="color:#333333;font-weight:bold;">var</span> headerBytes = <span style="color:#333333;font-weight:bold;">new</span> <span style="color:#0086b3;">Array</span>(header.length);<br></br>    <span style="color:#333333;font-weight:bold;">for</span> (<span style="color:#333333;font-weight:bold;">var</span> i = <span style="color:#008080;">0</span>; i < header.length; ++i) {<br></br>        headerBytes[i] = header.charCodeAt(i);<br></br>    }<br></br>    <span style="color:#333333;font-weight:bold;">var</span> docBytes = readBytes($filename);<br></br>    <span style="color:#333333;font-weight:bold;">var</span> footer = <span style="color:#dd1144;">'\r\n--'</span> + $boundary + <span style="color:#dd1144;">"--\r\n"</span>;<br></br>    <span style="color:#333333;font-weight:bold;">var</span> footerBytes = <span style="color:#333333;font-weight:bold;">new</span> <span style="color:#0086b3;">Array</span>(footer.length);<br></br>    <span style="color:#333333;font-weight:bold;">for</span> (<span style="color:#333333;font-weight:bold;">var</span> i = <span style="color:#008080;">0</span>; i < footer.length; ++i) {<br></br>        footerBytes[i] = footer.charCodeAt(i);<br></br>    }<br></br>    <span style="color:#333333;font-weight:bold;">return</span> headerBytes.concat(docBytes).concat(footerBytes);<br></br>}<br></br><br></br><span style="color:#999988;font-style:italic;">/*</span><br></br><span style="color:#999988;font-style:italic;"> * Uploads a file to $SERVER</span><br></br><span style="color:#999988;font-style:italic;"> */</span><br></br><span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">uploadFile</span>($filename) {<br></br>   <span style="color:#333333;font-weight:bold;">var</span> data = createMultipartPayload($filename);<br></br>   <span style="color:#333333;font-weight:bold;">var</span> url = $SERVER+ <span style="color:#dd1144;">"/upload/"</span>+$filename+<span style="color:#dd1144;">"?filename="</span>+$filename;<br></br>   log(<span style="color:#dd1144;">"url: "</span>+url);<br></br>   <span style="color:#333333;font-weight:bold;">var</span> call= createPut(url, data, <span style="color:#dd1144;">"multipart/form-data"</span>, <span style="color:#dd1144;">" boundary="</span> + $boundary);<br></br>   <span style="color:#333333;font-weight:bold;">return</span> process(call).getDataString();<br></br>}<br></br><br></br><span style="color:#333333;font-weight:bold;">const</span> $boundary = <span style="color:#dd1144;">"AIQ-DS-BOUNDARY"</span>;<br></br><span style="color:#333333;font-weight:bold;">const</span> $SERVER = <span style="color:#dd1144;">"http://xxxx.eu-west-2.elb.amazonaws.com"</span>;<br></br><br></br><span style="color:#333333;font-weight:bold;">var</span> $filename = <span style="color:#dd1144;">"test2.js"</span>;    <span style="color:#999988;font-style:italic;">// CHANGE FOR YOUR FILE TO UPLOAD</span><br></br><span style="color:#333333;font-weight:bold;">var</span> result = uploadFile($filename);<br></br><br></br>log(result);
```

 </div> </div><div class="code panel pdl conf-macro output-block" id="bkmrk--4" style="border-width:1px;"><div class="codeContent panelContent pdl"> </div> </div>### Send an email with a custom timestamp in the Subject

<div class="code panel pdl conf-macro output-block" id="bkmrk-copy-var-date-%3D-new-" style="border-width:1px;"><div class="codeContent panelContent pdl"><div class="codeSnippet"><div class="codeSnippetBody">```
<span style="color:#333333;font-weight:bold;">var</span> date = <span style="color:#333333;font-weight:bold;">new</span> <span style="color:#0086b3;">Date</span>();<br></br><span style="color:#333333;font-weight:bold;">var</span> formatDate = date.getDate() + <span style="color:#dd1144;">"-"</span> + date.getMonth() + <span style="color:#dd1144;">"-"</span> + date.getYear() + <span style="color:#dd1144;">" "</span> + date.toLocaleTimeString();<br></br><span style="color:#333333;font-weight:bold;">var</span> graphService = createOAuthMailClient(<span style="color:#dd1144;">"email"</span>, <span style="color:#dd1144;">"clientID"</span>, <span style="color:#dd1144;">"secretKey"</span>, <span style="color:#dd1144;">"tenantID"</span>);<br></br><span style="color:#333333;font-weight:bold;">var</span> msg = graphService.createMailMessage(<span style="color:#dd1144;">"Message generated "</span> + formatDate, <span style="color:#dd1144;">"Test body email."</span>);<br></br>msg.addTo([<span style="color:#dd1144;">"to@test.com"</span>]);<br></br><span style="color:#333333;font-weight:bold;">var</span> sent = graphService.sendMessage(msg);<br></br><span style="color:#333333;font-weight:bold;">if</span> (!sent) {<br></br>    <span style="color:#333333;font-weight:bold;">throw</span> <span style="color:#333333;font-weight:bold;">new</span> <span style="color:#0086b3;">Error</span>(<span style="color:#dd1144;">'An error occurred while sending the email.'</span>);<br></br>} <span style="color:#333333;font-weight:bold;">else</span> {<br></br>    log(<span style="color:#dd1144;">"Email sent."</span>);<br></br>}
```

 </div> </div> </div> </div>### Extract value from receive email’s subject

<div class="codeSnippet" id="bkmrk-copy-var-graphservic"><div class="codeSnippetBody">```
<span style="color:#333333;font-weight:bold;">var</span> graphService = createOAuthMailClient(<span style="color:#dd1144;">"email"</span>, <span style="color:#dd1144;">"clientID"</span>, <span style="color:#dd1144;">"secretKey"</span>, <span style="color:#dd1144;">"tenantID"</span>);<br></br><span style="color:#333333;font-weight:bold;">var</span> unreadList = graphService.getUnreadMessages();<br></br><span style="color:#333333;font-weight:bold;">var</span> unreadCount = unreadList.size();<br></br><span style="color:#333333;font-weight:bold;">if</span> (unreadCount > <span style="color:#008080;">0</span>) {<br></br>  <span style="color:#333333;font-weight:bold;">var</span> i = <span style="color:#008080;">0</span>; <span style="color:#999988;font-style:italic;">//first unread email</span><br></br>  log(<span style="color:#dd1144;">"Id: "</span> + unreadList.get(i).id);<br></br>  log(<span style="color:#dd1144;">"From: "</span> + unreadList.get(i).from.emailAddress.address);<br></br>  log(<span style="color:#dd1144;">"Subject: "</span> + unreadList.get(i).subject);<br></br>    <br></br>  <span style="color:#333333;font-weight:bold;">var</span> subject = unreadList.get(i).subject;<br></br>  <span style="color:#333333;font-weight:bold;">var</span> startIndex = subject.lastIndexOf(<span style="color:#dd1144;">"Ref. "</span>) + <span style="color:#008080;">5</span>;<br></br>  <span style="color:#333333;font-weight:bold;">var</span> refCode = subject.substr(startIndex, <span style="color:#008080;">8</span>);<br></br>  log(<span style="color:#dd1144;">"Ref code: "</span> + refCode);
```

 </div> </div><div class="code panel pdl conf-macro output-block" id="bkmrk--6" style="border-width:1px;"><div class="codeContent panelContent pdl"> </div> </div>### Compare email’s body 

<div class="codeSnippet" id="bkmrk-copy-var-expectedbod"><div class="codeSnippetBody">```
<span style="color:#333333;font-weight:bold;">var</span> expectedBody = <span style="color:#dd1144;">"This is an automated acknowledgement to let you know that your correspondence to the Appvance Information Rights Team has been received.Any request for personal data will be handled as a data subject access request."</span>;<br></br>  <span style="color:#333333;font-weight:bold;">var</span> body = unreadList.get(i).body.content.replace(/(\r\n|\n|\r)/gm,<span style="color:#dd1144;">""</span>); <span style="color:#999988;font-style:italic;">//remove line break and spaces.</span><br></br>  body = body.substr(<span style="color:#008080;">0</span>,body.indexOf(<span style="color:#dd1144;">"uk"</span>)+<span style="color:#008080;">2</span>); <span style="color:#999988;font-style:italic;">//trim to remove links at the end</span><br></br>  log(<span style="color:#dd1144;">"Email have the expected content: "</span> + (body === expectedBody));<br></br>} <span style="color:#333333;font-weight:bold;">else</span> {<br></br>    log(<span style="color:#dd1144;">"There's no unread messages."</span>);<br></br>}
```

 </div> </div><div class="code panel pdl conf-macro output-block" id="bkmrk--8" style="border-width:1px;"><div class="codeContent panelContent pdl"> </div> </div>###    
Utility Functions

<div class="codeSnippet" id="bkmrk-copy-%2F%2A%2A%C2%A0%2A-btoa%C2%A0%2A-%40p-1"><div class="codeSnippetBody">```
<span style="color:#999988;font-style:italic;">/**</span><br></br><span style="color:#999988;font-style:italic;"> * btoa</span><br></br><span style="color:#999988;font-style:italic;"> * @param st</span> <br></br><span style="color:#999988;font-style:italic;"> * @returns base64 encoded string</span><br></br><span style="color:#999988;font-style:italic;"> */</span><br></br> <span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">btoa</span>(st) {<br></br>    <span style="color:#333333;font-weight:bold;">return</span> Java.type(java.util.Base64).getEncoder().encode(st);<br></br>}<br></br><br></br><span style="color:#999988;font-style:italic;">/**</span><br></br><span style="color:#999988;font-style:italic;"> * atob</span><br></br><span style="color:#999988;font-style:italic;"> * @param st</span> <br></br><span style="color:#999988;font-style:italic;"> * @returns decoded base64 string</span><br></br><span style="color:#999988;font-style:italic;"> */</span><br></br><span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">atob</span>(st) {<br></br>    <span style="color:#333333;font-weight:bold;">return</span> Java.type(java.util.Base64).getDecoder().decode(st);<br></br>}<br></br><span style="color:#999988;font-style:italic;">/**</span><br></br><span style="color:#999988;font-style:italic;"> *</span> <br></br><span style="color:#999988;font-style:italic;"> * @param length number</span><br></br><span style="color:#999988;font-style:italic;"> * @returns random number of length number of digits</span><br></br><span style="color:#999988;font-style:italic;"> */</span><br></br><span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">randomNumber</span>(length) {<br></br>    <span style="color:#333333;font-weight:bold;">var</span> result = <span style="color:#dd1144;">''</span>;<br></br>    <span style="color:#333333;font-weight:bold;">for</span> (<span style="color:#333333;font-weight:bold;">var</span> i = <span style="color:#008080;">0</span>; i < length; i++) {<br></br>        result += <span style="color:#0086b3;">Math</span>.floor(<span style="color:#0086b3;">Math</span>.random() * <span style="color:#008080;">10</span>);<br></br>    }<br></br>    <span style="color:#333333;font-weight:bold;">return</span> result;<br></br>}<br></br><br></br><br></br><span style="color:#999988;font-style:italic;">/**</span><br></br><span style="color:#999988;font-style:italic;"> * Extracts catching an exception and returning NOT_FOUND string if target is not found.</span><br></br><span style="color:#999988;font-style:italic;"> * @param {string} format ("HTML","HTTP","PDF","CSV","Excel","TEXT","STRING")</span><br></br><span style="color:#999988;font-style:italic;"> * @param {HttpResponse} response</span> <br></br><span style="color:#999988;font-style:italic;"> * @param {string} target</span> <br></br><span style="color:#999988;font-style:italic;"> * @returns</span> <br></br><span style="color:#999988;font-style:italic;"> */</span><br></br><span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">extractOrNotFound</span>(format, response, target) {<br></br>    <span style="color:#333333;font-weight:bold;">const</span> NOT_FOUND = <span style="color:#dd1144;">"Not found."</span>;<br></br>    <span style="color:#333333;font-weight:bold;">var</span> value;<br></br>    <span style="color:#333333;font-weight:bold;">try</span> {<br></br>        value = extract(format, response, target);<br></br>        <span style="color:#333333;font-weight:bold;">if</span> (<span style="color:#333333;font-weight:bold;">typeof</span> value == <span style="color:#dd1144;">"undefined"</span>) {<br></br>            <span style="color:#333333;font-weight:bold;">return</span> NOT_FOUND;<br></br>        }<br></br>        <span style="color:#333333;font-weight:bold;">return</span> value;<br></br>    } <span style="color:#333333;font-weight:bold;">catch</span> (e) {<br></br>        <span style="color:#333333;font-weight:bold;">return</span> NOT_FOUND;<br></br>    }<br></br>}<br></br><br></br><span style="color:#999988;font-style:italic;">/**</span><br></br><span style="color:#999988;font-style:italic;"> * SSN</span><br></br><span style="color:#999988;font-style:italic;"> * @returns random string matching social security number format</span><br></br><span style="color:#999988;font-style:italic;"> */</span><br></br><span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">SSN</span>() {<br></br>    <span style="color:#333333;font-weight:bold;">var</span> result = <span style="color:#dd1144;">''</span>;<br></br>    result = randomNumber(<span style="color:#008080;">3</span>) + <span style="color:#dd1144;">"-"</span> + randomNumber(<span style="color:#008080;">2</span>) + <span style="color:#dd1144;">"-"</span> + randomNumber(<span style="color:#008080;">4</span>);<br></br>    <span style="color:#333333;font-weight:bold;">return</span> result;<br></br>}<br></br><br></br><span style="color:#999988;font-style:italic;">// *************************************************************************</span><br></br><span style="color:#999988;font-style:italic;">// parseCurrencyStringToNumber</span><br></br><span style="color:#999988;font-style:italic;">//</span><br></br><span style="color:#999988;font-style:italic;">// Parse a currency string to a number, $1,245.50 -> 1245.5</span><br></br><span style="color:#999988;font-style:italic;">// ************************************************************************</span><br></br><span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">parseCurrencyStringToNumber</span>(currency) {<br></br>    <span style="color:#333333;font-weight:bold;">if</span> (<span style="color:#333333;font-weight:bold;">typeof</span> currency == <span style="color:#dd1144;">"undefined"</span> || currency == <span style="color:#dd1144;">""</span>) {<br></br>        log(<span style="color:#dd1144;">"Warning in parseCurrencyStringToNumber, expecting a number but got undefined or empty."</span>);<br></br>        <span style="color:#333333;font-weight:bold;">return</span> <span style="color:#008080;">-1</span>;<br></br>    }<br></br>    <span style="color:#333333;font-weight:bold;">if</span> (currency == <span style="color:#dd1144;">"0"</span>) {<br></br>        <span style="color:#333333;font-weight:bold;">return</span> <span style="color:#008080;">0</span>;<br></br>    }<br></br>    <span style="color:#333333;font-weight:bold;">if</span> (currency.indexOf(<span style="color:#dd1144;">"("</span>) !== <span style="color:#008080;">-1</span>) {<br></br>        currency = <span style="color:#dd1144;">"-"</span> + currency.replace(/[(|)]+/g, <span style="color:#dd1144;">""</span>)<br></br>    }<br></br>    <span style="color:#333333;font-weight:bold;">return</span> <span style="color:#0086b3;">Number</span>(<span style="color:#0086b3;">String</span>(currency).replace(/[^<span style="color:#008080;">0-9.</span>-]+/g, <span style="color:#dd1144;">""</span>));<br></br>}<br></br><br></br><span style="color:#999988;font-style:italic;">// *************************************************************************</span><br></br><span style="color:#999988;font-style:italic;">// parseNumberToCurrency</span><br></br><span style="color:#999988;font-style:italic;">//</span><br></br><span style="color:#999988;font-style:italic;">// Parse a number to a string currency with commas, 1245.5  -> $1,245.50</span> <br></br><span style="color:#999988;font-style:italic;">// ************************************************************************</span><br></br><span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">parseNumberToCurrency</span>(aNumber) {<br></br>    <span style="color:#333333;font-weight:bold;">if</span> (aNumber == <span style="color:#008080;">0</span>) {<br></br>        <span style="color:#333333;font-weight:bold;">return</span> (<span style="color:#dd1144;">"$0.00"</span>);<br></br>    };<br></br>    <span style="color:#333333;font-weight:bold;">var</span> tempST = <span style="color:#0086b3;">String</span>(aNumber).replace(/[^<span style="color:#008080;">0-9.</span>-]+/g, <span style="color:#dd1144;">""</span>);<br></br>    <span style="color:#333333;font-weight:bold;">try</span> {<br></br>        <span style="color:#333333;font-weight:bold;">var</span> tempNumber = <span style="color:#0086b3;">Number</span>(<span style="color:#0086b3;">parseFloat</span>(tempST).toFixed(<span style="color:#008080;">2</span>));<br></br>        <span style="color:#333333;font-weight:bold;">var</span> tempLocale = tempNumber.toLocaleString(<span style="color:#008080;">undefined</span>, { minimumFractionDigits: <span style="color:#008080;">2</span> });<br></br>        <span style="color:#333333;font-weight:bold;">return</span> <span style="color:#dd1144;">"$"</span> + tempLocale;<br></br>    } <span style="color:#333333;font-weight:bold;">catch</span> (e) {<br></br>        log(<span style="color:#dd1144;">"Error converting to currency ["</span> + aNumber + <span style="color:#dd1144;">"], isNAN: "</span> + <span style="color:#0086b3;">isNaN</span>(aNumber) + <span style="color:#dd1144;">" - "</span> + e.message);<br></br>        <span style="color:#333333;font-weight:bold;">return</span> <span style="color:#dd1144;">"NA"</span>;<br></br>    }<br></br>}<br></br><br></br><span style="color:#999988;font-style:italic;">/**</span><br></br><span style="color:#999988;font-style:italic;"> * dateToString</span><br></br><span style="color:#999988;font-style:italic;"> * @param day</span> <br></br><span style="color:#999988;font-style:italic;"> * @returns</span> <br></br><span style="color:#999988;font-style:italic;"> */</span><br></br><span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">dateToString</span>(day) {<br></br>    <span style="color:#333333;font-weight:bold;">var</span> dd = <span style="color:#0086b3;">String</span>(day.getDate()).padStart(<span style="color:#008080;">2</span>, <span style="color:#dd1144;">'0'</span>);<br></br>    <span style="color:#333333;font-weight:bold;">var</span> mm = <span style="color:#0086b3;">String</span>(day.getMonth() + <span style="color:#008080;">1</span>).padStart(<span style="color:#008080;">2</span>, <span style="color:#dd1144;">'0'</span>); <span style="color:#999988;font-style:italic;">//January is 0!</span><br></br>    <span style="color:#333333;font-weight:bold;">var</span> yyyy = day.getFullYear();<br></br>    <span style="color:#333333;font-weight:bold;">return</span> mm + <span style="color:#dd1144;">'/'</span> + dd + <span style="color:#dd1144;">'/'</span> + yyyy;;<br></br>}<br></br><br></br><span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">getTodayDate</span>() {<br></br>    <span style="color:#333333;font-weight:bold;">var</span> now = java.time.LocalDateTime.now();<br></br>    <span style="color:#333333;font-weight:bold;">var</span> formatter = java.time.format.DateTimeFormatter.ofPattern(<span style="color:#dd1144;">"MM/dd/yyyy"</span>);<br></br>    <span style="color:#333333;font-weight:bold;">return</span> now.withHour(<span style="color:#008080;">0</span>).withMinute(<span style="color:#008080;">0</span>).withSecond(<span style="color:#008080;">0</span>).format(formatter);<br></br>}<br></br><br></br><span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">getYesterdayDate</span>() {<br></br>   <span style="color:#333333;font-weight:bold;">var</span> now = java.time.LocalDateTime.now();<br></br>   <span style="color:#333333;font-weight:bold;">var</span> formatter = java.time.format.DateTimeFormatter.ofPattern(<span style="color:#dd1144;">"MM/dd/yyyy"</span>);<br></br>   <span style="color:#333333;font-weight:bold;">return</span> now.minus(<span style="color:#008080;">1</span>, java.time.temporal.ChronoUnit.DAYS).withHour(<span style="color:#008080;">0</span>).withMinute(<span style="color:#008080;">0</span>)<br></br>                .withSecond(<span style="color:#008080;">0</span>).format(formatter);<br></br>}<br></br><br></br><span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">getTomorrowDate</span>() {<br></br>   <span style="color:#333333;font-weight:bold;">var</span> now = java.time.LocalDateTime.now();<br></br>   <span style="color:#333333;font-weight:bold;">var</span> formatter = java.time.format.DateTimeFormatter.ofPattern(<span style="color:#dd1144;">"MM/dd/yyyy"</span>);<br></br>   <span style="color:#333333;font-weight:bold;">return</span> now.plus(<span style="color:#008080;">1</span>, java.time.temporal.ChronoUnit.DAYS).withHour(<span style="color:#008080;">0</span>).withMinute(<span style="color:#008080;">0</span>)<br></br>                .withSecond(<span style="color:#008080;">0</span>).format(formatter);<br></br>}<br></br><br></br><span style="color:#999988;font-style:italic;">/**</span><br></br><span style="color:#999988;font-style:italic;"> * getDateISOString</span><br></br><span style="color:#999988;font-style:italic;"> * @returns</span> <br></br><span style="color:#999988;font-style:italic;"> */</span><br></br><span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">getDateISOString</span>() {<br></br>    <span style="color:#333333;font-weight:bold;">var</span> st = <span style="color:#333333;font-weight:bold;">new</span> <span style="color:#0086b3;">Date</span>().toISOString();<br></br>    <span style="color:#333333;font-weight:bold;">return</span> st.replace(/\-/g, <span style="color:#dd1144;">"_"</span>).replace(/\:/g, <span style="color:#dd1144;">"_"</span>).replace(/\./g, <span style="color:#dd1144;">"_"</span>);<br></br>}<br></br><br></br><span style="color:#999988;font-style:italic;">/**</span><br></br><span style="color:#999988;font-style:italic;"> * dateOneMonthAfter</span><br></br><span style="color:#999988;font-style:italic;"> * @param $date</span> <br></br><span style="color:#999988;font-style:italic;"> * @returns</span> <br></br><span style="color:#999988;font-style:italic;"> */</span><br></br><span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">dateOneMonthAfter</span>($date) {<br></br>    <span style="color:#333333;font-weight:bold;">var</span> day = <span style="color:#333333;font-weight:bold;">new</span> <span style="color:#0086b3;">Date</span>(<span style="color:#0086b3;">Date</span>.parse($date));<br></br>    day.setMonth(day.getMonth() + <span style="color:#008080;">1</span>);<br></br>    day.setTime(day.getTime() + TIME_OFFSET);<br></br>    <span style="color:#333333;font-weight:bold;">return</span> dateToString(day);<br></br>}<br></br><br></br><span style="color:#999988;font-style:italic;">/**</span><br></br><span style="color:#999988;font-style:italic;"> * dateOneYearAfter</span><br></br><span style="color:#999988;font-style:italic;"> * @param $date</span> <br></br><span style="color:#999988;font-style:italic;"> * @returns</span> <br></br><span style="color:#999988;font-style:italic;"> */</span><br></br><span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">dateOneYearAfter</span>($date) {<br></br>    <span style="color:#333333;font-weight:bold;">var</span> day = <span style="color:#333333;font-weight:bold;">new</span> <span style="color:#0086b3;">Date</span>(<span style="color:#0086b3;">Date</span>.parse($date));<br></br>    day.setFullYear(day.getFullYear() + <span style="color:#008080;">1</span>);<br></br>    day.setTime(day.getTime() + TIME_OFFSET);<br></br>    <span style="color:#333333;font-weight:bold;">return</span> dateToString(day);<br></br>}<br></br><br></br><span style="color:#999988;font-style:italic;">/**</span><br></br><span style="color:#999988;font-style:italic;"> * randomLastName</span><br></br><span style="color:#999988;font-style:italic;"> * @returns</span> <br></br><span style="color:#999988;font-style:italic;"> */</span><br></br> <span style="color:#333333;font-weight:bold;">function</span> <span style="color:#990000;font-weight:bold;">randomLastName</span>() {<br></br>    <span style="color:#333333;font-weight:bold;">var</span> sylabs = <span style="color:#008080;">2</span> + <span style="color:#0086b3;">Math</span>.floor(<span style="color:#0086b3;">Math</span>.random() * <span style="color:#008080;">2</span>)<br></br>    <span style="color:#333333;font-weight:bold;">var</span> result = <span style="color:#dd1144;">''</span>;<br></br>    <span style="color:#333333;font-weight:bold;">var</span> characters = <span style="color:#dd1144;">'bccdfghjkllmnnprrssttvwyz'</span>;<br></br>    <span style="color:#333333;font-weight:bold;">var</span> vocals = <span style="color:#dd1144;">'aeioeua'</span>;<br></br>    <span style="color:#333333;font-weight:bold;">var</span> charactersLength = characters.length;<br></br>    result += <span style="color:#dd1144;">"SBCLKJMCH"</span>.charAt(<span style="color:#0086b3;">Math</span>.floor(<span style="color:#0086b3;">Math</span>.random() * <span style="color:#008080;">9</span>));<br></br>    result += vocals.charAt(<span style="color:#0086b3;">Math</span>.floor(<span style="color:#0086b3;">Math</span>.random() * <span style="color:#008080;">7</span>));<br></br>    sylabs--;<br></br>    <span style="color:#333333;font-weight:bold;">for</span> (<span style="color:#333333;font-weight:bold;">var</span> i = <span style="color:#008080;">0</span>; i < sylabs; i++) {<br></br>        result += characters.charAt(<span style="color:#0086b3;">Math</span>.floor(<span style="color:#0086b3;">Math</span>.random() * charactersLength));<br></br>        result += vocals.charAt(<span style="color:#0086b3;">Math</span>.floor(<span style="color:#0086b3;">Math</span>.random() * <span style="color:#008080;">7</span>));<br></br>    }<br></br>    result += characters.charAt(<span style="color:#0086b3;">Math</span>.floor(<span style="color:#0086b3;">Math</span>.random() * charactersLength));<br></br>    <span style="color:#333333;font-weight:bold;">return</span> result;<br></br>}
```

 </div> </div><div class="code panel pdl conf-macro output-block" id="bkmrk--9" style="border-width:1px;"><div class="codeContent panelContent pdl">```

```

 </div> </div><div id="bkmrk-last-updated%3A-june-0">---

Last updated: <span class="mc-variable General.NewDateTimeVariable variable">June 02, 2023</span>

If you have any feedback on this topic, please contact us at <documentation@appvance.ai>

</div>

# Run Node.js npm Code from Service Suite

# Run Node.js npm Code from Service Suite

Use this guidance when a Service Suite scenario needs to call Node.js code or an npm package. Keep package execution controlled, repeatable, and limited to approved dependencies.

## Before execution

- Confirm the package is approved for the AIQ environment.
- Pin dependency versions through the approved package-management process.
- Keep credentials, tokens, and environment-specific values out of source files and articles.
- Document expected input, output, exit code, stdout, and stderr behavior.

## Validation workflow

1. Run the Node.js code with a small local or non-production sample.
2. Confirm Service Suite can locate the script and dependencies.
3. Review output and failures before using the package in a suite or scheduled run.
4. Record dependency changes with the scenario maintenance notes.

**Last updated:** September 8, 2026

# Send Email from Service Suite

Use this article when a Service Suite workflow needs to send email through an approved mail provider or internal SMTP path.

## What changed in this article

- Updated the email article around approved Service Suite email workflows and mail-provider controls.
- Added checks for SMTP/API endpoint, authentication, sender ownership, recipient controls, TLS, rate limits, retry behavior, and audit logging.
- Added guidance to avoid hard-coded passwords, personal mailboxes, and sensitive test data in email content.

## Validation workflow

1. Confirm the approved mail provider, sender identity, recipient list, and allowed test data before sending email.
2. Validate authentication, TLS, request payload, response status, and retry/error behavior in a controlled run.
3. Review logs and received messages without exposing passwords, tokens, or sensitive customer data.

**Review note:** This page now treats email sending as an integration with data-transmission risk controls.

---

Last updated: October 5, 2026

If you have feedback on this topic, contact <documentation@appvance.ai>.

# RBAC setup to use Graph Service in Service Suite

RBAC (Role-Based Access Control) for applications will eventually replace application access policies (see below). Today, the public preview shows some ragged edges in terms of the integration between Exchange Online and Azure AD that Microsoft says they’ll fix before general availability. Even with some bumps to navigate, the new functionality is a welcome addition that extends tenant control over their data, which is always a good thing.

In order to use this protocol you need to do the following configurations in your azure account so the roles and permissions are set correctly.

Once you have done the below steps you should be able to use the service suite Graph Service oauth2 client to send/receive emails using RBAC with the normal client commands.

1. Open Windows PowerShell as an Administrator
2. Execute: `connect-mggraph -scopes "Application.Read.All"`. If the exception *"The term connect-mggraph' is not recognized as the name of a cmdlet"* appears, execute the command   
    `install-module microsoft.graph`
    
     ![](https://docs.appvance.net/uploads/images/gallery/2026-07/scaled-1680-/kHcTrBP8IqcwvbSw-206298f29d5e.png)
3. After Microsoft Graph is installed, execute again the command `connect-mggraph -scopes "Application.Read.All"`
4. Sign in
    
     ![](https://docs.appvance.net/uploads/images/gallery/2026-07/scaled-1680-/OElRg6l1XPwEIE4K-37ffdb10936f.png)
5. After signing in, should see this:
    
     ![](https://docs.appvance.net/uploads/images/gallery/2026-07/scaled-1680-/Sd9vnWRdnhs1X26W-0637a63a1f99.png)
6. Execute: `$SP = Get-MgServicePrincipal -All`
7. Execute: `$ServicePrincipalId = $SP | Where-Object {$_.displayName -eq "{Application name}"} | Select-Object -ExpandProperty Id`
8. Execute: `$AppId = $SP | Where-Object {$_.displayName -eq "{Application name}"} | Select-Object -ExpandProperty AppId`
9. Execute: `Write-Host ("AppId is {0} and Service Principal Id is {1}" -f $AppId, $ServicePrincipalId)`   
    Output:
    
     ![](https://docs.appvance.net/uploads/images/gallery/2026-07/scaled-1680-/ellJI1M5BPx28A5O-87cec8a9db4a.png)
10. Execute: `Install-Module -Name ExchangeOnlineManagement`
11. Execute: `Import-module ExchangeOnlineManagement`
12. Execute: `Connect-ExchangeOnline -UserPrincipalName {user email}`  
    Output:
    
     ![](https://docs.appvance.net/uploads/images/gallery/2026-07/scaled-1680-/lKXYKes4OuazsfFK-d60bf650e0a7.png)
13. Execute: `New-ServicePrincipal -AppId $AppId -ServiceId $ServicePrincipalId -DisplayName '{Application name}'`
14. Execute: `New-ManagementScope -Name "Management emails" -RecipientRestrictionFilter "CustomAttribute1 -eq '{RolName}'"`
15. Execute: `Set-Mailbox -Identity {username} -CustomAttribute1 "{RolName}"`
16. Execute: `Get-EXOMailbox -Filter {CustomAttribute1 -eq "{RolName}"} | Format-Table DisplayName`
17. Execute: `New-ManagementRoleAssignment -App $AppId -Role "Application Mail.Mail.ReadWrite" -CustomResourceScope "Management emails"`
18. Execute: `New-ManagementRoleAssignment -App $AppId -Role "Application Mail.Send" -CustomResourceScope "Management emails"`
 
# Assing a role to a user

Execute: Set-Mailbox -Identity {username} -CustomAttribute1 "{RolName}"

# List available permissions

Execute: `Get-ManagementRole | Where-Object {$_.Name -like "Application *"}`

 ![](https://docs.appvance.net/uploads/images/gallery/2026-07/scaled-1680-/Gh7WDj7krQbRxsj4-c92a9a08657e.png)

# See permissions assigned to a user

Execute: `Test-ServicePrincipalAuthorization -Identity $AppId -Resource {email}`

 ![](https://docs.appvance.net/uploads/images/gallery/2026-07/scaled-1680-/nRTNr662Vqg4NsNL-432430f42a9a.png)

<div id="bkmrk-last-updated%3A-may-26">---

Last updated: <span class="mc-variable General.NewDateTimeVariable variable">May 26, 2023</span>

If you have any feedback on this topic, please contact us at <documentation@appvance.ai>

</div>