The Straatos Interact API enables 3rd party applications and web services to interact with Straatos to create new tasks, upload documents, update existing tasks, return values of tasks to the 3rd party application.
To know more about how two programs connect using web services, refer to FAQs.
Click highlighted areas for more information.
The Straatos Interact API allows you (or the CumulusPro Professional Services team) to define your own Straatos API in a simple JavaScript. The hosting of that API is done on the Straatos Platform and the API can be accessed through the Admin Panel.
Every organisation in Straatos has its own URL. The URL is unique to a specific organisation and can't be changed. For example: https://effektifconnector.cumuluspro.net/ConnectorService.svc/json/Interact/<YourOrganisationId>
JavaScript is used to define the web service. To define a new web service, go to Admin Panel > Organisation > Interact Script.
How to create a new task in a Straatos process:
| Name | Where to look | Description |
| createTask | Line 1 |
|
| Line 4 | A new task in Straatos created for the process ‘Test QA Workflow’ and the Start Event ‘Start’. | |
| Line 6 | A response provided to the calling web service. |
if (request.pathSegments[1] == 'createTask') {
// Create a new Task in the workflow named 'Test QA Workflow' at the Start Event 'Start'
// and returns the documentId of the newly created task
var documentId = straatos.addDocument('Test QA Workflow', 'Start');
// response of the webservice with the DocumentID
response.body = "Finished request of type " + request.pathSegments[1] + " DocumentID: " + documentId;
}
For easier development and troubleshooting, the Admin Panel provides a Log where a ‘console.log' command can write to get logging data.
To call this web service from a 3rd party application, the following URL can be used: https://effektif-connector.cumuluspro.net/ConnectorService.svc/json/Interact/<your organisation id>/createTask
This section describes how to use Straatos interact API to create new tasks, upload documents, update existing tasks, return values of tasks to the 3rd party application.
| Region | URL |
| Europe |
https://effektif-connector.cumuluspro.net/ConnectorService.svc/json/Interact/<YourOrganisationId> |
| Switzerland | https://effektif-connector-ch.cumuluspro.net/ConnectorService.svc/json/Interact/<YourOrganisationId> |
| Asia | https://effektif-connector-asia.cumuluspro.net/ConnectorService.svc/json/Interact/<YourOrganisationId> |
To know more about Organisation ID, refer to FAQs.
The request and response contain the information sent to the webservice and the response sent by the webservice to webservice call. Refer to Sample Code section for more details.
| Name | Type | Description | ||||||
| pathSegments | string |
Path segments. for example,
|
||||||
| queryParameters | ? |
Query parameters. for example, URL: https://domain.net/Connector.svc/json/Interact/A3B23-GUID-E76B/P2/P3?id=123&type=b
|
||||||
| headers | ? | Request headers as passed into the Interact call,for example, { 'Accept': 'application/json', 'X-Header': '123' } | ||||||
| contentType | string | Request content type as passed into the Interact call, for example, application/json | ||||||
| body | ? | Request body as passed into the Interact call as byte[] or string using UTF-8 encoding. Not available for multipart requests (Content-Type starts with 'multipart/'). | ||||||
| multipart | MultiPartRequest | Parsed parts of the multipart, only available if the request is a multipart request (Content-Type starts with 'multipart/' |
| Name | Type | Description |
| status | number |
HTTP status code to return to the client, 200 by default |
| headers | ? | Response headers that are returned to the client, for example, { 'Accept': 'application/json', 'X-Header': '123' } |
| body | ? | Response body as byte[] or MultiPart. To convert a string to byte[], you can use straatos.getBytes(stringVariable). A MultiPart object can be created using straatos.newFormData() |
Straatos contains functions to interact with the platform.
| Name | Attribute | Description |
| findDocuments | fn(workflowName: string, activityName: string, variables: ?) -> [number] | Find documents in the specified workflow step that match the variables (for example, { 'InvoiceNumber': 'IN12345' }). Returns an array with document ids. |
| messageWorkflow | fn(workflowName: string, activityName: string, documentIds: [number], variables: ?) | Send a message to the specified documents (usually acquired through straatos.findDocuments()) in the specified workflow step. The specified (workflow) variables (for example, { 'Status': 'Verified' }) will be updated. |
| addDocument | fn(workflowName: string, startEventName: string) -> number | Create a document, required for startWorkflow. Returns the document id. |
| addComment | fn(documentId: number, comment: string, commentDateTimeIso8601: string) | Adds a document comment. commentDateTimeIso8601 should be in ISO datetime format (YYYYMMDDThhmmss ie 2021-04-10T16:56:02Z) |
| startWorkflow | fn(documentId: number, variables: ?) | Start the workflow / start event for the specified document (created with addDocument). The specified (workflow) variables (for example, { 'Status': 'Verified' }) will be assigned. |
| getVariables | fn(documentId: number) -> ? | Get the workflow field values for the specified document (for example, { 'Name': 'John', 'InvoiceNumber': 'IN12345' }) |
| setDocumentContent | fn(documentId: number, files: [?], filetype: string, createPagePreviews: bool, createPDFPreviews: bool) | Add content to the document. The filetype parameters must be 'tif', 'pdf' or 'jpg' Each entry in the files parameter array should be a binary (byte[]), either a single (multi page) TIF, a single (multi page) PDF or one or more JPG files. |
| ajax | fn(parameters: AjaxParameters) -> jqXHR | Perform a synchronous HTTP (Ajax) request. |
| getString | fn(data: ?) -> string | Convert byte[] to string using UTF-9 encoding |
| getBytes | fn(data: string) -> ? | Convert string to byte[] using UTF-8 encoding |
| decodeBase64 | fn(data: string) -> ? | Decode base64 string to byte[] |
| encodeBase64 | fn(data: ?) -> string | Encode base64 byte[] to string |
| newFormData | fn() -> MultiPart | Create a new MultiPart object |
| newXMLDocument | fn(documentElementName: string, documentElementNamespace: string) -> JsXmlDocument | Create a new XML document. The documentElementName can contain a namespace prefix (for example, 'ns:company') if a documentElementNamespace is provided. The documentElementNamespace is optional, for elements without namespace this parameter should not be specified. |
| parseXML | fn(data: ?) -> JsXmlDocument | Parses the data parameter (either a byte[] or string containing the XML and returns the XML document |
| transformXSL | fn(xslDocument: JsXmlDocument, inputDocument: JsXmlDocument) -> JsXmlDocument | Transforms the inputDocument using the xslDocument XSL. Returns the result as XML document |
To create an XML Document, use the following straatos methods:
| Name | Attribute | Description |
| documentElement | JsXmlElement | The root element of the XML document |
| xml | string | Pretty printed XML string |
| xmlBytes | fn(encoding: string) -> ? | Returns a byte[] of the pretty printed XML, using the specified encoding. If no encoding is specified, UTF-8 is used. |
XML Elements can be accessed throught the documentElement property of the XML Document and the XML Element methods selectElements, selectSingleElement and created with addElement.
| Name | Attribute | Description |
| text | string | Text value of the element, for example, <company>CumulusPro</company> would return 'CumulusPro'. Can also be updated, e.g. element.text = 'new value'; |
| nodeName | string | Name of the element, for example, <company>CumulusPro</company> would return 'company' |
| namespacePrefix | string | If the element has a namespace, returns the prefix used for example, <ns:company>CumulusPro</ns:company> would return 'ns' |
| namespace | string | If the element has a namespace returns the namespace URI, for example, <ns:company xmlns:ns="urn:my-urn">CumulusPro</ns:company> would return 'urn:my-urn' |
| attributes | ? | Returns an object containing properties representing the attributes of the element, e.g. <ns:company ns:attr1="1" attr2="2">CumulusPro</ns:company> would return { 'ns:attr1': '1', '{urn:my-urn}:attr1': '1', 'attr2': '2' } |
| xml | string | Pretty printed XML string |
| addAttribute | fn(name: string, value: string, namespaceURI: string) | Adds a new attribute to the element. If namespaceURI is specified, name can contain a prefix, e.g. 'ns:attr1'. For attributes without a namespace, no namespaceURI should be specified. |
| removeAttribute | fn(name: string) | Removes the attribute by name. |
| addElement | fn(name: string, namespaceURI: string) -> JsXmlElement | Adds a child element to the current element. If namespaceURI is specified, name can contain a prefix, for example, 'ns:company'. For elements without a namespace, no namespaceURI should be specified. |
| remove | fn() | Remove the element from the document |
| selectElements | fn(xPath: string, namespaces: ?) -> [JsXmlElement] | Select elements using the given xPath expression, relative to the current element. Optionally, namespaces can be specified for example, { 'ns': 'urn:my-urn', 'ns2': 'urn:my-urn-2' } |
| selectSingleElement | fn(xPath: string, namespaces: ?) -> JsXmlElement | Select the first element matching the given xPath expression, relative to the current element. Optionally, namespaces can be specified for example, { 'ns': 'urn:my-urn', 'ns2': 'urn:my-urn-2' } |
| stringValue | fn(xPath: string, namespaces: ?) -> string | Evaluates the xPath expression relative to the current element. Optionally, namespaces can be specified for example, { 'ns': 'urn:my-urn', 'ns2': 'urn:my-urn-2' } |
| Name | Description | |||||||||||||||||||||
| jqXHR |
done: fn(callback: fn(data: ?, response: ?)) -> jqXHR fail: fn(callback: fn(response: ?, error: string)) -> jqXHR |
|||||||||||||||||||||
| AjaxParameters |
|
|||||||||||||||||||||
| MultiPart |
|
|||||||||||||||||||||
| MultiPartFile |
|
|||||||||||||||||||||
| MultiPartRequest |
|
Simple process flow in Straatos as follows:

Start Event: It must have a name. For example, in the above case 'Start'.
Wait: Once a task is formed in the system, we use a 'Message Receive' task called 'Wait' to wait for some input.
In this sample, a webservice is created that adds a new task in the workflow.
| Name | Where to look | Description |
| createTask | Line 1 | We must check for which webservice the call is. In this case, we expect the webservice to have a /createTask at the end. This allows us to create multiple webservices. |
| straatos.addDocument | Line 4 | The straatos.addDocument creates the task. The parameters specified are the workflow name (Test QA Workflow) and the Start Event Name (Start). The function returns the Straatos DocumentID. |
| response.body | Line 9 | We return the webservice response with a message and the DocumentID. The default Status is always 200 (unless set differently). The default Content-Type is text/plain. This can be overruled by e.g. response.headers['Content-Type'] = 'application/json'; |
if (request.pathSegments[1] == 'createTask') {
// Create a new Task in the workflow named 'Test QA Workflow' at the Start Event 'Start';
// and returns the documentId of the newly created task
var documentId = straatos.addDocument('Test QA Workflow', 'Start');
straatos.startWorkflow(documentId, {});
// response of the webservice with the DocumentID
response.body = "Finished request of type " + request.pathSegments[1] + " DocumentID: " + documentId;
}
In this sample, the indexfield values are submitted as part of the webservice. This script is builds on top of Sample code 1.
We can also add values that are submitted as URI parameters, Headers, and body.
| Name | Where to look | Description |
| FirstName | Line 8 | The workflow index field 'FirstName' gets the value assigned from the body. In this case, the body comes in as a Multipart. |
| LastName | Line 9 | The workflow index field 'LastName' gest the value assigned from the webservice header. |
| InvoiceNumber | Line 10 | The workflow index field 'InvoiceNumber' gest the value assigned from the URI parameter 'InvoiceNumber'. |
if (request.pathSegments[1] == 'createTask') {
// Create a new Task in the workflow named 'Test QA Workflow' at the Start Event 'Start'
// and returns the documentId of the newly created task
var documentId = straatos.addDocument('Test QA Workflow', 'Start');
// Adding Index fields values
straatos.startWorkflow(documentId, {
'FirstName': request.multipart.parameters.FirstName, // value from body, note this only works if the body is a multipart.
'LastName': request.headers.LastName, // value from header
'InvoiceNumber': request.queryParameters.InvoiceNumber // value from URI parameters
});
// response of the webservice with the DocumentID
response.body = "Finished request of type " + request.pathSegments[1] + " DocumentID: " + documentId;
}
In this sample, a PDF Document is attached in the new Straatos Task. This script is built on top of Sample code 1 and Sample code 2.
| Name | Where to look | Description |
| FirstName | Line 7 | Here we get the file from the multipart. We use multipart as the Indexfield 'FirstName' is also provided as part of the (multipart) body. |
| SetDocumentContent | Line 8 | SetDocumentContent adds now the JPG files to Straatos. |
Sample
if (request.pathSegments[1] == 'createTask') {
// Create a new Task in the workflow named 'Test QA Workflow' at the Start Event 'Start'
// and returns the documentId of the newly created task
var documentId = straatos.addDocument('Test QA Workflow', 'Start');
// Adding a document (multipart form post should contain JPG files)
var files = request.multipart.files.map(function (file) { return file.content; });
straatos.setDocumentContent(documentId, files, 'jpg', true, false);
// Adding Indexfields values
straatos.startWorkflow(documentId, {
'FirstName': request.multipart.parameters.FirstName, // value from body
'LastName': request.headers.LastName, // value from header
'InvoiceNumber': request.queryParameters.InvoiceNumber // value from URI parameters
});
// response of the webservice with the DocumentID
response.body = "Finished request of type " + request.pathSegments[1] + " DocumentID: " + documentId;
}
Documents are now created and flow to the process step 'Wait'.
In this code example, we will now find specific documents in the 'Wait' step and forward it in the workflow to the next step (in our case end).
| Name | Where to look | Description |
| forward | Line 1 | We created a new webservice called 'forward' as this is a completely different action to the create task. |
| Test QA Workflow | Line 2 | We want to find a specific document in the workflow 'Test QA Workflow' in the process step 'Wait'. |
| InvoiceNumber | Line 2 | We want to find a (all) documents where the invoice Number is the same as submitted in the header. |
| PaymentStatus | Line 6 | Here we update the document in the workflow. The 'PaymentStatus' is an index field in the workflow that gets updated and the document gets routed to the next stage. |
Sample
if (request.pathSegments[1] == 'forwardTask') {
var documentIds = straatos.findDocuments('Test QA Workflow', 'Wait', {
'InvoiceNumber': request.headers.InvoiceNumber
});
straatos.messageWorkflow('Test QA Workflow', 'Wait', documentIds, {
'PaymentStatus': 'paid'
});
response.body = "Finished request of type " + request.pathSegments[1];
}
In this sample, PDF is uploaded as part of the body, while JPG files are expected to be uploaded as a multipart.
Sample
if (request.pathSegments[1] == 'createTask') {
var documentId = straatos.addDocument('Test QA Workflow', 'Start');
if (typeof(request.multipart) == 'undefined') {
// assumes the body to contain a PDF file
straatos.setDocumentContent(documentId, [request.body], 'pdf', true, false);
} else {
// assumes the multi part files to be JPG
var files = request.multipart.files.map(function (file) { return file.content; });
straatos.setDocumentContent(documentId, files, 'jpg', true, false);
straatos.startWorkflow(documentId, {});
}
}
3rd party application may reject a push API call from the workflow. In this case, the 3rd party application may want to poll for information.
The code below looks for a document with a LastName workflow index field that matches the header 'Name.' If one or more documents are identified, it polls the indexfield values for the first document and returns the field value pairs as part of the body.
Sample
if (request.pathSegments[1] == 'poll') {
var documentIds = straatos.findDocuments('Test QA Workflow', 'Wait', {
'LastName': request.headers.Name
});
if (documentIds.length > 0) {
// console.log('Get variables: ' + JSON.stringify(straatos.getVariables(documentIds[0])));
response.body = JSON.stringify(straatos.getVariables(documentIds[0]));
} else {
response.body = 'Sorry, no documents found';
}
}
documentID (for example from when the document was created with the API further up in the sample), then you can use that particular ID directly in the get Variables call.
The script below uses the getDocumentInfo method on the Adapter and outputs the contents to the console.
Sample
try { var documentInfo = straatos.getDocumentInfo(straatos.documentId); console.log(documentInfo); response.body = 'Ok!'; } catch(err) { response.body = 'Error: ' + err; console.log('error: ' + err); }
The following script gets the merge-pages-pdf additional data (the result of a Merge PDF pages activity) of a certain document and returns that pdf to the browser.
Sample
try {
var documentInfo = straatos.getDocumentInfo(straatos.documentId);
// Return only the additionData objects with a merge-pages-pdf key
var additionalDataObj = documentInfo.additionalData.filter(function(additionalData) {
return additionalData.key == 'merge-pages-pdf';
});
if (additionalDataObj && additionalDataObj.length > 0) {
var mergeUrl = additionalDataObj[0].url + '?w=' + straatos.webServiceKey;
straatos.ajax({
url : mergeUrl,
dataType : 'binary'
}).done(function(pdfRes) {
response.body = pdfRes;
response.headers['Content-Type'] = 'application/pdf';
});
} else {
response.body = 'No merge-pages-pdf data found';
}
} catch(err) {
response.body = 'Error: ' + err;
console.log('error: ' + err);
}
This Script does not show the pdf in the browser, but it uploads the pdf as additional data with a different key, in this case, binary-test-pdf.
Sample
try {
var documentInfo = straatos.getDocumentInfo(straatos.documentId);
var additionalDataObj = documentInfo.additionalData.filter(function(additionalData) {
return additionalData.key == 'merge-pages-pdf';
});
if (additionalDataObj && additionalDataObj.length > 0) {
var mergeUrl = additionalDataObj[0].url + '?w=' + straatos.webServiceKey;
straatos.ajax({
url : mergeUrl,
dataType : 'binary'
}).done(function(pdfRes) {
// Add the document as Additional Data
var output = straatos.addAdditionalData(_documentId, pdfRes, '.pdf','binary-test-pdf');
console.log('uploaded document link: ' + JSON.stringify(output));
response.body = 'File uploaded!';
}).fail(function(jqXHR, error){
response.body = 'An error occurred: ' + error;
});
} else {
response.body = 'No merge-pages-pdf data found';
}
} catch (err) {
response.body = 'error: ' + err;
console.log('error: ' + err);
}
This Script shows how to create a simple XML document.
Sample
var xmlDocument = straatos.newXMLDocument('root');
var rootElement = xmlDocument.documentElement;
rootElement.addAttribute('attr', 'attribute value');
var element1 = rootElement.addElement('element');
element1.text = 'element value 1';
var element2 = rootElement.addElement('element');
element2.addAttribute('elementAttr', '25');
element2.text = 'element value 2';
console.log(xmlDocument.xml);
console.log('xpath string attr: ' + rootElement.stringValue('@attr'));
console.log('xpath string query by attr: ' + rootElement.stringValue('element[@elementAttr = "25"]'));
var elements = rootElement.selectElements('/root/element');
elements.forEach(function (element, index) {
console.log('element at index ' + index + ': ' + element);
});
This Script shows how to create a simple XML document with one namespace with a single prefix used on all elements and attributes.
Sample
var xmlDocument = straatos.newXMLDocument('ns:root', 'https://www.cumuluspro.com/api/1.0');
var rootElement = xmlDocument.documentElement;
rootElement.addAttribute('ns:attr', 'attribute value', 'https://www.cumuluspro.com/api/1.0');
var element1 = rootElement.addElement('ns:element', 'https://www.cumuluspro.com/api/1.0');
element1.text = 'element value 1';
var element2 = rootElement.addElement('ns:element', 'https://www.cumuluspro.com/api/1.0');
element2.addAttribute('ns:elementAttr', '25', 'https://www.cumuluspro.com/api/1.0');
element2.text = 'element value 2';
console.log(xmlDocument.xml);
console.log('xpath string attr: ' + rootElement.stringValue('@ns:attr', { 'ns': 'https://www.cumuluspro.com/api/1.0' }));
console.log('xpath string query by attr: ' + rootElement.stringValue('ns:element[@ns:elementAttr = "25"]', { 'ns': 'https://www.cumuluspro.com/api/1.0' }));
var elements = rootElement.selectElements('/ns:root/ns:element', { 'ns': 'https://www.cumuluspro.com/api/1.0' });
elements.forEach(function (element, index) {
console.log('element at index ' + index + ': ' + element);
});
When you create an interact script, it is open to the web and anyone can access it. A webservice key can be used to secure it for server-to-server interaction.
A webservice key cannot be used to secure the interact API when it is called from a website. The following script shows how an existing authenticated session can be used to check the authentication and roles.
This script assumes that the authentication took place outside of the interact API, for example via the MyHome Login. The interact script below could then be called from a Custom UI.
The session ID must be given as part of the header when calling from the custom Ui. In this script, we also want to check if the user has the right to do the action. As a result, if the user has that role, the calling action will be checked. For example, if a user wants to submit a task, we want to see if the user has the role 'New Job' assigned to him.
Sample
//The interact API is looking for the 'submitTask'
if (activityName == 'submitTask') {
try{
var userId = straatos.validateSession(request.headers['X-Session-Id']); //Validating the Session we received as part of the headers and assigning the result to userId
if (userId > 0) { //if it is a valid session, the returned number is bigger than 0. If no valid session, then the return is 0. hence, we only want to execute the code if it is a valid session.
var reqBody = JSON.parse(straatos.getString(request.body));
var authRoles = straatos.adapter.getAccount({id: userId}).Roles; //get the roles for the user account that has a valid session
var authOk = false; //set the authentication 'authOk' to false as a start.
// check if any of the roles the user has match the 'startevent' that was submitted. If true, the user has the role and hence is authorised to create the Job.
authOk = authRoles.some(function(record){
return record.Name === reqBody.wfstep;
});
if(authOk == true) { //only if the role is for which step the user wants to update a task we will attempt to update the task. If the user is not authorised, we will not update the task
straatos.messageWorkflow('Production Line Process', reqBody.wfstep, [reqBody.taskId], {
//'taskListData': 'test',
'taskListData': JSON.stringify(reqBody.taskListData),
'taskDetails': JSON.stringify(reqBody.taskDetails),
'action': reqBody.action
});
}
else{
response.body = '';
response.status = 401; //respond with 401 for issues with Authorisation
}
}
else{
response.body = '';
response.status = 401; //respond with 401 for issues with Authorisation
}
}
catch(err){
console.log('Error: ' & err.message);
response.status = 501;
response.body = err;
}
}
Each application has its own set of web services with its own parameters, headers, body requirements. The challenge is to make them talk to each other.
There are three ways to make that happen:
Knowledge & skills to change the API
- Changes affect other users of the web service.
- 3rd party product which can not be changed or requires the vendor to make changes.
- Effort and cost to make the changes.
Changes affect other users
- Duration, cost, and effort to develop a customer-specific web service (days to weeks).
- Agility to change the web services.
- No customer self-service to change the web services.
3rd Party Platform (such as Zapier/Mulesoft)
- Different geolocation
- Not the feature set required
- Additional subscription/cost
- Additional service/company.
Dedicated web service
- Effort & cost to build an entire/independent web service.
- Hosting & monitoring of the web service
- Code maintenance
- Extensive testing.
What incoming web service calls are supported?
The Straatos Interact API supports POST and GET calls.
All parameters, header, and body information are passed to the Interact Script and can be used in the script to determine what to do with the incoming call.
Yes, there is no limit on the number of different web service calls that can be defined in a single Straatos Interact Script.
Here an example for 3 web service calls:
CreateTask will create a new Task in the Workflow. See Sample Code.
ForwardTask will forward a specific task in the workflow to the next step.
RetrieveTaskInfo can return data from the workflow task to the 3rd party application, for example, a Name, Date of Birth, or a License Number that was extracted in the workflow from the AI Extraction engine.
The security can be built right into the Straatos Interact Script. The approach may depend on the application used. For example:
In summary, Authentication can be as secure and restrictive as need to be for the process.
Yes, all communication will be using SSL encryption.
Yes, the Straatos Interact Script allows for the data to be encrypted on top of SSL encryption. The incoming data can be decrypted within the Interact Script (if necessary, for processing the data) or the data can be passed encrypted to the Straatos process.
If required for processing, the data can then be decrypted within the process or passed straight through without decryption. The decryption requirements depend on what action the Straatos process has to take on the data.
The Organisation ID is a unique identifier that defines your organization and is also used as part of the request URL when consuming the API.
The new organisation will appear on the dashboard.