# STRAATOS CLOUD BPM

Welcome to the CumulusPro Help and KnowledgeBase Site

This is where you can find documentation for the CumulusPro Platform. Browse the categories on the left to find what you are looking for.

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>RELEASE NOTES</td><td><a href="/pages/-MgjIesbjC1Mf9TuIVsn">/pages/-MgjIesbjC1Mf9TuIVsn</a></td></tr><tr><td>GETTING STARTED WITH STRAATOS</td><td><a href="/pages/-Mg3a_jLfpKeWcspVIAG">/pages/-Mg3a_jLfpKeWcspVIAG</a></td></tr><tr><td>CONFIGURATION GUIDE</td><td><a href="/pages/04LQOaXTMvSPZH3RQHQM">/pages/04LQOaXTMvSPZH3RQHQM</a></td></tr><tr><td>STRAATOS ARCHIVE</td><td><a href="/pages/kWczpgwhydqZxga2l848">/pages/kWczpgwhydqZxga2l848</a></td></tr><tr><td>DEVELOPER GUIDE</td><td><a href="/pages/-MgO_oNvpTA-q0w-yjHy">/pages/-MgO_oNvpTA-q0w-yjHy</a></td></tr><tr><td>ENTERPPRISE SINGLE SIGN ON</td><td><a href="/pages/CrmxcmyQKfZ9FD8GawOq">/pages/CrmxcmyQKfZ9FD8GawOq</a></td></tr></tbody></table>


# RELEASE NOTES

Welcome to our Release Notes page, your go-to resource for staying informed about the latest updates to our products.

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>DECEMBER 2025</td><td><a href="/pages/YUea6SHS281z051iaHjC">/pages/YUea6SHS281z051iaHjC</a></td></tr><tr><td>NOVEMBER 2025</td><td><a href="/pages/YUea6SHS281z051iaHjC">/pages/YUea6SHS281z051iaHjC</a></td></tr><tr><td>OCTOBER 2025</td><td><a href="/pages/w0muOeWKYsqa5UnJUDDY">/pages/w0muOeWKYsqa5UnJUDDY</a></td></tr><tr><td>SEPTEMBER 2025</td><td><a href="/pages/qatn3JOhvhA0A9fIiEon">/pages/qatn3JOhvhA0A9fIiEon</a></td></tr><tr><td>AUGUST 2025</td><td><a href="/pages/dK3w2vyNvMUqZm4L1700">/pages/dK3w2vyNvMUqZm4L1700</a></td></tr><tr><td>MARCH 2025</td><td><a href="/pages/Sya84Nvia01b7zjfPls6">/pages/Sya84Nvia01b7zjfPls6</a></td></tr><tr><td>DECEMBER 2024</td><td><a href="/pages/GGToqTvuEEXy9WCOTFfA">/pages/GGToqTvuEEXy9WCOTFfA</a></td></tr><tr><td>OCTOBER 2024</td><td><a href="/pages/tCMhblotdXyyjZef5x0O">/pages/tCMhblotdXyyjZef5x0O</a></td></tr><tr><td>JUNE 2024</td><td><a href="/pages/5HsTwsedsRCgnsctJDhZ">/pages/5HsTwsedsRCgnsctJDhZ</a></td></tr><tr><td>APRIL 2024</td><td><a href="/pages/0122TO3P94SHlUGmpKrX">/pages/0122TO3P94SHlUGmpKrX</a></td></tr><tr><td>FEBRUARY 2024</td><td><a href="/pages/dOJ56XpuHv5iJJXFsdLK">/pages/dOJ56XpuHv5iJJXFsdLK</a></td></tr><tr><td>JANUARY 2024</td><td><a href="/pages/GicP6G2htqEgyJ4RjmUR">/pages/GicP6G2htqEgyJ4RjmUR</a></td></tr><tr><td>DECEMBER 2023</td><td><a href="/pages/UKIfwQxiJgcygOCPWget">/pages/UKIfwQxiJgcygOCPWget</a></td></tr><tr><td>NOVEMBER 2023</td><td><a href="/pages/2OPfj620R2WMs3CJTIDl">/pages/2OPfj620R2WMs3CJTIDl</a></td></tr><tr><td>FEBRUARY 2023</td><td><a href="/pages/ubwkV417P7jSRybQJj9O">/pages/ubwkV417P7jSRybQJj9O</a></td></tr><tr><td>JULY 2021</td><td><a href="/pages/PQkmj97dYd6SzeWm4St1">/pages/PQkmj97dYd6SzeWm4St1</a></td></tr><tr><td>JANUARY 2019</td><td><a href="/pages/Sk2tB4BAEEMiiSf20CU9">/pages/Sk2tB4BAEEMiiSf20CU9</a></td></tr><tr><td>APRIL 2018</td><td><a href="/pages/rthjigGUNuw2JLMNpb7H">/pages/rthjigGUNuw2JLMNpb7H</a></td></tr><tr><td>DECEMBER 2017</td><td><a href="/pages/k2XQgx7lorr8wa8ZOZRu">/pages/k2XQgx7lorr8wa8ZOZRu</a></td></tr><tr><td>NOVEMBER 2017</td><td><a href="/pages/qPgddEHj82ynnIVV133v">/pages/qPgddEHj82ynnIVV133v</a></td></tr><tr><td>OCTOBER 2017</td><td><a href="/pages/Pq0AUcKWNQPFeCGslW1R">/pages/Pq0AUcKWNQPFeCGslW1R</a></td></tr></tbody></table>


# March 2026

Discover March 2026 improved features

### General Improvements

#### **Form Designer  - 3/3/2026**

* Improved German translation for Form Designer labels in the user management.
* Removed 'USD' currency in the payment configuration in Form Settings.
* Added a loading indicator below the Gemeinde field selection and Address field.
* Improved the validation check for the Street Name in the Address field.
  * Added a behaviour where the validation checkbox will be set to red if unchecked.
* Improved the Form Steps design for large number of steps.
  * Only the active step will show the title, the rest of the inactive title will be hidden.
  * Title of the Inactive steps will only show when a user hovers over them.

***

### Bug Fixes

#### **Form Designer  - 3/3/2026**

* Fixed an issue where there would be an extra \* symbol in the File Upload type when set to mandatory
* Fixed an issue where the Form Settings could not be saved when setting the Email Notification to 'No'.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# February 2026

Discover February 2026 improved features

### General Improvements

#### **Form Designer  - 17/2/2026**

* Improved German translation for Form Designer labels.
* Added 'External Email Notification' feature for users
* Added 'Canton' field which copies the main form onto all the gemeinde's within the selected canton.
* Added 'Form Settings' under the 'Forms' navigation menu which allows for custom configuration for the tenant of the copied form.
  * Added the option to set the form as 'active' or 'inactive' for the tenant.
  * Added the option to set the 'active' or 'inactive' text for the tenant.
  * Added the option to set the 'Payment Configuration' for the tenant.
  * Added the option to set the 'Delivery Configuration' for the tenant.
  * Added the option to set the 'Email Notification' for the tenant.
* Added 'Lieferschein erstellen' button which downloads a delivery docket document from submitted Form Designer tasks.
* Removed Payrexx API Configuration from Payment Configuration view.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# January 2026

Discover January 2026 improved features

### General Improvements

#### **Form Designer  - 12/1/2026**

* Improved the time out session to prevent users from being logged out when making lengthy changes.
* Improved date fields display to follow local language settings.
* Improved the downloaded preview report which previously cut off text at the end of a page.
* Added 'Date Received' column to display when a task was submitted in the form navigation list.
* Added 'Do not display from title' option to hide the form title.

***

### Bug Fixes

#### **Form Designer  - 12/1/2026**

* Fixed an issue where the Address field type was not properly validating the street address.
* Fixed an issue where the Phone Number field type did not display an error message if the inputted value was wrong.
* Fixed an issue where the user list  would display all the users from different tenants.
* Fixed an issue where tags would not be able to be deleted or would still display when deleted.
* Fixed an issue where the dropdown list of Gemeinde and RZA was cut off.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# December 2025

Discover December 2025 improved features

### General Improvements

#### **TaskUI (EU) - 1/12/2025**

* Improve Archive Sorting functionality.

#### **Effektif-Connector (EU) - 1/12/2025**

* Security Update & Maintenance.

#### **Adminpanel (EU) - 1/12/2025**

* Security Update & Maintenance.

#### **Straatos Adapter (EU) - 1/12/2025**

* Security Update & Maintenance.

#### **Service Tasks (EU) - 1/12/2025**

* Security Update & Maintenance.

#### **Communicator (EU) - 3/12/2025**

* Maintenance.

#### **Effektif-Connector (GovCH) - 3/12/2025**

* Security Update & Maintenance.

#### **Adminpanel (GovCH) - 3/12/2025**

* Security Update & Maintenance.

#### **Straatos Adapter (GovCH) - 3/12/2025**

* Security Update & Maintenance.

#### **Communicator (GovCH) - 8/12/2025**

* Maintenance.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# November 2025

Discover November 2025 improved features

### General Improvements

#### **Form Designer  - 11/11/2025**

* Improved the validation error message for Regex function to stop 'flickering'.&#x20;

***

### Bug Fixes

#### **Form Designer  - 11/11/2025**

* Fixed an issue where conditional fields with the 'Hide' attribute with would not display the values of processed  forms.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# October 2025

Discover October 2025 improved features

### General Improvements

#### **Straatos API V2 - 30/10/2025**

* Security Update & Maintenance.

***

### Bug Fixes&#x20;

#### **Form Designer - 11/11/2025**

* Fixed an issue where the help text size was inconsistent to other text.
* Fixed an issue where the file upload description did not display.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# September 2025

Discover September 2025 improved features.

### General Improvements

#### **TaskUI - 10/9/2025**

* Added a 'ViewAllTasks' function as part of the User Group Function.

#### **Archive  - 10/9/2025**

* Improved Archive UI Advanced Search allowing for customised field order.

***

### Bug Fixes

#### **TaskUI  - 10/9/2025**

* Encountered an issue where clicking on the 'Profile' tab would kick users out of the session for Single-Sign-On users. The 'Profile' option is now disabled for SSO users.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# August 2025

Discover August 2025 improved features

### General Improvements

#### **Form Designer - 3/8/2025**

* Roles concept:
  * Role-based permissions introduced to control who can create, edit and view forms.

* Table feature:
  * Allows users to dynamically add rows of related data. e.g Entering multiple child records under a parent form.

* Activate/Deactivate button:
  * Users can now activate or deactivate forms without deleting them.

* Delete form function:
  * Users can now delete forms, including all previously submitted data.

* Search on list of forms:
  * A search bar is now available to quickly find forms by name or keyword.

* Tags features:
  * Forms can now be tagged for easier categorization and filtering.

* File upload improvements:
  * Setting different types of files/file size are now supported.

* Custom error messages:
  * Developers can now specify custom validation error messages per field.

* Change history display:
  * Users can view edit history and restore previous versions of the form.

* Date field restrictions:
  * Date fields now support restrictions (e.g. no past dates or future limits).

* Duplicate button:
  * Users can duplicate an existing form to speed up new form creation.

* Export and import:
  * Forms can now be exported and imported across environments.

***

### Bug Fixes

#### **Form Designer - 3/8/2025**

* Form Designer would automatically translate words.&#x20;
* Form Designer title was not aligned with the rest of the text.

#### **TaskUI - 18/08/2025**

* Fixed an issue where clicking on 'Forgot Password' only refreshes to the login page.
* AdvancePdfViewer keeps refreshing when selecting a page.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# March 2025

Discover March 2025 improved features.

### General Improvements

#### **Task UI - 31/03/2025**

* Various Security Updates.

***

### Bug Fixes

#### &#x20;**Straatos API - 31/03/2025**

* Resolved an issue causing performance delays when loading groups with a large number of users, document types, and organizational units.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# December 2024

Discover December 2024 improved features.

### Bug Fixes

#### **TaskUI - 09/12/2024**&#x20;

* Resolved an issue where task details failed to display in split view mode.
* Resolved caching issues when submitting documents in a short time interval.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# October 2024

Discover October 2024 new & improved features.

### General Improvements

#### **TaskUI (GovCH) - 29/10/2024**

* New PDF Viewer:
  * shade of active page thumbnail more prominent.
* Task Details:
  * Dynamic sizing of the document viewer and index field display area
  * Dynamic sizing of the indexfield accross the available space for indexfields

#### **Form Designer - 29/10/2024**

* Optimized the distance of the description of a field.
* Color schema for Date Picker adjusted to the customizable color design.
* English Translation for AHV Number error message and Address field.
* Configurable Email notification option when a new form is submitted.
* The asterisk (\*) indication of the mandatory field now follows the font color defined.

#### **TaskUI - 14/10/2024**

* New PDF Viewer which displays thumbnails. To use the PDF Viewer, the TaskUI Settings need to be changed, otherwise it shows the current viewer.
* Splitting of PDF documents based on Thumbnail selection.
* Indexfield values can be displayed in different colors based on rules.
* Lock task display in tasklist if another user is editing the document.
* History displays only the user tasks.

#### **Archive - 14/10/2024**

* When multiple filetypes are in a task, it displays the first PDF file in the viewer when loading the task.
* Improve UI speed when opening the Advanced Filter.
* Advanced Filter
  * Allow only to enter numbers in number fields and dates in date fields.
  * Range search for number fields is added.

#### **Straatos API V2 - 01/10/2024**

* Faster search results when returning many tasks from the archive.
* New Endpoint PUT GetArchiveDefinition to retrieve the archive definition.

***

### Bug Fixes

#### **Form Designer - 29/10/2024**

* Bug that 'View form on' link was not displayed after the initial saving of a new form.
* Form Designer Navigation disappears when opening the form in a separate tab.

#### **Archive - 14/10/2024**

* Search query not being cleared when going to the Advanced Filters.
* The file name was displaying the GUID instead of the filename.
* The indexfield display uses now more of the available screenspace to display the field value. So longer indexfield values are visible to the users.

#### **Straatos API V2 - 01/10/2024**

* Resolved an issue that affected search functionality when using an OR clause.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# June 2024

Discover June 2024 new & improved features

### General Improvements

#### **Task UI - 17/06/2024**

* Organizational Unit and Document types are not displayed in Group if they are not defined.
* Print function in the viewer for PDF files.
* Document types allow users to add multiple fields.
* Security updates by updating libraries to the latest version.

#### **Straatos - 17/06/2024**

* Security updates by updating libraries to the latest versions.
* Effektif:&#x20;
  * Allow removal of invalid tasks.
* Autocleanup of LogStats for documents deleted more than 1 year ago.
* Purge optimized (background process).
* DocumentPages extracted (reduce performance consumption on Straatos process for preview image generation).

#### **Form Designer - 17/06/2024**

* Introduced Form Designer.

***

### Bug Fixes

#### **Task UI - 17/06/2024**

* Resolved display issues with numeric and currency values in the Dutch localization.

#### **Straatos - 17/06/2024**

* Redact for rotated pages (bugfix).
* Several bug fixes.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# April 2024

Discover April 2024 new & improved features.

### General Improvements

#### **Task UI - 17/04/2024**

* Sum Function for Tables.
* Improving usability to remove index fields in the document type configuration.

#### **Archive - 17/04/2024**

* Added range search functionality for date and integer fields.
* Updated amount format for Switzerland.

#### **Straatos - 15/04/2024**

* SetSecret and GetSecret added for Workflow Script Task.

***

### Bug Fixes

#### **Task UI - 17/04/2024**

* Resolved date-time comparison issue.
* Resolved ReleaseTaskLock API error in TaskUI.
* Resolved an issue in MS O365:
  * Straatos for Outlook, where the email body was uploaded as an .eml file but was not visible in TaskUI.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# February 2024

Discover February 2024 new & improved features.

### General Improvements

#### **Task UI - 26/02/2024**

* Implemented "Hot Keys" in TaskUI to allow keyboard shortcuts for task validation:
  * Alt + Enter → Approve task and move to the next task.
  * Alt + R → Reject task and move to the next task.
  * Ctrl + S → Save task.

{% hint style="info" %}
This functionality must be configured by validation task.
{% endhint %}

* Task Locking:
  * When a user is working on a task, it will be locked to prevent other users from accessing it.

* Task Unlocking:
  * Added the ability to unlock a task in the workflow when needed.

#### **Straatos Archive Help Page - 09/02/2024**

* Updated version of the Straatos Archive Help page for customers and partners.
* The guide provides instructions on installing and configuring a Straatos Archive in a customer's Azure environment.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# January 2024

Discover January 2024 new & improved features.

### General Improvements

#### **Task UI - 22/01/2024**

* Caching of Search and Filter:
  * When a user searches for tasks or filters based on columns, TaskUI will cache the search criteria.
  * If the user opens a task and then returns to the task list, the cached filter/search will be applied to display the documents.

* Assign and Unassign Tasks:
  * Added the ability to configure buttons in TaskUI to assign or unassign tasks to the logged-in user.
  * Assigned tasks can be displayed in a separate folder (e.g., "My Documents").

* Compact View of Task List:
  * Updated design to display more lines in the task list.

* EML File Support in TaskUI Viewer:
  * Users can now select .eml files (email documents), and they will be displayed in the TaskUI viewer.

* Increased Task Display Limit:
  * Users can now set 1,000 tasks per page in TaskUI.

* Advanced Search on Archive:
  * Displays all index fields.
  * Allows searching in ranges and provides additional search options.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# December 2023

Discover December 2023 new & improved features.

### General Improvements

#### **Task UI - 17/12/2023**

* Sortable Task List:
  * Task list results can now be sorted in ascending or descending order based on the timestamp.

* Sorting of Comments:
  * Comments can now be sorted in ascending or descending order within the configuration settings.

#### **Straatos - 17/12/2023**

* Renaming Additional Data in Script:
  * The name of additional data can now be changed within a script task.

* Split Function for Additional Data:
  * A PDF file with additional data can be split into multiple files via a script task.
  * The split files can be added to the same task or assigned to different tasks.

#### **Straatos API V2 - 17/12/2023**

* Task Sorting:
  * The Tasks API can now return tasks sorted in ascending or descending order based on the timestamp.

* Info API Enhancements:
  * The Info API now returns the configuration of a specific user task for tables.
  * It considers user task-specific settings and overrides global settings.
  * Example: If a table is globally set to 'hidden = false' but a user task sets it to 'hidden = true', the Info API now reflects this change.

* Privileged Access Management:
  * New Privileged Access Management API allows defining admin functionalities at the organization level.
  * Users can enable/disable privileged access when performing admin tasks.
  * This applies to Straatos API v2 functions.

* Unassign from User:
  * Added an API call to unassign a document from a user.

#### **Archive API Enhancements - 17/12/2023**

* Delete Document:
  * Introduced an API to delete a document from the archive.

* Set Document Lifecycle:
  * Users can define a document lifecycle duration, ensuring documents are automatically removed from the archive once the lifecycle ends.
  * This setting can be configured globally and overridden per document if needed.

* Set Legal Hold:
  * Added the ability to set a legal hold on an archived document.
  * If legal hold is enabled (true), the document will not be deleted from the archive, even when the lifecycle ends.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# November 2023

Discover November 2023 new & improved features.

### General Improvements

#### **Task UI - 22/11/2023**

* Improved the loading speed of the task list when displaying 250 or more tasks.

***

### Bug Fixes

#### **Straatos API - 23/11/2023**

* A fix has been deployed to resolve timeout issues in script tasks for the following functions:
  * ftpPut.
  * addAdditionalData.
  * addAdditionalDataWithURL.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# February 2023

Discover February 2023 new & improved features

### OCR Engine Upgrade

* Replaced ABBYY OCR and FineReader with Microsoft Azure Cognitive OCR for improved text recognition.

***

### New Azure Archive Service

* Enables storing documents in a customer's Microsoft BLOB storage.

***

### User Task UI V2

* Improved UI with enhanced look and feel.
* Customizable Task UI to better suit business needs.

***

### Multi-Tenant Workflows

* Enables faster solution deployment and simplifies maintenance.

***

### Microsoft Office 365 Email Connector

* Faster and more reliable email import into CumulusPro workflow.

***

### Azure Functions Enhancements

#### PDF Redaction

* New function for redacting PDF documents.
* Barcode Recognition: Improved barcode recognition for documents.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# July 2021

Discover July 2021 new & improved features.

### General Improvements

* Monitor List Enhancements.
* Activities in the Monitor List are now sorted alphabetically.
* Search functionality added to quickly find an activity.
* Scrolling enabled to view all processes in the list.
* Task Table Management.
* Add a table to a task.
* Update a table in a task.
* Delete a table from a task.

***

### Straatos Monitor Enhancements

* The "Move all to" workflow steps are now ordered alphabetically, with an automatic type-ahead filter option.
* Added the ability to start a task directly from the Straatos Monitor.
* A new "Files" column displays all task-related files, including the Original File and additional data.
* The script log column has been moved before all index fields for quicker access.

***

### Workflow Enhancements

* Copy comments between the main flow and subflow.
* Copy table values to and from the subflow.
* A workflow task can now be started directly from a script task.
* Expanded file attachment options for emails sent via SendGrid. Any additional data file can now be included.
* Workflow reports now allow exporting history for a specific workflow step and/or a specific document ID.

***

### Workflow Monitor - Recycle Bin

* A recycle bin is now available. Deleted documents will first be moved here before permanent deletion. Documents can be restored back to the workflow.

***

### OCR & Barcode Recognition Improvements

* Azure Machine Learning OCR is now an option for creating searchable PDFs. Contact us for more details.
* Updated Barcode Engine with improved barcode recognition, including support for reading barcodes from PDFs. The existing barcode engine will remain until all processes are migrated.

***

### Straatos Archive and Retrieval Solution

* First phase (Archive) implemented. Allows tasks, including documents, index fields, and comments, to be stored in Azure BLOB storage.
* A Retrieval option will be available in a future release via TaskUI.

***

### Improved Email & FTP Import

* Test button added in the configuration to check server connection and accessibility.

***

### GetFiles API

* Instead of using an AJAX call to get file content in a script task, a single line GetFiles function is now available.
* This function is available in both Script Task and Interact API.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# January 2019

Discover January 2019 new & improved features.

### SAML-Based Single Sign-On (SSO) with Microsoft Azure Active Directory

* Straatos now supports Single Sign-On (SSO) via Security Assertion Markup Language (SAML).
* Users do not need to sign in again if they have already been authenticated by Microsoft Azure Active Directory (IdP).
* User accounts are automatically created in Straatos upon the first successful login.

***

### Custom Password Policy

* Administrators can define separate password policies for different user groups.
* Policies can enforce:
  * Maximum login attempts.
  * Session timeout limits.
  * Password history restrictions (preventing reuse of old passwords).
  * Minimum password age enforcement (forcing users to change passwords periodically).

***

### Enhanced Straatos Security

* New user password policies include:
  * Minimum password length.
  * Password complexity requirements (e.g., passwords cannot contain usernames).
  * Weak password checks.

* Incremental-delayed login enforcement:&#x20;
  * After three unsuccessful attempts, login attempts will be gradually delayed, in addition to the existing account lockout feature.

***

### User Management Enhancements

* New "Manage User" Role:
  * Users with this role can:
    * Create new user accounts.
    * Assign roles.
    * Enable/disable accounts.
    * Reset passwords.

* Enable/Disable User Accounts:
  * Administrators and users with the "Manage User" role can now enable or disable user accounts.

***

### Performance & System Improvements

* Improved Backend Performance:
  * A new queuing framework has been implemented to handle high-volume task processing and backend operations more efficiently.

***

### Enhanced iConnector Framework Security

* A new security feature enforces authenticated user sessions for document uploads.
* Beneficial for mobile applications built using CumulusPro Mobile SDK, ensuring that only authenticated Straatos users can upload documents.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# April 2018

Discover April 2018 new & improved features.

### Bug Fixes

* Password Reset for Users Without Email
  * Users without an email address can now reset their passwords after logging in.
* Convert JPG to PDF
  * Ability to generate PDF output from JPG images.
* Convert PDF to JPG
  * Ability to generate JPG output from PDF files.

***

### Customization Of White-Label

* White-Label Service
  * Ability to white-label the Straatos MyHome and Admin Panel interfaces to match a customer’s corporate branding.
  * Customizable elements include:
    * Favicon.
    * Company logos.
    * Color themes and fonts.
    * Custom URLs.

***

### Language Localization

* New "Export from" and "Import to" Excel functions added in the Admin Panel (under Group Settings).
* This feature simplifies language translation of the MyHome interface:
  * Export the current web labels in English (Excel format).
  * Translate the text into any desired language.
  * Import the edited Excel file back into the Admin Panel for implementation.

***

### Security & Access Control

* Document Time-Based Access Control:
  * Designed for server-to-server integration with third-party web services that do not support token-based security.
  * Process administrators can configure a time-limited document access window (within minutes from creation).
  * Once the third-party service processes the document and returns results, the document becomes inaccessible after the set duration expires.

***

### Processing & Workflow Automation

* OMR and OCR Zonal Setup - User Interface:
  * A new graphical template configurator has been added for setting up OMR (Optical Mark Recognition) and OCR (Optical Character Recognition).
  * Simplifies forms processing setup for administrators.

* Unzip Functionality:
  * The Unzip function is now available in Task Scripts and Interact API libraries.
  * Uploaded ZIP files in Straatos can be automatically extracted, and the content (images, text files, etc.) can be used in workflow processes.

* Configurable User Viewing of Documents in Tasks:
  * Process Administrators can now configure which types of documents are displayed to users when they work on their tasks in MyHome.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# December 2017

Discover December 2017 new & improved features.

### Bug Fixes

* Infinite Loop Prevention:
  * In previous versions, it was possible for tasks to enter an infinite processing loop.
  * In this release, Straatos automatically aborts task processing if a task passes through 300 workflow steps without termination.

***

### Customization & UI Enhancements

* Custom UI for MyHome:
  * Users can now customize their user interface within MyHome to display:
  * Index Fields.
  * Buttons.
  * Viewer:
    * Custom UI can be implemented in two ways:
      * Providing a link to a hosted site.
      * Uploading a ZIP file containing the webpage contents.
    * This allows businesses to offer user experience optimized for specific processes.

***

### Performance & Workflow Optimization

* Throttle for Automated Tasks:
  * By default, Straatos processes 10 tasks per activity concurrently.
  * This version introduces the ability to manually adjust task throttling to limit parallel document processing.
  * Useful for external engines with limited performance capabilities.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# November 2017

Discover November 2017 new & improved features.

### Global Login Enhancement

* Unified Login Experience:
  * Users can now log in directly from [CumulusPro.com](https://www.cumuluspro.com/) to access Straatos.
  * Upon logging in, users are automatically directed to the correct data center based on their credentials.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# October 2017

Discover October 2017 new & improved features.

### Bug Fixes

* Configurable type-ahead dropdowns now display all entries.

* Long workflow & usernames no longer overlap buttons in the Admin Panel UI.

* Web Validation:
  * Resolved ‘bad gateway error’ when splitting documents.

* Workflow Import:
  * Resolved issues when importing workflows with expanded subprocesses.

* Copy & Paste in Process Designer:
  * Resolved issues in Internet Explorer 11.

* My Home Filter:
  * Resolved issues when using special characters.

* Documentation Links:
  * Resolved issue when pressing "OK" closed the dialog unexpectedly.

* Process Designer Stability:
  * Resolved freezing issue when a user with workflow design rights edits a workflow without clicking "Edit Workflow" first.

* Process Monitor & PDF Reports:
  * Resolved missing workflow arrows.

* Auto-Complete Alignment:
  * Resolved display misalignment during browser resizing.

* Admin Panel Errors:
  * Resolved error when users with Monitor View Rights open a workflow.

* Workflow Publishing Bug:
  * Resolved issue where users with the designer role couldn't publish workflows.

***

### Security & Authentication

* 2-Factor Authentication (2FA) with Google Authenticator:
  * Can be enabled per user, group, or organization wide.
  * If enforced at the organization or group level, all users must use 2FA to log in.

***

### Process Designer Enhancements

* Reference Point Feature:
  * A reference point is now available at the top-left corner of the designer canvas.
  * Users can reset the canvas position using a button (above the zoom-in/out buttons).

***

### User Interface & Experience

* My Home Task Enhancements:
  * Task ID, Workflow Step, and Workflow Name can now be used in sorting & filtering options.

* Tooltips & Onboarding Messages:
  * Pop-up messages now appear for:
    * New features.
    * Product updates.
    * 2FA setup instructions.

{% hint style="info" %}
These messages appear only once per user.
{% endhint %}

* Customizable Table Names:
  * In My Home, the ‘Form’, ‘Collaboration’, and ‘History’ tabs can now be renamed.

***

If you have any questions, please contact CumulusPro support at <support@cumuluspro.com>.


# Straatos Overview

CumulusPro Straatos is a cloud-based platform for Business Process Management (BPM) and Workflow Automation. It allows for quick digital transformation of business processes and content. Users can design, execute, and manage business processes using BPMN 2.0 standards, all within a few days.

### **Straatos Architecture**

<div align="center"><figure><img src="/files/Vybbwi3NMrzA38QQLzRe" alt=""><figcaption></figcaption></figure></div>

***

### **Optimized for the Cloud Infrastructure**

Straatos BPM is fully optimized for cloud infrastructure, enhancing its accessibility and performance across various locations. Users can access the platform from anywhere with an Internet connection.

#### Key features include

* Security and Reliability:
  * The platform uses Microsoft Azure’s global network of data centers, which are:
    * ISO/IEC 27001 certified for maintaining high-security standards.
    * Compliant with Safe Harbor principles to ensure proper handling of European citizens' personal data.

* Scalability:
  * Leveraging the scalability of Azure, Straatos can support any number of accounts and manage concurrent processes effectively, accommodating growing business needs seamlessly.

***

### **Multi- channel Input Infrastructure**

Straatos offers a multi-channel input infrastructure that supports a wide array of input methods tailored to modern business needs. These methods include web scan, email attachments, electronic document imports (e.g., e-invoices), mobile capture, and web form scans. This flexibility ensures seamless integration into various stages of business processes.

#### Export and Integration Capabilities

* Support for All Formats:&#x20;
  * Straatos can export data in multiple formats including CSV and XML, allowing easy integration with existing back-end systems such as ERP and accounting systems.

* Secure iConnector Framework:&#x20;
  * This framework securely transfers images and data directly to Line of Business (LOB) applications like Document Management Systems (DMS) or file repositories.

#### Real-Time Processing Features

* Verification of user access.
* Retrieval and validation of metadata fields.
* Real-time document upload to business systems.
* Immediate notifications upon task completion.

#### Compatibility and Accessibility

* The suite of Straatos web and mobile applications is compatible across Windows and Apple OS X devices.
* The mobile app supports devices operating on Apple iOS and Android, with a version for Windows to be released soon.
* This cross-platform compatibility enhances collaboration among employees, suppliers, and customers using various workstations, smart devices, and scanners.

***

### **Web-Scan application**

The browser-based scanning application enables distributed capture of documents and can be deployed anywhere with an Internet connection.

***

### **Mobile Capture**

This mobile capture app is specifically designed to capture document images easily from the mobile device. There is no need to deal with complex configurations and adjustments. Both CumulusPro’s Mobile Document Capture App and SDK works seamlessly with the Straatos BPM platform.

***

### **Universal web-based Validation, Quality Control and Approval client**

The role-based web application enables users to access their work from anywhere. Depending on their assigned role(s), users can scan, validate information, approve or reject workflow tasks while viewing the relevant document images. Straatos universal web application includes automated validation mechanism that help to ensure quality and accuracy of image and information, supports complex data validation and automated matching for invoice processing.

***

### **Social Media chat bots**

Straatos integration with Facebook messenger platform enables scripted business conversation through the social media platform and initiates business processes on Straatos. For example a mortgage loan application and guided by the bot, customers can send supporting documents or provide the required information when prompted.

***

### **Connect to Any Application on the Cloud**

Through cloud automation platform Zapier, Straatos BPM Platform integrates with more than 700 cloud applications.

***

### **Design Business Processes with the BPMN 2.0 Process Designer**

The Straatos Process Designer is a versatile tool designed for both process-aware professionals and IT specialists. It facilitates the design and execution of business processes ranging from simple to complex. Users can easily create BPMN flows through a user-friendly drag-and-drop interface, enhancing productivity and collaboration.

#### Key Features of the Process Designer

* Interactive Design Tools:
  * Drag and drop new input channels, work steps, and routing rules within the process flow diagrams.
  * Role-Based Assignments:
    * Assign work activities and documents to specific groups, roles, or individual users.
  * Component Reusability:
    * Allows for the reuse of components in new processes, improving efficiency.

#### Accessibility and Usability

* Web Browser Access:
  * All administrative functions, including the Process Designer, are accessible through standard web browsers.

* Intuitive Interface:
  * The interface is attractive and easy to use, reducing the need for expensive training.

#### Unique Advantages

* No Coding Knowledge Required:
  * Unlike standard BPMN 2.0 designers, the Straatos Process Designer enables any process owner to design and run business processes immediately on the platform without needing coding expertise.

* Template Saving:
  * Users can save templates for designing future processes, adding a layer of convenience and forward-planning capability.

***

### **Document Transformation and Data Extraction Technologies**

Straatos' automatic document classification engine uses machine learning and AI technologies to identify and categorize documents, such as invoices, based on their content. This system efficiently processes both scanned images and Adobe PDFs. Once classified, documents are swiftly and automatically routed to appropriate processes, repositories, or individuals within the organization, facilitating streamlined operations.&#x20;

***

### **Exception Handling**

Straatos BPM streamlines business processes and reduces both costs and manpower by efficiently managing exceptions. For example, if an insurance claim lacks necessary information, rather than requiring an employee to contact the applicant, Straatos automates the process by sending an email with a hyperlink. This allows the applicant to directly input the missing information via a secure, temporary access that does not require setting up a new user account for one-time use.

***

### **Automated Notifications to Speed up Processes**

Straatos BPM allows for the configuration of business rules and conditions that trigger notifications to specific users or user groups through email, SMS, or chat. This feature enables group supervisors to either send targeted messages to individual team members or broadcast messages to the entire team, facilitating effective communication and prompt action.

{% hint style="info" %}
Some features may require additional subscription from 3rd party providers.
{% endhint %}


# Best Practice for Straatos Process Modelling

This article provides process modelers some guidelines to build clear and effective models compliant with the BPMN standard.

The **Business Process Model and Notation (BPMN)** standard provides organizations with a graphical representation of their internal business processes, ensuring clear and standardized communication of procedures.

However, simply using BPMN does not guarantee effective process modeling. The **clarity and accuracy** **of a BPMN model** depends on:

* How modelers interpret business conditions.
* The way they structure workflows.

To ensure effective communication and implementation, BPMN models should be well-structured, easy to understand, and logically organized.

### **BPMN Modeling principles**

When defining process diagrams you should take into account the following basic principles:

* [Simple and Clear flow.](#simple-and-clear-flow)
* [Use BPMN standards.](#use-the-bpmn-standards)
* [Use Labeling.](#use-labeling)
* [Simplify diagrams. ](#simplify-diagrams)

***

### Simple and Clear flow

#### Start and End Events in BPMN

* In BPMN, start and end events are optional.
* However, omitting them can lead to ambiguity and misinterpretations.
* To ensure clarity, always use start and end events in every **process** and **subprocess** to explicitly define their beginning and completion.

#### Start and End Events in Straatos

* In Straatos, start and end events play a key role in process automation.
* Start events trigger actions such as:
  * Importing data from emails, websites, or other sources.
* End events are used to:
  * Purge documents after a defined retention period.

<figure><img src="/files/tbXEKM5eDNEBRIyGmXDR" alt=""><figcaption></figcaption></figure>

#### Follow a consistent direction of flow

* Make the process logic visible in the diagram. Avoid crossed lines (connectors), maintain a time seuquence and keep a consistent direction of flow.

<figure><img src="/files/GrLGBpCF3oDRP0GqAZyY" alt=""><figcaption></figcaption></figure>

#### Keep primary scenario clear (happy path)

* The "happy path" should be easily identified when reading a diagram. A good approach is to design of the happy path first and then the alternative flows.

<figure><img src="/files/9GuCb1778KUrPaCco5pj" alt=""><figcaption></figcaption></figure>

#### Keep alternative scenarios clear

* BPMN offers the necessary tools to represent exception handling logic explicitly in the diagram. Once the primary scenario is designed, make use of the following elements to model alternative flows as required.

#### Use events attached to tasks

* If an Event is attached to the boundary of an activity, it will change the normal flow into an exception flow when something happens (error event, time limit reached, etc.)

<figure><img src="/files/cKanhOmS1VMvuhnlmk36" alt=""><figcaption></figcaption></figure>

#### Distinguish success and failure end states

* Use separate end events to identify when a process has finished successfully and when it did not.

<figure><img src="/files/gmNXKH6LgMjwj2eBYp8W" alt=""><figcaption></figcaption></figure>

***

### **Use the BPMN standards**

* The BPMN standard provides guidelines for diagramming business processes.
* However, not all BPMN guidelines are strictly enforced in Straatos.
* Despite this, following BPMN best practices ensures that processes remain clear, readable, and well-structured.

#### Usage of Pools

* Pools are displayed on top of each other over the entire length.

<figure><img src="/files/clpD723hUlgtrkZWwgY1" alt=""><figcaption></figcaption></figure>

* The height of the expanded Pool depends on the height of the content.

<figure><img src="/files/EkH7BhzrGOrInepzz0o4" alt=""><figcaption></figcaption></figure>

* Collapsed Pools must have at least one outgoing message flow.

<figure><img src="/files/6OoUGm1BMF7EuERPIciE" alt=""><figcaption></figcaption></figure>

#### Usage of Lanes

* Create a lane only if at least one task or intermediate event is performed in it.

<figure><img src="/files/afzdN0lcMhPKqU9UMa3U" alt=""><figcaption></figcaption></figure>

* Do not create lanes to represent the area or entity that carries out automatic tasks or gateways.

<figure><img src="/files/pGawCUEsCNdudqXEnFmV" alt=""><figcaption></figcaption></figure>

* Do not diagram tasks, gateways or events in the middle of two lanes.

<figure><img src="/files/AGmf582RXrKI65ZsdBJY" alt=""><figcaption></figcaption></figure>

#### Usage of Activities

* Do not branch flow’s using tasks. Always use gateways to do so.

<figure><img src="/files/GCWiM9HyEdsJhgwMwxhO" alt=""><figcaption></figcaption></figure>

#### Usage of Gateways

* Do not use gateways to join and split at the same time.

<figure><img src="/files/A5Kjz888Q7kG968HfkTq" alt=""><figcaption></figcaption></figure>

* Balance gateways:&#x20;
  * Splits must be joined equivalently.

<figure><img src="/files/Px5e2vyfVhZqcaEbxQZV" alt=""><figcaption></figcaption></figure>

* Always use the same type of Gateway used for splitting to join the flow.

<figure><img src="/files/DuDMIFsjqQlBs0tvUcFC" alt=""><figcaption></figcaption></figure>

#### Use of Connectors

* Use sequence flows to connect all the activities, events and gateways. Never use message flow to connect activities within the same pool or leave shapes unconnected. This is enforced in Straatos.
* Never use sequence flows to connect elements of different pools. Use message flows to represent information exchanging between processes. This is enforced in Straatos.

***

### **Use Labeling**

#### Labeling Processes

* Processes labels should clearly describe their main purpose. Ensure that you do not use short names or abbreviations.

#### Label Activities

* Give activities a label composed of a one verb, and one noun. This way readers can clearly understand the objective of a task. Also, ensure that you do not use short names or abbreviations.

<div data-full-width="false"><figure><img src="/files/A6t3jLj0GL2tujaSPEZR" alt=""><figcaption></figcaption></figure></div>

#### Labeling Events

* Use labeling when multiple start and end events are used. Do not repeat names.

<figure><img src="/files/PWVtpAuhUvcZRU1tunUf" alt=""><figcaption></figcaption></figure>

#### Labeling Gateways

* Divergence gateways should have a clear name indicating the decision or condition evaluated when it applies.  Use a name composed of one verb, one object, and a question mark to identify what is being evaluated. You can even use questions to clarify the decision involved.

<figure><img src="/files/l9xza3GYdsyV3nXrExA2" alt=""><figcaption></figcaption></figure>

* If names do not apply for any gateway use abbreviations or numbers to differentiate them.

<figure><img src="/files/YcgIbGRLrekfsqsEwFYW" alt=""><figcaption></figcaption></figure>

***

### **Simplify diagrams**

* Large diagrams do not allow giving an end-to-end perspective to readers. They are difficult to read and clearly communicate the purpose of the process.

* Defining the correct scope of tasks and level of detail of processes is key to reduce the overage of information. The following tips will help:
  * Reduce the number of redundant tasks:&#x20;

    * When diagramming it is useful to imagine that you are a final user. If a set of consecutive activities can be performed by the same person, at the same time then these activities could be integrated into a single activity.

* A set of consecutive activities in the same lane may indicate missing participant details, too much detail, or a misalignment in scope. Review these patterns to identify opportunities for activity integration.


# General Information

This article describes all general information questions that you might have.

### **Input Devices (e.g. Scanners, MFP, Mobile Devices)**

#### **What capture peripherals are supported by CumulusPro Straatos?**

* All scanners with TWAIN are directly supported.
* Network or MFP scanners with email capabilities can be supported via our Email Import feature.
* Documents are sent to a specific email address, and our Email Import feature will directly import documents into the Straatos platform for processing.
* If the scan operator would like to view the document:
  * For instance, to check the scan quality.&#x20;
  * He/she can log on to the system via our Web validation interface, check the document, and submit it for processing.

#### **Can CumulusPro support network capture peripherals so users can scan from their workstations?**

* This depends on the local settings as well as network scanner model.

#### **What are the industry standards for accessing scanner hardware through CumulusPro Straatos?**

* CumulusPro Straatos supports TWAIN for direct integration to scanners, which is the industry standard that comes with the best support from scanner manufacturers.

#### **What other channel inputs do CumulusPro work with?**&#x20;

* CumulusPro uses input channels such as email, FTP, Zapier (which can be used with up to 500+ other systems to provide input to Straatos), and the iConnector client to write any integration to another 3rd party system.

***

### **Operating Systems, Browser, Open Standards**

#### What operating systems and browsers do CumulusPro support for the scan client and web validation?

* CumulusPro supports the following:
  * Operating System:&#x20;
    * Windows 7.
    * Windows 8.
    * Windows 8.1.
    * Windows 10.
    * Browser:&#x20;
      * Edge.
      * Firefox.
      * Chrome.

#### **How does CumulusPro plan to support possible changes to existing LOB systems or new LOB systems in the future?**

* CumulusPro’s iConnector framework, which is responsible for inter-system connectivity, provides a standard interface to the Straatos Platform for importing and exporting documents and metadat The iConnector interface is a webservice interface.
* In addition, Straatos can integrate with other systems in the market (e.g. Zapier, Sendgrid, etc.), as well as connect with the JavaScript-based Script Task to exchange data.

***

### **Network**

#### **What encryption algorithm is used during data exchange on CumulusPro Straatos?**

* All communication via iConnector is SSL encrypted (via HTTPS).

***

### **Data Format**

#### **In what formats are imaged captured and stored?**

* Captured images are stored in standard PDF, TIFF, and JPEG.

***

### **Data Integrity**

#### **How are documents and data in Straatos managed to ensure data consistency and integrity?**

* Documents either reside on the client or on the server during the entire transactional process. But once a document is successfully uploaded and committed to the CumulusPro Straatos server for processing, these document images are deleted from our web clients and becomes cache in our mobile app (for offline operations).

* On Straatos platform, documents are stored in Amazon S3 data centres with the best possible security measures. Any step, modification, and deletion of documents is logged in an Audit Log.
  * Should a user delete a document, this is recorded too. Once documents are uploaded into our Straatos process, they can be stored in a 3rd party Document Management System for added security.

***

### **Data Security**

#### **During document processing, are documents only accessible by users who are given access to work on them?**

* Yes. In the CumulusPro Straatos workflow platform, user access and security is managed by RBAC (Role-Based Access Control).

* To do this, ensure that documents are assigned to the required worker role in the organisation group during creation and configuration of a new process (represented as “Organisation”) or workflow on the Straatos process designer. This restricts document access to users with designated roles within the process (or “Organisation”).

* To manage documents within an “Organisation”, a user account can join a Role/Group that has been given access to Process Monitor.

* A good practice is to create a unique “Organisation” for each process, so that rights to the Process Monitor can be granted only to the process owner (usually a business unit supervisor or department head).

#### **What types of data are captured during the document process, and how are they handled securely?**

* There are two types of data involved in a workflow or process:&#x20;
  * Workflow-related statistical data.&#x20;
  * document content data.

* Workflow-related statistical data such as document file type, size, and format are logged for troubleshooting purposes.

* Images and data from documents that have completed their process life cycles are completely removed and purged.

* None of the data is or will be in any way be exchanged with other parties, nor used for purposes other than for document input and processing.

* Data can be encrypted while “at rest” (during storage) and during transmission. We do not share any customer data with 3rd parties, unless authorised by you (e.g. for troubleshooting) or when you provide an individual with access via the Admin Panel.

***

### **Cloud Application Services and Performance**

#### **What is the performance of Straatos running on Azure? How long does it take before an uploaded document image appears on the Web Validation client?**

* From experience, performance bottleneck arises only from poor Internet connection speed, starting from the time to upload documents from a web scan client to Straatos. Depending on the available Internet connection, as well as document size, users may have a slight delay before the document image appears in Web Validation or Process Monitor.

#### **Since CumulusPro Straatos sits on Azure, can it scale automatically based on demand?**

* Yes, CumulusPro server applications are configured with Azure auto-scaling when additional performance is required. This means, if there is a huge load of documents to be processed, additional server resources (and additional servers) will be added to process the load. More instances of your application can also be deployed once the workload becomes bigger.

#### **How fast are OCR services running in the cloud?**

* OCR speed is highly dependable on document image size, as well as the OCR technology. (For instance, ABBYY and Tessaract have different performance speeds.).

#### **If a user scans multiple pages/documents in a batch and these pages/documents require OCR, how will this be handled?**

* Straatos automated modules and services are running on MS Azure with auto-scaling mode. When a cloud service or application has reached its pre-set maximum queue capacity, auto-scaling kicks in and will spark off another virtual instance of the services.

* When ABBY Cloud (for example) detects a high volume of documents in its processing queue, more OCR services will kick off to serve this queue. When all the pages of each document have gone through the OCR process, the result of each document will be returned immediately.

#### **What are the SLA levels?**

* Our SLA is based on Microsoft Azure’s availability, guaranteed at 99.5% or higher. Scheduled maintenance is kept to a minimum and takes up less than 15 minutes per event every 3 to 6 months. Maintenance schedules cannot be negotiated; however, when possible, we perform scheduled maintenance outside of business hours.

#### **What kinds of network connections are available, and will they offer sufficient speed for high volume data transfers?**

* The outgoing connection from servers is from Microsoft Azure and bandwidth of 30Mbit/s is the standard/average connection speed for outbound traffic. (Azure offers faster speeds on outgoing connection.).

* Internet bandwidth depends on many other factors too, such as the bandwidth that is made available for the iConnector framework as well as other infrastructure factors as Internet network traffic is routed at different speeds.

***

### **System Maintenance**

#### **Can a non-IT expert able to perform any first-time installation or future upgrade at the scan station?**

* Yes, our first-time configuration/installer is designed so non-IT experts can install them. All CumulusPro software component upgrades (excluding scanner drivers that are shipped by scanner manufacturers) are done automatically without any user intervention.

***

### **Error Handling**

#### **When errors are encountered by the system, and how are they handled?**

There are a few possible causes to system errors in CumulusPro Straatos, each of which is handled differently. They can be categorised as follows:

1. **Uploading from client to cloud server.**

* When documents encounter error transmission due to Internet connection failure, the documents remain on the client machine and the user will get a notification that the specific document cannot be uploaded. User can choose to retry manually, or the application will auto-retry/auto-recover from its last upload status when the Internet connection is reinstated.

2. **During local system crashes that may cause a loss of data.**

* The web client will attempt to recover from its last known status when the client machine reboots. Users may have to re-scan documents if the last event before the system crash happens before the system was able to save the images into the machine’s storage.

3. **During communication with CumulusPro web services.**

* All CumulusPro web services shall return error codes when the communication fails. Applications can interpret those error messages, inform the users of unsuccessful operations, and provide recovery actions.

#### **What are the most common possible reasons for system interruption? What is the error rate in general?**

* Most common errors occur during scan operations, such as paper jam, double feeding, etc..
* Errors related to the scan operation are displayed to the user, who can take immediate action.
* Errors during upload are usually related to missing or interrupted Internet connectivity.
* Error rates vary, and are primarily dependent on the reliability of Internet connection as well as capture peripherals.

#### **Does the user need to wait for all steps to be completed, or can the user proceed to terminate a document flow directly after scanning?**

* The user does not have to wait for all steps in the process flow to complete. However, for audit and governance reasons, only a normal user account role using web scan or validation client with delete rights granted  are  allowed to delete any document once it is submitted into the workflow.
* If the user without delete rights granted wishes to cancel a document already in the process, the user can contact his/her supervisor or administrator to delete the document using the Process Monitor. It is best practice for access to the Process Monitor to be limited to supervisors or system admins.

***

### **Image Optimisation**

#### **How can CumulusPro’s scanning software help in image optimisation?**

* CumulusPro’s web scan solution produces a good quality image natively from the scanner’s device capability, without degradation of the image quality from the scanner. However, additional image processing features such as deskew, border removal, etc. can be enabled through the Admin Panel. Other parameters such as brightness/contrast/gamma and colour options can be set in the Admin Panel too.


# Document Access Control

This article describes the purpose of Document Access Control

Documents added to tasks in Straatos are stored in Blob Storage. By default, Azure Blob Storage is used. However, in regions where Azure Blob Storage is unavailable, documents are stored on a File Server.

### **Security & Encryption**

* Documents are encrypted at the application level.
* In Azure Blob Storage, they receive additional encryption at the infrastructure level for enhanced security.

***

### **Accessing Documents**

* Within Straatos: Documents are primarily accessed via Straatos Workflow Steps or through the Straatos MyHome page. Secure access is automatically managed by Straatos in these cases.

* External Access:&#x20;
  * When documents need to be:
    * Exported to a backend system.
    * Submitted to external tasks for processing.

* The API interface must be used to allow access. This can be configured using:
  * Time-limited access.
  * Authentication-based access.

By implementing controlled access mechanisms, Straatos ensures document security while enabling integration with external systems.

***

### **Access to Documents (Webservice Key)**

Using a Webservice Key is the preferred method for server-to-server communication, ensuring that the key remains secure and not exposed.

#### **Steps to Access a Document via Webservice Key**

1. Retrieve the Document URL:

* Use the GetDocumentInfo API call to obtain the document’s URL.

2. Authenticate with the Webservice Key:

* Include the Webservice Key (found in the Organisation Configuration) when accessing the document URL.

Example URL from GetDocumentInfo:

`https://effektif-connector-cpro.cumuluspro.net/ConnectorService.svc/json/AsyncStorage/e27d78eb-b0c1-49f2-91bf-dff0f92d5c55.pdf`

Example URL with Webservice Key to Access Externally:

`https://effektif-connector-cpro.cumuluspro.net/ConnectorService.svc/json/AsyncStorage/09551add-e6ed-47f7-87ec-d388ff94f7f5.pdf?w=4ac45ee9-3581-400e-b6a8-7578dd1e3c0d`

***

### **Access to Documents (User Session ID)**

Using a User Session ID is recommended when displaying a document in a browser window.

**Important Notes:**

* The Session ID is regenerated each time a user logs in.
* Session IDs have a limited lifespan and expire after a period of inactivity.
* If a user saves the document link, it will no longer be accessible once the Session ID expires.

This approach ensures secure, session-based access while preventing unauthorized use of expired links.

Example of URL with Session ID added:

`https://effektif-connector-cpro.cumuluspro.net/ConnectorService.svc/json/AsyncStorage/09551add-e6ed-47f7-87ec-d388ff94f7f5.pdf?s=4ac45ee9-3581-400e-b6a8-7578dd1e3c0d`

***

### **Access to Documents (Time-Based)**

Some APIs or integrations may not support additional parameters and require direct access to the document URL. In such cases, access can be granted using a time-based restriction.

#### **Configuring Time-Based Access**

* The time-based access restriction can be configured in the UI.
* By default, this restriction is set to "Never", meaning unrestricted access is not enabled.
* The access time is calculated from the moment the document is created in the workflow.

This method ensures controlled access while accommodating APIs that cannot handle additional authentication parameters.

The options Custom allows the definition of the number of Minutes until the access is expired.

***

### **Access to Documents (Limit on Number of Times)**

Some APIs or integrations may not support additional parameters and require direct access to the document URL. In such cases, access can be restricted based on the number of times a document can be accessed.

#### **How It Works**

* A document can be configured to be accessed a limited number of times.
* For example, if access is granted only once, the document becomes unavailable after it has been accessed a single time.

#### **Availability**

* This option is only configurable via Script and is not available in the UI.

This method provides an additional layer of control over document access, ensuring security while integrating with external systems.

***

### **Setting Access via Script**

Document access restrictions for "Time-Based Access" and "Limit on Number of Times" can be configured via script.

#### **Use Case Example**

* If a backend system needs access to store a document, the script can grant one-time access in a workflow step just before the export.
* This ensures that the document URL is only exposed for a limited time or number of accesses, enhancing security.

Using this approach helps control document accessibility while integrating with external systems.


# Performance Tuning by Throttling

This article explain Performance Tuning by Throttling

In Straatos, each automated workflow step or activity queues and processes tasks in parallel. However, not all queued tasks within a step or activity are processed simultaneously. Straatos dynamically manages the throughput of each automated step or activity by adjusting both:

* The number of "ready-for-process" tasks.
* The number of processing threads running in parallel.

This adjustment, known as throttling, ensures efficient resource utilization and controlled task execution.

Both of these parameters can be configured by setting the following in a workflow step or activity:

* Number of Instances:
  * Controls the number of "ready-for-process" tasks.
* Number of Threads:
  * Defines the number of processing threads running in parallel.

***

### **Why do we need to throttle?**

Throttling is essential when an automated service task sends information and data to an external service that has limitations on the number of tasks it can accept and process.

By controlling the number of tasks being sent, throttling helps:

* Prevent overloading the external service.
* Ensure smooth and reliable data transmission.
* Optimize system performance and stability.

This approach ensures that workflows operate efficiently while respecting external system constraints.

***

### **Configuration task Throttles and Threads**

The throttle can be configured separately for each workflow step. In the Process Designer, click on an activity, then click on the 'Set maximum number of threads' icon.

Throttling can be configured separately for each workflow step. To set the throttle limit in the Process Designer:

1. In the Process Designer click on the desired activity.
2. Click on the "Set Maximum Number of Threads" icon.
3. Configure the maximum number of processing threads as needed.

<figure><img src="/files/lWNF7SYWFPVO2fuA5yT1" alt=""><figcaption></figcaption></figure>

In the pop up box, enter the settings:

<figure><img src="/files/Qa0NeQRoLN9oaPPi5mTk" alt=""><figcaption></figcaption></figure>

***

### **Throttling the Maximum Number of Instances in an Activity**

* Purpose of Throttle:
  * To limit the number of "ready-to-process" tasks in a workflow step.

* Scenario:
  * In a busy environment, 1000 tasks are queued in a workflow step for sending documents to an OCR cloud service.

* OCR Service Limit:
  * The service can accept only 20 documents at a time.

* Consequence of No Throttle:
  * Setting the throttle parameter to 0 causes Straatos to attempt sending all 1000 tasks, resulting in an error.

#### **Maximum threads processed in parallel**

The purpose of Threading in Workflows helps to limit the number of processing threads servicing a queue of tasks, working in conjunction with the throttle parameter which manages the number of "ready-to-process" tasks.

* Synchronous Execution:
  * In environments like JavaScript steps, the number of threads is effectively the same as the number of instances when the throttle is set to 0 (no throttling).
  * The default number of threads is set to 10.
  * The number of processing threads should not exceed the number of instances.

* Asynchronous Processing:
  * This involves processing steps where a return result from the external service is not immediately required.
  * The system triggers 10 processing threads at a time and waits for the completion of these threads before starting the next cycle.
  * If the asynchronous service returns a result, a thread from the configured pool is used to handle this result, optimizing the use of computing resources.

In asynchronous workflows, most Straatos Service Tasks process documents behind the scenes. The throttle setting here is crucial for managing system resources efficiently and ensuring high throughput without significant performance degradation, even when many tasks are processed in parallel. For cases where task limitation is essential, especially in high-load environments, adjusting the throttle parameter is recommended to prevent bottlenecks and optimize overall system performance.

#### Optimizing Performance and Resource Utilization

* This setup optimizes computing resource usage, reduces bottlenecks, and maximizes throughput.
* Most Straatos Service Tasks process documents asynchronously in the background, so limiting throttling generally does not impact performance significantly.
* However, for workflows handling a large number of tasks in parallel, throttling should be adjusted appropriately.

If limiting task execution is required, it is recommended to configure the throttle option.


# Turning "Allow User Management" On/Off

This articles describes Turning "Allow User Management" On/Off.

Straatos API allows a Script Task to create, update, and delete user accounts. This API functionality is created so workflows can for example add users and assign roles based on an imported user list. However, if this function is not needed, an Administrator might want to limit access to user accounts from within the Scripts so that user accounts are not unnecessarily exposed.

This can be done by setting ‘Allow User Management' to 'Off', which is also the default option.

### Configuration

The configuration can be made in the Workflow Settings, option 'Allow User Management'. See screenshot below.

<figure><img src="/files/7pLob3DSrlqzTPjHwL6p" alt=""><figcaption></figcaption></figure>

By default, for any newly created workflow, the option is set to 'Off'.

If the setting is 'Off', any script that tries to update, create, delete an Account will fail.

If the setting is 'On', scripts that use the update, create, delete function for an Account will execute.


# Introduction

This article outlines the configuration of Straatos Cloud Archive in a customer’s Azure cloud environment.

The Straatos Cloud Archive enables secure storage and retrieval of documents and metadata. Customers can choose to archive data in their own Azure environment or opt for CumulusPro to host the archive in our data centers.

* Key Components:
  * Archive Connector:
    * Connects to SQL Database, Azure AI Search, and Azure Storage.
  * Azure Key Vault:
    * Securely stores secrets and passwords.

* Document Upload & Retrieval:
  * Documents can be uploaded via the CumulusPro BPM platform (workflow) using the CumulusPro Archive Connector.
  * Documents can be retrieved through the following methods:
    * CumulusPro Web User Interface (TaskUI).
    * Secure REST API.

{% hint style="info" %}
This documentation excludes network and application security recommendations. Follow your company’s security policies or Microsoft Azure Security frameworks. It focuses solely on component setup and configuration.
{% endhint %}

### **Diagram of component interaction**

![](/files/lEcPrbonVLNIBDnDgiYh)

{% hint style="info" %}
API Management Service is optional. Alternatively, an Application Gateway or direct access to the Web App Service can be used.
{% endhint %}


# Creating all Azure Resources

### **What is Azure Resource setup for Straatos Cloud Archive?**

The following resources are required and must be created in Azure environment. It is highly recommended to create all Azure Resources in the same Azure region (example: West Europe).

#### **How Does It Work?**

This article covers the following key components:

* [Azure Resource Group](#azure-resource-group)
  * Serves as a container to organize and manage all related Azure resources.

* [Azure Web App Service](#azure-web-app-service)
  * Hosts the Straatos Archive Connector for handling integration and processing.

* [Azure AI Search](#azure-ai-search)

  * Enables fast and secure indexing and retrieval of archived documents.

* [Azure Key Vault](#azure-key-vault)
  * Stores and manages sensitive credentials, secrets, and encryption keys.

* [Azure Storage Account](#azure-storage-account)
  * Provides durable, secure cloud storage for archived documents.

* [Azure SQL Database](#azure-sql-database)
  * Maintains metadata, configuration data, and indexing relationships for document retrieval.

***

### **Getting Started**

To deploy all required resources successfully, follow the steps outlined below.

{% hint style="info" %}
Names can only include alphanumeric, underscore, parentheses, hyphen, period (except at the end), and Unicode characters that match the allowed characters.
{% endhint %}

{% hint style="info" %}
Ensure that Microsoft is listed as the service provider for all Azure resources created.
{% endhint %}

***

### **Azure Resource Group**

#### **What is an Azure Resource Group?**

A logical container that holds related Azure resources such as virtual machines, databases, and web apps allowing them to be managed collectively. It simplifies resource organization, access control, and lifecycle management across deployments.

#### **Creating Azure Resource Group**

1. &#x20;In the Homepage of Microsoft Azure please select **Create a resource**.

<figure><img src="/files/oPBKYWxzyxPPbb4Ffus0" alt=""><figcaption></figcaption></figure>

2. In the search bar type in **Resource Group** and choose the first option.

<figure><img src="/files/u1PaxHKoUU2iDidgwrzA" alt=""><figcaption></figcaption></figure>

3. Select the first result from the list.

<figure><img src="/files/jno7DPTfCBNcwUfpDZAb" alt=""><figcaption></figcaption></figure>

4. Select **Create.**

<figure><img src="/files/zEn6Ro0GcZrntFu7JiG3" alt=""><figcaption></figcaption></figure>

5. Enter your preferred resource group name and click on **Review + Create**.

<figure><img src="/files/2ZgjXCtxesyTDAtHg7sR" alt=""><figcaption></figcaption></figure>

6. The resource group will be created.

***

### **Azure Web App Service**

#### What is an Azure Web App Service?

A fully managed platform as a service (PaaS) that enables you to build, host, and deploy web applications using frameworks such as .NET, Java, Node.js, and Python. It abstracts infrastructure management, handles scaling, and enforces security best practices allowing developers to focus on application development.

The Straatos ArchiveConnector runs within an Azure Web App Service, leveraging the platform’s scalability, security, and managed infrastructure.

#### Creating Azure Web App

1. In the Overview pane of your resource group, select **Create resources** to add a new resource.

<figure><img src="/files/bypfLbkhBY6wBglYisd9" alt=""><figcaption></figcaption></figure>

2. Use the search bar, enter Web App then select the first result from the list.

<figure><img src="/files/UAPQHTZ3FvgMYemW7Mkp" alt=""><figcaption></figcaption></figure>

3. Select the first option.

<figure><img src="/files/RKqIeJuA5w8bQqRlyQSV" alt=""><figcaption></figcaption></figure>

4. Click on **Create**.

<figure><img src="/files/TIjKRNc3c0uXdOxdMphL" alt=""><figcaption></figcaption></figure>

5. Please use the following recommended settings to create the Azure Web App.

<table data-header-hidden><thead><tr><th width="206.27276611328125"></th><th></th></tr></thead><tbody><tr><td>Name</td><td>Web App Service Name (example: webapp-cpro-archive).</td></tr><tr><td>Publish</td><td>Code.</td></tr><tr><td>Runtime Stack</td><td>.Net 8 (LTS).</td></tr><tr><td>Operating System</td><td>Windows.</td></tr><tr><td>Region</td><td>Same region as the Azure Resource Group (example above: West Europe).</td></tr><tr><td>Pricing Plan</td><td>Same region as the Azure Resource Group (example above: West Europe).</td></tr></tbody></table>

<figure><img src="/files/mUcc1xJDzf9Razn8s4kq" alt=""><figcaption></figcaption></figure>

***

### Azure AI Search

#### What is an Azure AI Search?

A cloud-based search service that leverages AI capabilities to index, search, and analyze content across diverse data sources. It supports advanced full-text search, cognitive skills such as OCR and entity recognition, and semantic ranking for improved relevance.

In this solution, Azure AI Search enables secure, intelligent document search and retrieval.

#### Creating Azure AI Search

1. In the Overview pane of your resource group, select **Create resources** to add a new resource.

<figure><img src="/files/GBpTk79DfWxxx9ZX575P" alt=""><figcaption></figcaption></figure>

2. Use the search bar, enter **AI Search** then select the first result from the list.

<figure><img src="/files/7Fm6zWiCXbWTZDkPoW7z" alt=""><figcaption></figcaption></figure>

3. Select the first option.

<figure><img src="/files/Phb8jBbMH3ETC511K8h6" alt=""><figcaption></figcaption></figure>

4. Click on **Create**.

<figure><img src="/files/7spJbaxkgwnZFbUBSTZG" alt=""><figcaption></figcaption></figure>

5. Use the recommended configuration settings to create the Azure AI Search service.

{% hint style="info" %}
You may use any name for the Azure AI Search, as long as it meets Azure naming requirements.
{% endhint %}

<figure><img src="/files/6hR8kAj5iUL772k1q1wj" alt=""><figcaption></figcaption></figure>

***

### **Azure Key vault**

#### **What is Azure Key vault?**

A cloud-based service that securely stores and manages sensitive information such as secrets, encryption keys, and certificates. It enhances data protection by providing centralized access control and secure key management for applications.

#### **Creating Azure Key vault**

1. In the Overview pane of your resource group, select **Create resources** to provision a new service.

<figure><img src="/files/ObdRYzJGT7hXFNXvqbTN" alt=""><figcaption></figcaption></figure>

2. Use the search bar, enter **Azure Key vault** and select the first result from the list.

<figure><img src="/files/ST8lthj4FR7m1jqXToRR" alt=""><figcaption></figcaption></figure>

3. Select the first option.

<figure><img src="/files/cHxS7aUZmeyHxUKjB49x" alt=""><figcaption></figcaption></figure>

4. Create the Key vault with the following configuration.

{% hint style="info" %}
You may use any name for the Key Vault, as long as it meets Azure naming requirements.
{% endhint %}

<figure><img src="/files/kBlkFy6kN945fmxMycR4" alt=""><figcaption></figcaption></figure>

By default, the Key vault will implement the settings below. You will not need to configure them.

* Access Configuration: Azure role-based access control (RBAC).

<figure><img src="/files/z3ONxd9sNMx588ixdaOG" alt=""><figcaption></figcaption></figure>

* Networking.

<figure><img src="/files/vpbLdqElnRnXT0Gdg8I8" alt=""><figcaption></figcaption></figure>

***

### Azure Storage Account

#### What is Azure Storage Account?

A scalable cloud storage solution for managing data objects such as blobs, files, queues, and tables. It provides secure, durable, and highly available storage for both structured and unstructured data workloads.

#### Creating Azure Storage Account

1. In the Overview pane of your resource group, select **Create resources** to provision a new service.

<figure><img src="/files/le0oGIR2kcQwOo9imfMI" alt=""><figcaption></figcaption></figure>

2. Use the search bar, enter **Azure Storage Account** and select the first result from the list.

<figure><img src="/files/zwNv7Ttp6Cm6IDv6vPlb" alt=""><figcaption></figcaption></figure>

3. Select **Storage account**.

<figure><img src="/files/3BZVnNJDkAHKizO65Gnk" alt=""><figcaption></figcaption></figure>

4. Click on **Create.**

<figure><img src="/files/8myjfOPmB2zVgOCJhhpR" alt=""><figcaption></figcaption></figure>

5. Please follow the recommended settings as the image below.

<figure><img src="/files/B6j1CqQ65x4n9BmlJmnr" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
You may use any name for the Storage Account, as long as it meets Azure naming requirements. and choose Geo-redundant storage (GRS) for replication and high availability.
{% endhint %}

***

### Azure SQL Database

Stores metadata, document index fields, and archive configuration to support efficient document management and retrieval.

{% hint style="info" %}
An existing SQL server is required. The configuration steps below are intended for creating the database and tables only.
{% endhint %}

#### Creating Azure SQL Database.

1. In the Overview pane of your resource group, select **Create resources** to provision a new service.

<figure><img src="/files/5vocuUNpaVt7V228fpc7" alt=""><figcaption></figcaption></figure>

2. Use the search bar, enter **Azure SQL Database** and select the first result from the list.

<figure><img src="/files/zsZL6kG9Cw9lvZ3D2deD" alt=""><figcaption></figcaption></figure>

3. Select **SQL Database**.

<figure><img src="/files/K03G0Q3FN7uo6MTjNfD6" alt=""><figcaption></figcaption></figure>

4. Click on **Create**.

<figure><img src="/files/LIlxFaGgrI6NlmrtjCTl" alt=""><figcaption></figcaption></figure>

5. Create Azure SQL Database using the following settings.

<table data-header-hidden><thead><tr><th width="202.63641357421875"></th><th></th></tr></thead><tbody><tr><td>Resource Group</td><td>The resource group that was created</td></tr><tr><td>Database Name</td><td>Any name based on your preference</td></tr><tr><td>Server</td><td>Follow the server that has been configured for the rest of the Azure Resources</td></tr></tbody></table>

<figure><img src="/files/NEOH4NuiWWCRBttI0fgM" alt=""><figcaption></figcaption></figure>

6. Click **Review + create** and the Azure SQL Database will be created.

#### **SQL server setup.**

1. In the SQL server, locate the database that was created during the setup process.
2. Right click the database, then select **New Query** to open a query editor window.
3. In the query window, verify that the **Database** dropdown is set to the database you created.
4. In the query window, enter the following two lines of code.

```
CREATE User with Password =
Alter role [db_owner] add member []
```

{% hint style="info" %}
The first line creates a user and a password for the Database.

The second line assigns db\_owne**r** permissions to the user.
{% endhint %}

#### **Example of Database Connection String is as below**

`Data Source=tcp:<servername>.database.windows.net,1433;Initial Catalog=<DBName>;User Id=<Username>;Password=<password>`

***

### **Overview of Created Azure Components**

Upon completion, the following Azure components will be configured:

* Azure Resource Group.
* Azure Web App Service.
* Azure AI Search.
* Azure Key Vault.
* Azure Storage Account.
* Azure SQL Database.


# Configuring all Azure Resources

Below describes the complete configuration of all Azure components in the customer's Azure environment.

* [Azure App Service configuration](https://help.cumuluspro.net/straatos-archive/pages/DxsV5IY9Vjg6quFsl6Si#id-4.1-azure-app-service-configuration)
* [Azure Key Vault configuration](https://help.cumuluspro.net/straatos-archive/pages/DxsV5IY9Vjg6quFsl6Si#id-4.2-azure-key-vault-configuration)
* [Azure AI Search configuration](https://help.cumuluspro.net/straatos-archive/pages/DxsV5IY9Vjg6quFsl6Si#id-4.3-azure-ai-search-configuration)
* [Azure Storage Account configuration](https://help.cumuluspro.net/straatos-archive/pages/DxsV5IY9Vjg6quFsl6Si#id-4.4-azure-storage-account-configuration)
* [Azure Service Bus configuration](https://help.cumuluspro.net/straatos-archive/pages/DxsV5IY9Vjg6quFsl6Si#id-4.5-azure-service-bus-configuration)
* [API Management configuration](https://help.cumuluspro.net/straatos-archive/pages/DxsV5IY9Vjg6quFsl6Si#id-4.6-api-management-configuration)

***

### **Azure App Service configuration**

The full archive setup and configuration are performed within the Azure App Service. To proceed, you will need the deployment package file.

{% file src="/files/cV0YKfK33Po9DcI6ll60" %}

Once you have the file, follow these steps to complete the deployment.

1. Deploy the ZIP file to the Azure App Service by following the steps below.
2. Go to the settings of your Azure Web App. Under **Developer Tools** and open Advanced Tools.

<figure><img src="/files/nLoadhbAsgo47wN2mm7j" alt=""><figcaption></figcaption></figure>

3. Click on **Go** and a new web browser TAB will be opened.
4. Click Debug console > CMD.

<figure><img src="/files/GOZagjHko4QBhseC8ZiJ" alt=""><figcaption></figcaption></figure>

5. Go to directory (\home\site\wwwroot).

<figure><img src="/files/0N0ce3jJRFWh87WIJXlx" alt=""><figcaption></figcaption></figure>

6. In this directory (\home\site\wwwroot), the ZIP file should be deployed.
7. You can do this by Drag and Drop the ZIP file into this directory.

<figure><img src="/files/RBkrJS3w4rOyB5CFK9kJ" alt=""><figcaption></figcaption></figure>

8. The ZIP file will be automatically extracted into the wwwroot folder.
9. After the ZIP file is deployed you can edit / modify the appsettings.json file.
10. The purpose of this appsettings.json file is to configure the complete archive setup when there is no Key Vault available at the customer site.

{% hint style="info" %}
Please avoid configuring settings directly in appsettings.json file instead please utilize Key Vault or app service configuration, or both. Before deploying a new archive connector, ensure a backup of appsettings.json is created. If not using it, ensure all settings are commented.
{% endhint %}

#### Editing the app.settings JSON file

1. Please open the appsettings.json file.

<figure><img src="/files/FT4bs2lwENZCW1HvXKel" alt=""><figcaption></figcaption></figure>

2. Ensure the different sections are commented out by adding the underscore (\_) before each setting.

<figure><img src="/files/cEzYhKplDqfT38AYls8w" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Do this for every section and key in the appsettings.json file.
{% endhint %}

#### Web App Configuration

1. Add a new configuration setting by clicking on **Settings** and **Environment Variables** then click on **Add**.

<figure><img src="/files/lERhlkLAtqFvkENw8bjA" alt=""><figcaption></figcaption></figure>

#### Create the following Web Application settings

**Application Setting for Database**

* Name: Database:CreateUpdateDatabase.
* Value: true.

<figure><img src="/files/qQYvwvEhFhZ3D0qWfshn" alt=""><figcaption></figcaption></figure>

**Application Setting for Keyvault**

* Name: KeyVault:Name.
* Value: keyvault-cpro-archive.

<figure><img src="/files/WBX7IOI9ZouMKUcSKylz" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Please use your own created Key Vault name value.
{% endhint %}

**Application Setting for Storage Account**

* Name: StorageAccount:StorageName.
* Value: storagecproarchive.

<figure><img src="/files/SLFoxTr4G2llWs6cPEhL" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Please use your own created storage account name value.
{% endhint %}

**Application Setting for Search Index URL**

* Name: SearchIndex:IndexUri.
* Value: <https://search-ai-cpro-archive.search.windows.net>.

<figure><img src="/files/KtYFXrWm8htWenWJFuTs" alt=""><figcaption></figcaption></figure>

The value of the SearchIndex:IndexUri can be found in the Azure AI Search.

<figure><img src="/files/NxPmdIenk90y7yJJLatR" alt=""><figcaption></figcaption></figure>

**Application Setting for Search Index Name**

The index will be created automatically upon the creation of the Azure AI Search.

* Name: SearchIndex:IndexName.
* Value: cprosearchindex.

<figure><img src="/files/vFw6PEP8qXg0rDlCeaZC" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Please use your own created Index Name value.
{% endhint %}

#### Setting up Managed Identity on the Web App

To enable Managed Identity on the Web App:

1. In the **Settings** dropdown select **Identity**.
2. Set Status to On.
3. Click on **Save**.

<figure><img src="/files/Gv1470xFtUy2vgkToyOp" alt=""><figcaption></figcaption></figure>

Key Vault access always uses Managed Identity and below is a description of how to set up Azure role-based access control on the Azure Key Vault.

1. Select the Azure Key Vault and click on **Access configuration**.
2. Select **Azure role-based access control (recommended)**.

<figure><img src="/files/uBWOXfx2x1Dg6xeAuI0E" alt=""><figcaption></figcaption></figure>

3. Go to Access control (IAM) and click on Add > Add role assignment.

<figure><img src="/files/WvkfaXflhzOT7XHY9fh6" alt=""><figcaption></figcaption></figure>

4. Click on Job function roles and search for Key Vault Reader from the search bar. Select Key Vault Reader and click on the Next button.

<figure><img src="/files/5ZoDMvDUgJgAZO8pGjuO" alt=""><figcaption></figcaption></figure>

5. From the Members section, click on select members and a window on the right appears to select members. Search for the Azure Web App you have created.

<figure><img src="/files/GExII4jLGrC4EdBNNORN" alt=""><figcaption></figcaption></figure>

6. Click on **Review + assign** button.

<figure><img src="/files/Fvjb36NM0hmH0ECUulDp" alt=""><figcaption></figcaption></figure>

7. Repeat the Add role assignment for the role Key Vault Secret User.

<figure><img src="/files/E4jYQOTDbmmvb0uD4nAw" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/Wl8VcMjuEtdrFZSoYMVh" alt=""><figcaption></figcaption></figure>

#### Adding the database connection string to the Key Vault

{% hint style="info" %}
In order to create any secrets in the Key Vault. Please ensure that you have enough user rights.
{% endhint %}

* Name: ConnectionStrings—ArchiveContext.
* Secret value:
  * `Data Source=tcp:mydb.database.windows.net,1433;Initial Catalog=the-archive-catalog;User Id=mydbaccount;Password=verysecret`

<figure><img src="/files/WM6QqZD2LrIad4TrOkZ5" alt=""><figcaption></figcaption></figure>

The database user specified should have the following access rights on the database:

* DDL writer/reader access because it will create the database upon application startup.

If needed, these access rights can be revoked after the first successful startup.

***

### Azure AI Search configuration

Azure AI Search uses Managed Identity and below is a description of how to set up Azure role-based access control on the Azure AI Search.

1. Select the AI Search and go to Access Control (IAM) and click on Add > Add role assignment.

<figure><img src="/files/Wv4PBMk5qUoOXwRPq7Z8" alt=""><figcaption></figcaption></figure>

2. Add the role **Search Index Data Contributor**.

<figure><img src="/files/pvKFCu09ZifZIbnMtuI8" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/hP5JhNT4KeA9BzYgttaO" alt=""><figcaption></figcaption></figure>

3. Add the role **Contributor** role (under tab Privileged administrator roles).

<figure><img src="/files/0IX6OAEmAL9ollGE6yl9" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/T1UqXdLQ1BvcQv3dPhlC" alt=""><figcaption></figcaption></figure>

4. Change the **Keys** setting of the Cognitive Search resource.
5. In the search service, click on **Keys** and select **Role-based access control.**

<figure><img src="/files/EhqG9g4Plf09QHHozyqR" alt=""><figcaption></figcaption></figure>

***

### Azure Storage Account configuration

The Azure Storage Account is responsible for storing all documents in the archive. Therefore, the following settings must be applied:

1. Create a new container in the Storage Account (example: cparchive).

<figure><img src="/files/ZZmRz7wXyu6Z3XLmp61t" alt=""><figcaption></figcaption></figure>

2. Select the Web App and click on the **Configuration** and add a new application setting.

* Name: StorageAccount:ContainerName.
* Value: cparchive.

<figure><img src="/files/nnx6MkyAATMWzCdBd1fD" alt=""><figcaption></figcaption></figure>

3. The Azure Storage Accounts also work with Managed Identity, and you have to set the correct role rights so the Azure Web App can have access to the Azure Storage container you have just created.
4. Select the Storage account and go to Access Control (IAM) and click on **Add > Add role assignment.**

<figure><img src="/files/89utsUBZtyvRkCZUAC5y" alt=""><figcaption></figcaption></figure>

5. Add the role Storage Blob Data Contributor.

<figure><img src="/files/HrpZby5njPaTJjVABYwl" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/D8WSRahZwb5US8tHm7C5" alt=""><figcaption></figcaption></figure>

***

### Azure Service Bus configuration

{% hint style="info" %}
The Azure Service Bus will be configured in the CumulusPro Azure environment. CumulusPro Professional Services will take care of the settings below.
{% endhint %}

Create two new Queues in the Azure Service Bus. The **archive-result** is a mandatory queue and must have this name:

1. Select the Azure Service Bus and click on **Queues**.
2. Add a new Queue named **archive-result**.

<figure><img src="/files/zXlbMeNpEwLXkVfgUzfG" alt=""><figcaption></figcaption></figure>

3. Add another queue and you can use your own name.
4. Add a new Queue named archivecpro.

<figure><img src="/files/sM816KCerFpWGn40rahC" alt=""><figcaption></figcaption></figure>

The following queues are now created:

<figure><img src="/files/spyUTyOdt8DGYWyTBfQn" alt=""><figcaption></figcaption></figure>

5. Add the newly created Azure Servicebus queue to the Azure Web Application settings.
6. Select the Web App and click on the **Configuration** and add a new application setting.

* Name: ServiceBus:QueueName.
* Value: cparchivesetup.

<figure><img src="/files/S0CkLdxW7LxuL9V75Oot" alt=""><figcaption></figcaption></figure>

#### Service bus Shared Access Policy

Create a Share Access Policy on the service bus:

1. Select the Service Bus Namespace and click on the Shared access policies and add a New SAS Policy.
2. Add the access policies **Send** and **Listen**.

<figure><img src="/files/8gRIA40yjZlTsmsOfEOV" alt=""><figcaption></figcaption></figure>

Add the Primary Connection String to the Key Vault.

3. Click on sharedcpro to open the configuration.
4. Copy the Primary Connection String which is needed for the Key Vault setting.

<figure><img src="/files/g6YxSsYhodmlBAgsmLZd" alt=""><figcaption></figcaption></figure>

5. Select the Key Vault and click on the Secrets and add a new secret by clicking on Generate/Import.

<figure><img src="/files/3tfINE4H8Nu0pPaUKvvl" alt=""><figcaption></figcaption></figure>

6. Create a secret:

* Name: ServiceBus—ConnectionString.
* Secret value:&#x20;
  * The primary connection string you copied earlier.
* Example:
  * `Endpoint=sb://servicebuscproarchive.servicebus.windows.net/;SharedAccessKeyName=sharedcpro;SharedAccessKey=......`

<figure><img src="/files/wY9GIKEd1SYQtiXMMxb8" alt=""><figcaption></figcaption></figure>

7. You will now have the following secrets in Key Vault.

<figure><img src="/files/xIgFSTn2d4By0Amgnylq" alt=""><figcaption></figcaption></figure>

***

### API Management Configuration

If the Azure API Management is used, then the following API calls to the archive connector need to be configured.

The curl commands below do not include the body or the Authorization (Bearer Token).

Highlighted parts are parameters that change between calls:<br>

```
curl -X 'PUT' \
  'https://<your domain>/API/Document/<documentId>/SetLegalHold' \
  -H 'accept: */*'

curl -X 'PUT' \
  'https://<your domain>/API/Document/<documentId>/UnSetLegalHold' \
  -H 'accept: */*'

curl -X 'DELETE' \
  'https://<your domain>/API/Document/<documentId>/DeleteDocument' \
  -H 'accept: */*'

curl -X 'GET' \
  'https://<your domain>/API/File/<file>' \
  -H 'accept: */*'

curl -X 'GET' \
  'https://<your domain>/API/Index' \
  -H 'accept: application/json'

curl -X 'POST' \
  'https://<your domain>/API/Index/AddField' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json-patch+json'

curl -X 'POST' \
  'https://<your domain>/API/Index/RemoveField' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json-patch+json'

curl -X 'POST' \
  'https://<your domain>/API/Index/RemoveDocumentField' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json-patch+json'

curl -X 'POST' \
  'https://<your domain>/API/Index/RebuildIndex' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json-patch+json'

curl -X 'GET' \
  'https://<your domain>/API/Index/ListIndexes?definitionId=<definitionId>' \
  -H 'accept: application/json'

curl -X 'POST' \
  'https://<your domain>/API/Index/ActivateIndex?definitionId=<definitionId>' \
  -H 'accept: */*'

curl -X 'POST' \
  'https://<your domain>/API/Index/CancelRebuild' \
  -H 'accept: */*'

curl -X 'POST' \
  'https://<your domain>/API/Index/ResumeRebuild?definitionId=<definitionId>' \
  -H 'accept: */*'

curl -X 'GET' \
  'https://<yourdomain>/API/Index/IndexingLogs?limit=<limit>&order=<desc/asc>' \
  -H 'accept: application/json'

curl -X 'POST' \
  'https://<your domain>/API/Search' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json-patch+json'

```


# Test your configuration

After you have configured all Azure resources, please test if the Archive is working by following the method below.

1. Navigate to the Web App and click on the dropdown of the **Development Tools** and select **Advanced Tools**.
2. Click on **Go** to open the Kudu Services.

<figure><img src="/files/8DMDaKPTe95jdqZPMozz" alt=""><figcaption></figcaption></figure>

3. Open a Command Shell by selecting CMD.

<figure><img src="/files/qNjEagTg8yxYT2ik1OoK" alt=""><figcaption></figcaption></figure>

4. Go to the **LogFiles** directory.

<figure><img src="/files/aMnEpiPWlynZc8BGp9uT" alt=""><figcaption></figcaption></figure>

5. Open the **eventlog.xml** by clicking on the **pencil**.

<figure><img src="/files/yvIIHQrX8laxrdgbHsPj" alt=""><figcaption></figcaption></figure>

6. Clear this eventlog by deleting the content and saving this file.

<figure><img src="/files/Anru1fP4TtK651Vox6tV" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/8MHFuQw07XBkupOBOgnJ" alt=""><figcaption></figcaption></figure>

7. Select the Web App and click on **Overview**.
8. Restart the Web App by clicking on **Stop** and **Start.**

<figure><img src="/files/SuL2TtQjHtcrBwDaDV7D" alt=""><figcaption></figcaption></figure>

9. If there are no error messages, you can test the complete configuration by opening a browser and using the following URL.

<figure><img src="/files/BcYJwtZiSzmjNM79oRWk" alt=""><figcaption></figcaption></figure>

10. If the deployment is successful, you will get the following response.

<figure><img src="/files/FoUCHZAora58Gt0ZHGuY" alt=""><figcaption></figcaption></figure>


# Rebuilding the Archive Index

This article describes the purpose of, and procedure for, rebuilding the Microsoft Azure AI Search index used by the Straatos Archive.

### Overview

The Straatos Archive search index is continuously updated whenever documents are added to or deleted from the archive. These changes are synchronised between the SQL database and the Azure AI Search index.

Over time, certain situations may require a full rebuild of the index:

* Configuration changes:
  * In the Straatos Archive (for example, removing index fields for specific document types).\
    In this case, existing documents are not automatically updated in the search index—only newly added documents reflect the new configuration.

* Manual changes:
  * Made directly in the SQL database related to search data. These changes are not synchronised back to Azure AI Search.

In such scenarios, the search index may contain outdated or unnecessary data, making it larger and less efficient. A full rebuilding of the index is required to bring the search index back into a consistent state.

***

### Permissions and Prerequisites

* The user must be authenticated.
* The user must have **tenant administrator** permissions.
* Ensure sufficient **storage quota** is available in Azure AI Search.

{% hint style="danger" %}
During rebulding, the existing index remains active while a new index is built in parallel.\
As a guideline, rebuilding requires approximately the same storage capacity as the current index. Depending on configuration changes, the required storage may be higher or lower.
{% endhint %}

***

### Starting a Rebuild

The rebuild is triggered via the following API call:&#x20;

```
curl -X 'POST' \
  'https://straatosv2-eu-api.cumuluspro.net/API/Archive/RebuildIndex/{tenantId}' \
  -H 'accept: */*' \
  -d ''
```

Replace `{tenantId}` with the appropriate tenant identifier.

***

### Behaviour During Rebuilding of the index

* Users can continue to search and retrieve documents as usual.
* No documents can be added or updated in the archive while rebuild is in progress.
* Rebuilding of the index can take a significant amount of time.

{% hint style="info" %}
As a guideline, rebuilding a 10 GB search index takes approximately 12–13 hours.
{% endhint %}

***

### Monitoring the rebuild Progress

You can monitor the progress and logs of the rebuild process using the following API call:

```
curl -X 'GET' \
  'https://straatosv2-eu-api.cumuluspro.net/API/Archive/RebuildLogs/35' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer ey...'
Request URL
```

This endpoint returns the current status of the index rebuild and any errors encountered.

#### Example Log Output (Successful Rebuild)

```
[
  {
    "id": 58,
    "timestamp": "2025-12-13T09:26:48.4246839Z",
    "message": "Indexing finished, please manually remove the old search index, or resume the rebuild if it was not fully finished",
    "isError": false,
    "searchIndexDefinitionId": 20
  },
  {
    "id": 57,
    "timestamp": "2025-12-13T09:26:48.4173321Z",
    "message": "Index rebuilding finished, new index activated, index id 20",
    "isError": false,
    "searchIndexDefinitionId": 20
  },
  {
    "id": 56,
    "timestamp": "2025-12-13T09:26:48.317855Z",
    "message": "Rebuilding index done, now activating for use, index id 20",
    "isError": false,
    "searchIndexDefinitionId": 20
  },
  {
    "id": 55,
    "timestamp": "2025-12-12T20:24:34.6127758Z",
    "message": "Indexing (re)started, parallel threads: 10",
    "isError": false,
    "searchIndexDefinitionId": 20
  }
]
```

If the rebuild completes successfully, the new index is automatically activated.\
If errors occur, the new index is **not** activated and the existing index remains in use.

***

### Listing Search Indexes

To list the search indexes known to the Straatos Archive, use the following API call:

```
curl -X 'GET' \
  'https://straatosv2-eu-api.cumuluspro.net/API/Archive/ListIndexes/{tenantId}' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer ey...'
```

This returns the indexes as recorded in the Straatos database.

{% hint style="danger" %}
This API does **not** validate the actual indexes present in Azure AI Search.\
Additional indexes may exist in Azure AI Search that were created manually or not cleaned up correctly.
{% endhint %}

#### Example Response

```
[
  {
    "id": 20,
    "indexName": "archiveprod20251212-1",
    "createdAt": "2025-12-12T20:24:33.105566Z",
    "rebuildStarted": "2025-12-12T20:24:33.1056359Z",
    "latestRebuildId": 8642440,
    "rebuildFinished": "2025-12-13T09:26:48.4020132Z",
    "active": true
  },
  {
    "id": 18,
    "indexName": "archiveprod20250505-1",
    "createdAt": "2025-05-05T16:09:51.842953Z",
    "rebuildStarted": "2025-05-05T16:09:51.8430506Z",
    "latestRebuildId": 6962182,
    "rebuildFinished": "2025-05-06T01:54:13.3186574Z",
    "active": false
  }
]
```

In this example, two indexes exist. The active flag and timestamps indicate which index is currently in use and which one is older.

***

### Cleaning Up Old Indexes

After the new index has been tested and confirmed to work correctly, the old index must be removed manually to free up Azure AI Search storage quota.

#### Delete the Index in Azure AI Search

1. Open the Azure Portal.
2. Navigate to the Azure AI Search service.
3. Delete the index that is no longer active.

#### Remove the Index from the Straatos Database

After deleting the index in Azure AI Search, remove the corresponding entry from the Straatos SQL database.

Retrieve the existing index entries:

```sql
SELECT  * FROM [archive].[SearchIndexDefinition]
```

Delete the unused index entry:

```sql
DELETE FROM [archive].[SearchIndexDefinition] where [Id] = {your id}
```

Replace `{your id}` with the ID of the index you want to remove.


# Straatos Fields Reference Basics

The links below will direct you to the topics listed

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>System Fields</td><td><a href="/pages/tEOXuVaKB3OiemgBFMJF">/pages/tEOXuVaKB3OiemgBFMJF</a></td></tr><tr><td>Workflow Index Fields</td><td><a href="/pages/66fe8a09baf3f85d4daca021b6fda626dcde3825">/pages/66fe8a09baf3f85d4daca021b6fda626dcde3825</a></td></tr></tbody></table>


# System Fields

This article describes system fields.

System Fields are default fields available in the Straatos platform and in most cases are pre-filled from the System.

System Fields can be used to:

* Route documents with an exclusive gateway.
* Used in scripts to read or assign values to the System Fields.
* Add values in Process Steps, for example set the Scan Operator as the email recipient.

The following section explains the different System Fields and how they can be used, including some scripting examples.

### \_documentId

* When a document is created, a unique numeric ID is generated. The variable \_documentId contains this ID. \_documentId is a read only variable.

***

### userId

The variable \_userId is used by Web Validation to assign a document to a specific user. For more information please see.<br>

* Assign Document to User for Web Validation.

***

### \_errorMessage

The variable \_errorMessage is used to store details about errors that arise in different modules, such as the Service Task.

For instance, it records issues when the extraction module fails to process documents that haven't undergone OCR.

Additionally, this variable can be set in a Script Task to indicate any problems encountered, for example:

```javascript
_errorMessage = 'Web Service did not return expected result';
onwards = false; // keep the document in this workflow step

```

***

### \_status

A system variable set by a previous workflow step, commonly during web validation.

Function:

* Captures the button pressed by the user when closing a document.

Values:

* No value:&#x20;
  * Indicates that the document was completed normally.
* invalid:
  * &#x20;Assigned when the user presses the 'Complete Ignoring Validation' button, despite one or more invalid field values.

Purpose:

* Determines the routing of the document to appropriate process steps based on the user's action selected during web validation.

The \_status variable will be assigned one of the following values by Web Validation:

* No value if the document is Completed normally without validation errors.
* 'invalid' if the document is completed with validation errors (also if a Custom Button is used to complete the document).
* 'reject' if the Reject button is used.
* 'return' if the Return button is used.
* 'rework' if the Rework button is used.
* 'rescan' if the Rescan button is used.

#### Using \_status in Script

The \_status value can be assigned and read in a ScriptTask.

Here is a sample script assigning (setting) the \_status value:

```javascript
status = 'reject';
```

In this case, the field status gets the value 'reject' assigned.

Here is a sample script reading the currently assigned value in \_status:

```javascript
var status;
status = _status;
```

{% hint style="info" %}
The \_status value is a string.
{% endhint %}

***

### \_moveToStep

In the workflow designer, up to 3 custom buttons can be configured:

<figure><img src="/files/ZeCsJfScISKpIId0U3q9" alt=""><figcaption></figcaption></figure>

If the user presses this button, the variable \_moveToStep will be assigned the value 'Custom Action 1'.

***

### \_customData

CustomData is a string optionally provided by a capture client, for example Scan+ProcessLite or Scan+Express. This parameter can be any string and passed during the upload of a document to Straatos into the \_customData system variable.

***

### \_authAccountId

When an account is created in the Admin Panel, a unique numerid ID will be generated for the account.

This ID can be seen in the URL of the Account maintenance screen in the Admin Panel:

* URL: `https://admin.cumuluspro.net/adminpanel.aspx#account/10032/settings`

For each document that was sent into Straatos from a Scan Client (Scan+ProcessLite, Scan+Express, Mobile Capture etc.) the variable \_authAccountId will hold the user ID of the account if the user was authenticated.

***

### \_authLoginName

When an account is created in the Admin Panel, a Login Email Address is specified:

<figure><img src="/files/POJJ5glPsvtDnnrBJVzR" alt=""><figcaption></figcaption></figure>

For each document that was sent into Straatos from a Scan Client (Scan+ProcessLite, Scan+Express, Mobile Capture etc.) the variable \_authAccountLoginName will hold the Login Email Address of the account if the user was authenticated.

***

### \_authUserIdentifier

When an account is created in the Admin Panel, a User Identifier can be specified:

<figure><img src="/files/DvKlIvVh8xs1oNwsWsOq" alt=""><figcaption></figcaption></figure>

For each document that was sent into Straatos from a Scan Client (Scan+ProcessLite, Scan+Express, Mobile Capture etc.) the variable \_authUserIdentifier will hold the User Identifier of the account if the user was authenticated.


# Workflow Index Fields

This articles describes Workflow Index Fields

{% hint style="info" %}
Most of the field properties below only apply to My Home and Web Validation. Within JavaScript steps, most properties do not apply. Exceptions are Name and data type.
{% endhint %}

Index Fields for workflow are defined in the Workflow settings. The fields are available in the workflow monitor, User Tasks (MyHome) and in Interact API and Script Tasks.

Index fields store values on a workflow instance level and appear to the user on task/document level.

There are no restrictions on the number of index fields that can be added.

### Index field properties

<table><thead><tr><th width="306.54547119140625">Label</th><th>Description</th></tr></thead><tbody><tr><td>Page (starts at 0)</td><td>Used in Web Validation indicating which page the field applies to and hence web validation opens that page when the document is active. Does not apply to My Home.</td></tr><tr><td>Name</td><td><ul><li>The internal Name of the field. This field is used within JavaScript to access the field values. If the 'Display Name' is empty, this field is used in Monitor and My Home as a Label.</li></ul><p></p><ul><li>Does not allow spaces, special characters and starting with numbers.</li></ul></td></tr><tr><td>Display Name</td><td>The name is used for displaying in Process Monitor, My Home Task and Web Validation. It can contain spaces and special characters.</td></tr><tr><td>Tab name in My Home</td><td><ul><li>Index fields are grouped into tabs based on their values in the 'Tab name in My Home' field.</li></ul><p></p><ul><li>If no index field has a value in this field, no tabs are displayed.</li></ul><p></p><ul><li>If at least one index field has a value, tabs are displayed.</li></ul><p></p><ul><li>Fields without a value in 'Tab name in My Home' are grouped in a tab named '...'.</li></ul></td></tr><tr><td>Column in My Home (1,2,3)</td><td>Index fields can be arranged in up to 3 columns in My Home. If the value is left empty, the index value is by default in column 1.</td></tr><tr><td>Datatype</td><td>YizclLKriu5p</td></tr><tr><td>Type</td><td>Description</td></tr><tr><td>string</td><td>Allows to store up to 20,000 characters. If data with more than 20,000 characters needs to be stored, that should be added as a file in additional data.</td></tr><tr><td>amount</td><td>An amount field which includes thousand separator and always has two decimal places</td></tr><tr><td>date</td><td><ul><li>A date field. Will display with a data picker in My Home and Web Validation.</li></ul><p></p><ul><li>Dates are displayed in the local formatting according to the browser’s regional settings.</li></ul><p></p><ul><li>In order to store a date via script correctly, it needs to be in the format YYYY-MM-DD.</li></ul></td></tr><tr><td>datetime</td><td><ul><li>This field includes a date and time picker in 'My Home' and 'Web Validation'.</li></ul><p></p><ul><li>Dates and times are displayed according to the browser's regional settings.</li></ul><p></p><ul><li>Time is shown with hours and minutes and is adjusted for the UTC time difference.</li></ul><p></p><ul><li>For correct script storage, datetime must be formatted as YYYY-MM-DDTHH:mm:ss+00:00, such as "2017-12-31T23:59:59+02:00" to represent December 31, 2017, at 11:59:59 PM with a 2-hour UTC adjustment.</li></ul></td></tr><tr><td>lookup</td><td><ul><li>Appears as a dropdown list in 'My Home' and 'Web Validation', allowing users to select a value.</li></ul><p></p><ul><li><p>Configurable as a key/value pair:</p><ul><li>The 'key' is used for data storage and scripting, while the 'value' is displayed to users.</li></ul><p></p></li><li>Includes an auto-complete feature that allows users to type ahead to filter the dropdown list, which can be configured to look up data from a database.</li></ul></td></tr><tr><td>number</td><td>A numeric field without decimal places.</td></tr><tr><td>Default Value</td><td><ul><li>Displays a default value in 'My Home' or 'Web Validation'.</li></ul><p></p><ul><li>The default value is set only when opening in Web Validation or My Home, not at the start of the workflow.</li></ul></td></tr><tr><td>Is Required</td><td>If set, the My Home/Web Validation requires a value to be set. In case the value is empty, an error message is displayed to the user and the user cannot complete the document with the Complete Button.</td></tr><tr><td>Hide</td><td><ul><li>Requires a value to be set if configured.</li></ul><p></p><ul><li>If the value is empty, an error message is displayed to the user.</li></ul><p></p><ul><li>The user cannot complete the document using the Complete Button until a value is provided.</li></ul></td></tr><tr><td>Hide in Workflow Monitor</td><td><ul><li>When enabled, the field is hidden in the workflow monitor.</li></ul><p></p><ul><li>The field will not be visible when a user clicks on a task in the Workflow Monitor to view documents.</li></ul><p></p><ul><li>This feature is useful for hiding long field values, such as JSON strings or URL links, or sensitive information like credit card details.</li></ul></td></tr><tr><td>Read Only</td><td>When enabled, the field can only be read by the user but not modified.</td></tr><tr><td>Min Value</td><td>The minimum value that can be entered. For example, if 'Min Value' is set to 50, the user cannot enter 49.</td></tr><tr><td>Max Value</td><td>The maximum value that can be entered. For example, if 'Max Value' is set to 50, the user cannot enter 51.</td></tr><tr><td>Min Length</td><td>If set, the user needs to enter a value with minimum that length. It is ideal to check fixed length fields such as IBAN, Account Numbers, Tax Numbers.</td></tr><tr><td>Max Length</td><td>If set, the user needs to enter a value not exceeding that length. It is ideal to check fixed length fields such as IBAN, Account Numbers, Tax Numbers.</td></tr><tr><td>Lookup Values</td><td>See 'Datatype Lookup' above.</td></tr></tbody></table>

| Type     | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| string   | Allows to store up to 20,000 characters. If data with more than 20,000 characters needs to be stored, that should be added as a file in additional data.                                                                                                                                                                                                                                                                                                                                                                                    |
| amount   | An amount field which includes thousand separator and always has two decimal places                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| date     | <ul><li>A date field. Will display with a data picker in My Home and Web Validation.</li></ul><p></p><ul><li>Dates are displayed in the local formatting according to the browser’s regional settings.</li></ul><p></p><ul><li>In order to store a date via script correctly, it needs to be in the format YYYY-MM-DD.</li></ul>                                                                                                                                                                                                            |
| datetime | <ul><li>This field includes a date and time picker in 'My Home' and 'Web Validation'.</li></ul><p></p><ul><li>Dates and times are displayed according to the browser's regional settings.</li></ul><p></p><ul><li>Time is shown with hours and minutes and is adjusted for the UTC time difference.</li></ul><p></p><ul><li>For correct script storage, datetime must be formatted as YYYY-MM-DDTHH:mm:ss+00:00, such as "2017-12-31T23:59:59+02:00" to represent December 31, 2017, at 11:59:59 PM with a 2-hour UTC adjustment.</li></ul> |
| lookup   | <ul><li>Appears as a dropdown list in 'My Home' and 'Web Validation', allowing users to select a value.</li></ul><p></p><ul><li><p>Configurable as a key/value pair:</p><ul><li>The 'key' is used for data storage and scripting, while the 'value' is displayed to users.</li></ul><p></p></li><li>Includes an auto-complete feature that allows users to type ahead to filter the dropdown list, which can be configured to look up data from a database.</li></ul>                                                                       |
| number   | A numeric field without decimal places.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |

***

### Auto-Complete / Type Ahead

My Home allows a field to be specified as a type ahead field. In this case, the Field is linked to a database and when the user starts typing a value, a dropdown list shows the matching entries in the database. The user can then select one of those entries.

| Name                                  | Description                                                                                                                                                                                                                                                                                                                                                                                       |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Server Lookup Name                    | A unique Name for this lookup.                                                                                                                                                                                                                                                                                                                                                                    |
| Database Connection String Name       | <ul><li>Provided by CumulusPro after the initial Setup.</li></ul><p></p><ul><li>Please contact CumulusPro for the initial setup.</li></ul>                                                                                                                                                                                                                                                        |
| Database Table Name                   | The name of the table in the database contains the lookup values.                                                                                                                                                                                                                                                                                                                                 |
| Database Value Field Name             | The value that is returned to the index field after selection.                                                                                                                                                                                                                                                                                                                                    |
| Database Description Field Name       | The Database description field name is displayed to the user in My Home to select.                                                                                                                                                                                                                                                                                                                |
| Database Group Field Name (optional)  | <ul><li>This field can be used to group similar values together.</li></ul><p></p><ul><li>For instance, in a product catalog, it can group all items labeled as 'Tools' under one title and all 'Electrical' items under another.</li></ul>                                                                                                                                                        |
| Database Filter Field Name (optional) | <ul><li>This option filters the database based on the value from 'WF Field Name Value'.</li></ul><p></p><ul><li>Using this filter makes 'WF Field Name Value' a mandatory field.</li></ul>                                                                                                                                                                                                        |
| WF Field Name Value (optional)        | If you need the value from the 'Database Value Field Name' column (typically a database ID or key) to be stored in a separate index field, specify the name of that index field in this setting.                                                                                                                                                                                                  |
| WF Field Name Filter                  | Straatos Index field that you want to filter the database with. For example: a company name, then you get a list of suppliers belonging to that Company.                                                                                                                                                                                                                                          |
| Show all entries                      | <ul><li>By default, only the top 25 entries are displayed, requiring users to start typing to find specific entries. This is suitable for long lists, like Supplier Databases with thousands of entries.</li></ul><p></p><ul><li>If set to 'On', all entries that match the filter criteria are displayed, making it easier for users to select items, particularly with shorter lists.</li></ul> |

***

## Regular Expression

Under the menu Regular Expressions are two different types of easy to configure business rules combined.

* Regular Expression:&#x20;
  * used to validate formats like Account Numbers or Tax Numbers using a pattern matcher. If the input does not match the specified pattern, an error message is displayed, prompting the user to provide a correct format.

* Invoke Business Rule Validation:&#x20;
  * executes a JavaScript function that returns true or false based on the validation logic. If it returns false, an error message is displayed, and the user must correct the value. This validation can utilize complex rules from the Script Library.


# Straatos API

The links below will direct you to the topics listed

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>Straatos API V2</td><td></td></tr><tr><td>Straatos Interact API</td><td><a href="/pages/1c6a6574f2b6f24b04f42686572cfb20315e3c50">/pages/1c6a6574f2b6f24b04f42686572cfb20315e3c50</a></td></tr><tr><td>Straatos Adapter Service</td><td><a href="/pages/129d726f984715355240f4234a6243705ffa2078">/pages/129d726f984715355240f4234a6243705ffa2078</a></td></tr><tr><td>Straatos Script Service API</td><td><a href="/pages/590179f634d9db593c71af3af64bda7edad8db13">/pages/590179f634d9db593c71af3af64bda7edad8db13</a></td></tr><tr><td>Straatos XML API</td><td><a href="/pages/92e8cd5139cf99a54a399d3fbc6e52f29d577293">/pages/92e8cd5139cf99a54a399d3fbc6e52f29d577293</a></td></tr></tbody></table>


# Straatos API V2


# Malware Scanning for Uploaded Documents

Security feature from Straatos that scans uploaded files for malicious software.

Straatos Malware Scanning is a security feature that scans uploaded files for malicious software (such as viruses, ransomware, or other harmful code) before they are processed or stored. This helps prevent infected files from entering the system and ensures that only clean files are made available for further processing.

If malware scanning is enabled, when the Upload API is called, the files are initially stored in an isolation container. Only after the malware scan completes successfully, the files move automatically to the corresponding task, where they become available for further processing.

* If the scan completes successfully, the Upload API returns an OK status, and the file is moved to the tasl where it becomes available for processing.
* If malware is detected, the response will be “MalwareScanFileInfected” and the file is not processed.
* If you uploaded multiple files in a single Upload call, and one of them os detected with malware, then this set of files will not get uploaded.

### Prerequisites

There are some prerequisites to enable/disable the Malware Scanning.

1. An Organisation has been created for the project. You will need the OrganisationId when calling the API.
2. Your account has been invited to the Organisation and assigned to the Organisation Admin group.
3. A valid access token for an Organisation Admin account is included in the Authorization request header.

### Enabling or Disabling Malware Scanning

Malware scanning can only be configured at the Organisation level. Tenant-level and Group-level configuration is not supported.

To enable malware scanning, send a PUT request to:

{% hint style="info" icon="link-simple" %}
*{Straatos API domain}/IAM/Organisations/{OrganisationId}*
{% endhint %}

Include the Header with the access token:

```json
"Authorization": {access_token}
```

Set the malwareScanningEnabled property to either true or false:

```json
"malwareScanningEnabled": true
```

When you set everything correctly you will receive a 200 OK result.

Other possible responses:

* 400 : Bad request, please check the validity of your data
* 401/403: Unauthorized/Forbidden, please check if your access token is valid or no
* 500: Possible issue with server connection, please get in touch with our support team

Below is the cURL example:

```
url --request PUT \
  --url https://{straatos-api-domain}/IAM/Organisations/{OrganisationId} \
  --header "Authorization: Bearer {access_token}" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --data '{
    "malwareScanningEnabled": true
  }'

```


# Straatos Interact API

This articles describes Staatos Interact API functionality

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, please refer to [FAQs](#faqs).

Click highlighted areas for more information:

* [Create a new Task in Straatos](#sample-code-1-create-a-new-task-in-straatos).
* [Create a new Task in Straatos with Index fields](#sample-code-2-create-a-new-task-in-straatos-with-index-fields).
* [Create a new Task in Straatos with Index fields and JPG Files / Pages](#sample-code-3-create-a-new-task-with-index-fields-and-jpg-files-pages).
* [Forward a Task in the workflow and update field values](#sample-code-4-forward-a-task-in-the-workflow-and-update-field-values).
* [Upload a PDF File](#sample-code-5-upload-a-pdf-file).
* [Polling](#sample-code-6-polling).
* [Usage of getDocumentInfo](#sample-code-7-usage-of-getdocumentinfo).
* [Get additional stored documents](#sample-code-8-get-additional-stored-documents).
* [Uploading a PDF as additional data](#sample-code-9-uploading-a-pdf-as-additional-data).
* [XML without namespaces](#sample-code-10-xml-without-namespaces).
* [XML with namespaces](#sample-code-11-xml-with-namespaces).
* [Securing the interact script](#sample-code-12-securing-the-interact-script).

#### References

* [FAQs](#faqs).
* [API DOCS](#api-documentation).

***

### Benefits

* Straatos accepts web service calls from any POST/GET web service call, regardless of parameters, headers, or body.
* Reduce development time of integration from weeks to days.
* No additional hosting fees and third-party service provider.
* Control functionality and data available through the web service.
* Control security of the web service.

***

### How Does it Work

Straatos Interact API allows you (or the CumulusPro Professional Services team) to define your own Straatos API in a simple JavaScript. Hosting of API is done on Straatos Platform and API can be accessed through Admin Panel.

***

### Web Service URL

Every organisation in Straatos has its own URL. The URL is unique to specific organisation and cannot be changed.

Example:

* `https://effektifconnector.cumuluspro.net/ConnectorService.svc/json/Interact/`&#x20;

{% hint style="info" %}
Actual URL can change based on your organisation and geographical location.
{% endhint %}

#### Configuration of the Web Service

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.

<table><thead><tr><th width="123.54541015625">Name</th><th width="141.1817626953125">Where to look</th><th>Description</th></tr></thead><tbody><tr><td>createTask</td><td>Line 1</td><td><p>New web service is defined.</p><p></p><p>Web service calls are checked if it is for web service.createTask.</p></td></tr><tr><td></td><td>Line 4</td><td>New task in Straatos created for the process ‘Test QA Workflow’ and Start Event ‘Start’.</td></tr><tr><td></td><td>Line 6</td><td>Response provided to calling web service.</td></tr></tbody></table>

#### Sample Code

```javascript
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, Admin Panel provides a Log where `console.log` can write logging data.

To call this web service from a 3rd party application, the following URL can be used:

Example:

* <https://effektif-connector.cumuluspro.net/ConnectorService.svc/json/Interact//createTask>

***

### API Documentation

This section describes how to use Straatos interact API to create new tasks, upload documents, update existing tasks, return values of tasks to 3rd party application.

#### API Server and Base URL

<table><thead><tr><th width="165.8182373046875">Region</th><th>URL</th></tr></thead><tbody><tr><td>Europe</td><td><code>https://effektifconnector.cumuluspro.net/ConnectorService.svc/json/Interact/</code></td></tr><tr><td>Switzerland</td><td><code>https://effektifconnector-ch.cumuluspro.net/ConnectorService.svc/json/Interact/</code></td></tr><tr><td>Asia</td><td><code>https://effektifconnector-asia.cumuluspro.net/ConnectorService.svc/json/Interact/</code></td></tr></tbody></table>

To know more about Organisation ID, refer to [FAQs](#faqs).

#### Request and Response Parameter

Request and response parameter contain information sent to web service and response sent by web service to web service call. Refer to [Sample Code](#sample-code) section for more details.

#### Request

<table><thead><tr><th width="170.272705078125">Name</th><th width="161.63629150390625">Type</th><th>Description</th></tr></thead><tbody><tr><td>pathSegments</td><td>string</td><td>Path segments. for example:</td></tr><tr><td>URL</td><td>pathSegments</td><td></td></tr><tr><td>https://domain.net/Connector.svc/json/Interact/A3B23-GUID-E76B/P2/P3</td><td>['A3B23-GUID-E76B', 'P2', 'P3']</td><td></td></tr><tr><td>queryParameters</td><td></td><td>For example: URL: <code>https://domain.net/Connector.svc/json/Interact/A3B23-GUID-E76B/P2/P3?id=123&#x26;type=b</code></td></tr><tr><td>headers</td><td>?</td><td><p>Request headers as passed into the Interact call, for example, </p><p></p><p>{ 'Accept': 'application/json', 'X-Header': '123' }</p></td></tr><tr><td>contentType</td><td>string</td><td>Request content type as passed into the Interact call, for example, application/json</td></tr><tr><td>body</td><td></td><td>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/').</td></tr><tr><td>multipart</td><td>MultiPartRequest</td><td>Parsed parts of the multipart, only available if the request is a multipart request (Content-Type starts with 'multipart/')</td></tr></tbody></table>

#### Response

<table><thead><tr><th width="167.18182373046875">Name</th><th width="142.727294921875">Type</th><th>Description</th></tr></thead><tbody><tr><td>status</td><td>number</td><td>HTTP status code to return to the client, 200 by default</td></tr><tr><td>headers</td><td></td><td><p>Response headers that are returned to the client.</p><p></p><p>For example: { 'Accept': 'application/json', 'X-Header': '123' }</p></td></tr><tr><td>body</td><td></td><td>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()</td></tr></tbody></table>

***

### Straatos Functions

Straatos contains functions to interact with the platform.

<table><thead><tr><th width="202.6363525390625">Name</th><th width="247.4544677734375">Attribute</th><th>Description</th></tr></thead><tbody><tr><td>findDocuments</td><td>fn(workflowName: string, activityName: string, variables: ?) -> [number]</td><td>Find documents in the specified workflow step that match the variables (for example, { 'InvoiceNumber': 'IN12345' }). Returns an array with document ids.</td></tr><tr><td>messageWorkflow</td><td>fn(workflowName: string, activityName: string, documentIds: [number], variables: ?)</td><td>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.</td></tr><tr><td>addDocument</td><td>fn(workflowName: string, startEventName: string) -> number</td><td>Create a document, required for startWorkflow. Returns the document id.</td></tr><tr><td>addComment</td><td>fn(documentId: number, comment: string, commentDateTimeIso8601: string)</td><td>Adds a document comment. commentDateTimeIso8601 should be in ISO datetime format (YYYYMMDDThhmmss ie 2021-04-10T16:56:02Z)</td></tr><tr><td>startWorkflow</td><td>fn(documentId: number, variables: ?)</td><td>Start the workflow / start event for the specified document (created with addDocument). The specified (workflow) variables (for example, { 'Status': 'Verified' }) will be assigned.</td></tr><tr><td>getVariables</td><td>fn(documentId: number) -> ?</td><td>Get the workflow field values for the specified document (for example, { 'Name': 'John', 'InvoiceNumber': 'IN12345' })</td></tr><tr><td>setDocumentContent</td><td>fn(documentId: number, files: [?], filetype: string, createPagePreviews: bool, createPDFPreviews: bool)</td><td>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.</td></tr><tr><td>ajax</td><td>fn(parameters: AjaxParameters) -> jqXHR</td><td>Perform a synchronous HTTP (Ajax) request.</td></tr><tr><td>getString</td><td>fn(data: ?) -> string</td><td>Convert byte[] to string using UTF-9 encoding</td></tr><tr><td>getBytes</td><td>fn(data: string) -> ?</td><td>Convert string to byte[] using UTF-8 encoding</td></tr><tr><td>decodeBase64</td><td>fn(data: string) -> ?</td><td>Decode base64 string to byte[]</td></tr><tr><td>encodeBase64</td><td>fn(data: ?) -> string</td><td>Encode base64 byte[] to string</td></tr><tr><td>newFormData</td><td>fn() -> MultiPart</td><td>Create a new MultiPart object</td></tr><tr><td>newXMLDocument</td><td>fn(documentElementName: string, documentElementNamespace: string) -> JsXmlDocument</td><td>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.</td></tr><tr><td>parseXML</td><td>fn(data: ?) -> JsXmlDocument</td><td>Parses the data parameter (either a byte[] or string containing the XML and returns the XML document</td></tr><tr><td>transformXSL</td><td>fn(xslDocument: JsXmlDocument, inputDocument: JsXmlDocument) -> JsXmlDocument</td><td>Transforms the inputDocument using the xslDocument XSL. Returns the result as XML document</td></tr></tbody></table>

***

### XML

#### XML Document (JsXmlDocument)

To create an XML Document, use the following straatos methods:

* newXMLDocument.
* prseXML and.
* transformXSL.

<table><thead><tr><th width="208.0909423828125">Name</th><th width="242.6363525390625">Attribute</th><th>Description</th></tr></thead><tbody><tr><td>documentElement</td><td>JsXmlElement</td><td>The root element of the XML document</td></tr><tr><td>xml</td><td>string</td><td>Pretty printed XML string</td></tr><tr><td>xmlBytes</td><td>fn(encoding: string) -> ?</td><td>Returns a byte[] of the pretty printed XML, using the specified encoding. If no encoding is specified, UTF-8 is used.</td></tr></tbody></table>

#### XML Element (JsXmlElement)

XML Elements can be accessed throught the documentElement property of the XML Document and the XML Element methods selectElements, selectSingleElement and created with addElement.

<table><thead><tr><th width="209.90911865234375">Name</th><th width="240.818115234375">Attribute</th><th>Description</th></tr></thead><tbody><tr><td>text</td><td>string</td><td>Text value of the element, for example, CumulusPro would return 'CumulusPro'. Can also be updated, e.g. element.text = 'new value';</td></tr><tr><td>nodeName</td><td>string</td><td>Name of the element, for example, CumulusPro would return 'company'</td></tr><tr><td>namespacePrefix</td><td>string</td><td>If the element has a namespace, returns the prefix used for example, <a href="ns:company">ns:company</a>CumulusPro&#x3C;/ns:company> would return 'ns'</td></tr><tr><td>namespace</td><td>string</td><td>If the element has a namespace returns the namespace URI, for example, &#x3C;ns:company xmlns:ns="urn:my-urn">CumulusPro&#x3C;/ns:company> would return 'urn:my-urn'</td></tr><tr><td>attributes</td><td>?</td><td>Returns an object containing properties representing the attributes of the element, e.g. &#x3C;ns:company ns:attr1="1" attr2="2">CumulusPro&#x3C;/ns:company> would return { 'ns:attr1': '1', '{urn:my-urn}:attr1': '1', 'attr2': '2' }</td></tr><tr><td>xml</td><td>string</td><td>Pretty printed XML string</td></tr><tr><td>addAttribute</td><td>fn(name: string, value: string, namespaceURI: string)</td><td>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.</td></tr><tr><td>removeAttribute</td><td>fn(name: string)</td><td>Removes the attribute by name.</td></tr><tr><td>addElement</td><td>fn(name: string, namespaceURI: string) -> JsXmlElement</td><td>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.</td></tr><tr><td>remove</td><td>fn()</td><td>Remove the element from the document</td></tr><tr><td>selectElements</td><td>fn(xPath: string, namespaces: ?) -> [JsXmlElement]</td><td>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' }</td></tr><tr><td>selectSingleElement</td><td>fn(xPath: string, namespaces: ?) -> JsXmlElement</td><td>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' }</td></tr><tr><td>stringValue</td><td>fn(xPath: string, namespaces: ?) -> string</td><td>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' }</td></tr></tbody></table>

***

### AJAX Utility Function

<table><thead><tr><th width="207.81829833984375">Name</th><th width="540.727294921875">Description</th></tr></thead><tbody><tr><td>jqXHR</td><td>done: fn(callback: fn(data: ?, response: ?)) -> jqXHR fail: fn(callback: fn(response: ?, error: string)) -> jqXHR</td></tr><tr><td>AjaxParameters</td><td>GG4HPafC3gA7</td></tr><tr><td>MultiPart</td><td>nvqmhbnJhIlx</td></tr><tr><td>MultiPartFile</td><td>F7EoVe62tTIc</td></tr><tr><td>MultiPartRequest</td><td>FB2k6jQOgjbD</td></tr></tbody></table>

#### Sample Code

Simple process flow in Straatos as follows:

<figure><img src="/files/qgQjFNZaClCIBsKobh4Z" alt=""><figcaption></figcaption></figure>

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.

***

### Sample Code 1 - Create a new Task in Straatos

In this sample, a webservice is created that adds a new task in the workflow.

<table><thead><tr><th width="205.3636474609375">Name</th><th width="153.727294921875">Where to look</th><th>Description</th></tr></thead><tbody><tr><td>createTask</td><td>Line 1</td><td>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.</td></tr><tr><td>straatos.addDocument</td><td>Line 4</td><td>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.</td></tr><tr><td>response.body</td><td>Line 9</td><td>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';</td></tr></tbody></table>

#### Sample

```javascript
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;
}
```

***

### Sample Code 2 - Create a new Task in Straatos with Index fields

This sample shows submitting index field values as part of the webservice. The body may be multipart.

Key points:

* FirstName:
  * Example getting value from multipart body.
* LastName:
  * Example getting value from header.
* InvoiceNumber:
  * Example getting value from query parameter.

#### Sample

```javascript
if (request.pathSegments[1] == 'createTask') {

  var documentId = straatos.addDocument('Test QA Workflow', 'Start');

  // Adding Index fields values
  straatos.startWorkflow(documentId, {
    'FirstName': request.multipart.parameters.FirstName, // value from multipart body
    'LastName': request.headers.LastName,                // value from header
    'InvoiceNumber': request.queryParameters.InvoiceNumber // value from URI parameters
  });

  response.body = "Finished request of type " + request.pathSegments[1] + " DocumentID: " + documentId;
}
```

***

### Sample Code 3 - Create a new Task with Index fields and JPG Files / Pages

This sample attaches image files uploaded as multipart to a new Straatos Task.

{% hint style="info" %}
If files are uploaded as part of multipart, this works for multipage JPGs where each page is a separate JPG file.
{% endhint %}

#### Sample

```javascript
if (request.pathSegments[1] == 'createTask') {

  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,
    'LastName': request.headers.LastName,
    'InvoiceNumber': request.queryParameters.InvoiceNumber
  });

  response.body = "Finished request of type " + request.pathSegments[1] + " DocumentID: " + documentId;
}
```

***

### Sample Code 4 - Forward a Task in the workflow and update field values

Find documents in the 'Wait' step for a workflow and forward them by updating index fields.

<table><thead><tr><th width="180.8182373046875">Name</th><th width="136.6363525390625">Where to look</th><th>Description</th></tr></thead><tbody><tr><td>forward</td><td>Line 1</td><td>We created a new webservice called 'forward' as this is a completely different action to the create task.</td></tr><tr><td>Test QA Workflow</td><td>Line 2</td><td>We want to find a specific document in the workflow 'Test QA Workflow' in the process step 'Wait'.</td></tr><tr><td>InvoiceNumber</td><td>Line 2</td><td>We want to find a (all) documents where the invoice Number is the same as submitted in the header.</td></tr><tr><td>PaymentStatus</td><td>Line 6</td><td>Here we update the document in the workflow.<br><br>The '<code>PaymentStatus</code>' is an index field in the workflow that gets updated and the document gets routed to the next stage.</td></tr></tbody></table>

#### Sample

```javascript
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];
}
```

***

### Sample Code 5 - Upload a PDF File

This sample handles both PDF (raw body) and JPG (multipart) uploads.

```javascript
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, {});
  }
}
```

***

### Sample Code 6 - Polling

3rd party application may want to poll Straatos for documents. This example finds documents by index field and returns variables (index fields) for the first match.

```javascript
if (request.pathSegments[1] == 'poll') {

  var documentIds = straatos.findDocuments('Test QA Workflow', 'Wait', {
    'LastName': request.headers.Name
  });

  if (documentIds.length > 0) {
    response.body = JSON.stringify(straatos.getVariables(documentIds[0]));
  } else {
    response.body = 'Sorry, no documents found';
  }
}
```

{% hint style="info" %}
If you have the exact documentID (for example, 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.
{% endhint %}

***

### Sample Code 7 - Usage of getDocumentInfo

The script below uses the getDocumentInfo method on the Adapter and outputs the contents to the console.

```javascript
try {
  var documentInfo = straatos.getDocumentInfo(straatos.documentId);
  console.log(documentInfo);
  response.body = 'Ok!';
} catch(err) {
  response.body = 'Error: ' + err;
  console.log('error: ' + err);
}
```

***

### Sample Code 8 - Get additional stored documents

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.

```javascript
try {
  var documentInfo = straatos.getDocumentInfo(straatos.documentId);

  // Return only the additionalData 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);
}
```

***

### Sample Code 9 - Uploading a PDF as 'additional data'

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.

```javascript
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);
}
```

***

### Sample Code 10 - XML without namespaces

```javascript
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);
});
```

***

### Sample Code 11 - XML with namespaces

This script shows how to create a simple XML document with one namespace with a single prefix used on all elements and attributes.

```javascript
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);
});
```

***

### Sample Code 12 - Securing the interact script

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.

```javascript
//The interact API is looking for the 'submitTask'
if (activityName == 'submitTask') {
  try {
    var userId = straatos.validateSession(request.headers['X-Session-Id']);
    if (userId > 0) {
      var reqBody = JSON.parse(straatos.getString(request.body));
      var authRoles = straatos.adapter.getAccount({id: userId}).Roles;
      var authOk = false;

      authOk = authRoles.some(function(record){
        return record.Name === reqBody.wfstep;
      });

      if (authOk == true) {
        straatos.messageWorkflow('Production Line Process', reqBody.wfstep, [reqBody.taskId], {
          'taskListData': JSON.stringify(reqBody.taskListData),
          'taskDetails': JSON.stringify(reqBody.taskDetails),
          'action': reqBody.action
        });
      } else {
        response.body = '';
        response.status = 401;
      }
    } else {
      response.body = '';
      response.status = 401;
    }
  } catch(err) {
    console.log('Error: ' & err.message);
    response.status = 501;
    response.body = err;
  }
}
```

***

## FAQs

<details>

<summary>What are the usual challenges when two applications try to interact via web services?</summary>

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:

* 3rd party application makes changes to their push web service API calls.
* Straatos makes changes to its API definitions.
* Use of a 3rd party web service (or Platform) that makes the two web service calls to talk to each other (example: Zapier, Mulesoft).

</details>

<details>

<summary>What are the challenges of traditional approaches?</summary>

* 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 affecting other users:
  * Duration, cost, and effort to develop a customer-specific web service (days to weeks).
  * Agility to change Webservices.
  * No customer self-service to change the Webservices.

* 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.

</details>

<details>

<summary>What incoming web service calls are supported?</summary>

* 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.

</details>

<details>

<summary>Can more than one web service call be defined?</summary>

Yes, there is no limit on the number of different web service calls that can be defined in a single Straatos Interact Script.

Example for 3 web service calls:

* CreateTask.
* ForwardTask.
* RetrieveTaskInfo.

</details>

<details>

<summary>Security: how does a web service call get authorised?</summary>

The security can be built into the Straatos Interact Script. Options:

* No authentication: open web service.
* Web service Key/API Key: check the key in the script.
* OAuth2:&#x20;
  * Use ajax to obtain tokens and validate outside Straatos.

Authentication can be as secure and restrictive as needed.

</details>

<details>

<summary>Is data between web service calls encrypted?</summary>

Yes, all communication uses SSL encryption.

</details>

<details>

<summary>Can payload encryption be used?</summary>

Yes. The Interact Script can decrypt incoming encrypted payloads (if needed) or pass encrypted data through the workflow. Decryption and handling depend on processing needs.

</details>

<details>

<summary>What is Organisation ID?</summary>

The Organisation ID is a unique identifier that defines your organization and is used as part of the request URL when consuming the API.

How to find your Organisation ID:

1. Log in to the CumulusPro Admin Panel with your credentials. The CumulusPro Admin dashboard will appear.
2. In the dashboard, click Create Organisation.

{% hint style="info" %}
If the organisation is already available, please proceed to step 4.
{% endhint %}

3. Select the desired template. and click Next.
   1. The new organisation will appear on the dashboard.
4. From the dashboard, click the newly created organisation. A new dashboard will appear.
5. Click the organisation settings to view the organisation details. The organisation Settings page contains the Unique ID and all relevant information about the organization.

</details>


# Straatos Adapter Service API

This articles describes Straatos Adapter Service API

The Adapter Service is an extension of the Straatos Workflow, designed to enhance script service APIs and Interact APIs by providing built-in functionalities. This eliminates the need for developers to implement certain features manually, allowing for a more efficient development process.

Key Features:

* Enhances API capabilities without additional development effort.
* Provides pre-built methods that can be used in Interact APIs and Script APIs.
* Simplifies workflow integration by handling complex operations within Straatos.

How It Works:

* Developers can access adapter service methods within their script APIs or interact API.
* These methods can be used for data transformation, external system communication, and automation.
* The adapter service helps streamline workflow automation and integration with minimal coding.

***

### **Methods**

Below is a list of functionalities provided by Straatos platform.

<table><thead><tr><th width="361.272705078125">Method</th><th>Description</th></tr></thead><tbody><tr><td><a href="#get-document-info">Get Document Info</a></td><td>Retrieves the information about the document or task.</td></tr><tr><td><a href="#magick">Magick</a></td><td>This method incorporates an ImageMagick wrapper into the straatos data architecture. ImageMagick allows you to generate, edit, compose and convert digital photos. To learn more about the services that ImageMagick can provide, refer to https://imagemagick.org/.</td></tr><tr><td><a href="#add-document-comment">Add Document Comment</a></td><td>Use this method to add a comment to the specific document identified by the documentId. DocumentId is the unique identifier for a document. The current Document ID is used as the default value.</td></tr><tr><td><a href="#image-detect">Image Detect</a></td><td>Determine the presence of the Swiss flag and human faces on images/identity cards.</td></tr><tr><td><a href="#add-additional-data">Add Additional Data</a></td><td>Add additional files to an existing document.</td></tr><tr><td><a href="#add-additional-data-with-url">Add Additional Data With URL</a></td><td>Add additional files to an existing document from a specified path.</td></tr><tr><td><a href="#remove-additional-data">Remove Additional Data</a></td><td>Remove additional data from a document.</td></tr><tr><td><a href="#detect-barcodes">Detect Barcodes</a></td><td>Detect barcodes on specific document page identified by the documentId.</td></tr><tr><td><a href="#detect-barcodes-v2">Detect Barcodes V2</a></td><td>Detect barcodes in a document, using a newer and faster engine (optionally specified by documentId)</td></tr><tr><td><a href="#get-account">Get Account</a></td><td>Retrieves account information for specific account id.</td></tr><tr><td><a href="#list-accounts-for-organization">List Accounts For Organisation</a></td><td>Retrieves all account information in an organisation.</td></tr><tr><td><a href="#list-accounts-for-manager">List Accounts For Manager</a></td><td>Retrieves information about all accounts managed by a specific manager.</td></tr><tr><td><a href="#face-detection">Face Detection</a></td><td>Determines whether an image contains a face, which can be useful when processing passports or identification cards.</td></tr><tr><td><a href="#split-document">Split Document</a></td><td>Divide a single document into two separate documents.</td></tr><tr><td><a href="#merge-documents">Merge Document</a></td><td>Combine two documents into a single document.</td></tr><tr><td><a href="#delete-document-page">Delete Document Page</a></td><td>Deletes a page from a document permanently. Once deleted, there is no method to recover a document!</td></tr><tr><td><a href="#html-to-pdf">Html To Pdf</a></td><td>Converts an HTML input to a PDF file. It is possible to generate an Audit Report and attach it to a document.</td></tr><tr><td><a href="#zip">Zip</a></td><td>It generates a zip archive.</td></tr><tr><td><a href="#unzip">Unzip</a></td><td>Unzips a zipped document associated with a task and adds the zip file's contents as additional data.</td></tr><tr><td><a href="#pdf-to-image">Pdf To Image</a></td><td>Convert a PDF document to a multipage TIFF or a collection of JPG images and add as additional data. This function returns a URL that points to the first image.</td></tr><tr><td><a href="#create-searchable-pdf">Create Searchable Pdf</a></td><td><p>Create a searchable pdf file containing the results of a JSON file. This provided URL is:</p><p></p><ul><li><p>Local URL: </p><ul><li>It only contains the filename and retrieved from the CumuluPpro storage.</li></ul></li></ul><p></p><ul><li><p>Full URL: </p><ul><li>It contains the entire URL, beginning with HTTP.</li></ul></li></ul></td></tr><tr><td><a href="#create-merge-pdf">Create Merge PDF</a></td><td>Create a PDF document from a collection of PDF files and/or images. Provides a URL to the generated PDF.</td></tr><tr><td><a href="#set-error">Set Error</a></td><td>Configure a Straatos Error. Once configured, the Straatos Task generates an Error Event and displays the Error Message in the Monitor.</td></tr><tr><td><a href="#set-document-restriction">Set Document Restriction</a></td><td><p>Access to a document stored within Straatos is granted using one of two methods:</p><ul><li>Time-based restriction.</li></ul><p></p><ul><li>Access count restriction.</li></ul></td></tr><tr><td><a href="#create-account">Create Account</a></td><td>Create a new user account.</td></tr><tr><td><a href="#get-account">Get Account</a></td><td>Retrieve information about an existing account.</td></tr><tr><td><a href="#update-account">Update Account</a></td><td>Update a user's account information.</td></tr><tr><td><a href="#delete-account">Delete Account</a></td><td>Delete a user account.</td></tr><tr><td><a href="#start-workflow">Start Workflow</a></td><td>Start a new task in a workflow.</td></tr><tr><td><a href="#get-file-as-string-get-file-as-base64-get-file-as-bytearray">Get File As String - Get File As Base64 - Get File As ByteArray</a></td><td>Retrieves a file either as a string or as a Base64 file based on a provided URL to the file.</td></tr><tr><td><a href="#list-roles-for-organisation">List Roles For Organisation</a></td><td>List all of the roles and functions of the current organisation.</td></tr></tbody></table>

***

### **Get Document Info**

#### **Input Parameters**

| Name       | Required/Optional | Description                                                                                               |
| ---------- | ----------------- | --------------------------------------------------------------------------------------------------------- |
| DocumentId | Optional          | DocumentId is the unique identifier for a document. The current Document ID is used as the default value. |

#### **Sample Request Body**

```javascript
var documentInfo = straatos.adapter.getDocumentInfo();
```

#### **Response Parameters**

<table><thead><tr><th width="357.6363525390625">Name</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td>The unique identifier to obtain information about a document.</td></tr><tr><td>region</td><td>The S3 region is used for storage.</td></tr><tr><td>originalURL</td><td>When available, the original URL of the uploaded document will be displayed.</td></tr><tr><td>documentPages</td><td>A list of documentPages. This list contains the following fields:</td></tr><tr><td>lastModifiedDateTime</td><td>DateTime when the document was last updated.</td></tr><tr><td>Comments</td><td>A list of comments. This list contains the following fields:</td></tr><tr><td>timestamp</td><td>When the comment was entered.</td></tr><tr><td>comment</td><td>The actual comment.</td></tr><tr><td>additionalData</td><td>A list of all the additional data. This list contains the following fields:</td></tr><tr><td>width</td><td>The width of the original document. Set the value of GetDimensions to true.</td></tr><tr><td>height</td><td>The height of the original document. Set the value of GetDimensions to true.</td></tr></tbody></table>

| Name  | Description                                                                                            |
| ----- | ------------------------------------------------------------------------------------------------------ |
| key   | The additional data key.                                                                               |
| index | When multiple additional data’s with the same key exist, this index is set with an incremental number. |
| url   | The URL where the file can be downloaded.                                                              |

| Name      | Description                   |
| --------- | ----------------------------- |
| name      | The name of the comment.      |
| timestamp | When the comment was entered. |
| comment   | The actual comment.           |

| Parameter      | Description                               |
| -------------- | ----------------------------------------- |
| originalURL    | Optional.                                 |
| pagePreviewURL | Optional.                                 |
| thumbnailURL   | Optional.                                 |
| orientation    | The detected orientation of the document. |
| filename       | The original filename of the uploaded.    |
| pdfPageURL     | Optional.                                 |

***

### **Magick**

#### **Input Parameters**

<table><thead><tr><th width="356.727294921875">Name</th><th>Description</th></tr></thead><tbody><tr><td>DocumentId</td><td>documentId is the unique identifier for a document. This is an optional parameter. (default: _documentId)</td></tr><tr><td>Command</td><td>The imageMagick command to execute; by default, convert is used.</td></tr><tr><td>InputAdditionalDataKey</td><td>If not null then the input file will be the additional file identified by the data key to use. If empty, then use the original URL (or if empty, preview URL) on a page level.</td></tr><tr><td>OutputAdditionalDataKey</td><td>Do not return the output URL but store the output as additional data. If this additional data key already exists, the new version will overwrite it.</td></tr><tr><td>OutputFormat</td><td>If the information is true, the result will contain the redirected output of the command rather than the URL of the output image. Another possible value is JSON, which results in the return of a JSON document containing all processed parameters.</td></tr><tr><td>ReturnOutput</td><td>if true and OutputFormat is not info, then '-' is appended.</td></tr><tr><td>OutputExtension</td><td></td></tr><tr><td>PageIndex</td><td>Indicates the page number to be used (zero-based).</td></tr><tr><td>Parameters</td><td>Parameters to pass to the imageMagick call.</td></tr></tbody></table>

#### **Sample Code**

```javascript
try {
    var magickDetect = {
        OutputFormat: 'json',
        ReturnOutput: true,
        PageIndex: 0,
        Parameters:
            //'-gravity ' + gravity +
            ' -crop 50%x50%! ' +
            '-normalize ' +
            '-fuzz 30% -fill white +opaque red ' +
            '-monochrome ' +
            '-morphology close disk:3 ' +
            '-trim ' +
            '-resize 250x250 ' +
            '-shave 14x5 ' +
            '-moments'
    };
    var output = straatos.adapter.magick(magickDetect);
    console.log(output);
    MagickStatus = "OK";
}
catch (err) {
    console.log('error:' + err);
}
```

#### **Sample Response**

The following response is snippet of the actual result. It can either be JSON with output of imageMagick, or URL of resulting image.

```json
"image": {
    "name": "-",
    "baseName": "18625465-1135-4f7c-9806-0b8cd35f23c7.jpg",
    "format": "JPEG",
    "formatDescription": "JPEG",
    "mimeType": "image/jpeg",
    "class": "DirectClass",
    "geometry": {
        "width": 222,
        "height": 240,
        "x": 0,
        "y": 0
    },
    "resolution": {
        "x": 200,
        "y": 200
    },
    "printSize": {
        "x": 1.1100000000000001,
        "y": 1.2
    },
    "units": "PixelsPerInch",
    "type": "Bilevel",
    "baseType": "TrueColorAlpha",
    "endianess": "Undefined",
    "colorspace": "sRGB",
    "depth": 1,
    "baseDepth": 8,
    "channelDepth": {
        "alpha": 1,
        "gray": 1
    },
    "pixels": 53280,
    "channelStatistics": {
        "Alpha": {
            "min": "255",
            "max": "255",
            "mean": "255",
            "standardDeviation": "0",
            "kurtosis": "0",
            "skewness": "0"
        },
    }
}
```

***

### **Add Document Comment**

#### **Input Parameters**

<table><thead><tr><th width="357.6363525390625">Name</th><th>Description</th></tr></thead><tbody><tr><td>DocumentId</td><td>DocumentId is the unique identifier for a document. This is an optional parameter. (default: _documentId)</td></tr><tr><td>Comment</td><td>The text of the comment.</td></tr><tr><td>CommentTimestamp</td><td>The (optional) timestamp should be stored with the comment. If the date/time field is left blank, the current date/time will be used.</td></tr><tr><td>AuthAccountId</td><td>The id of the CumulusPro account.</td></tr><tr><td>LoginName</td><td>This information will be stored in the Comment table, with the LoginName displayed during Web validation.</td></tr><tr><td>Name</td><td>This information will be stored in the Comment table, with the row name displayed during Web validation.</td></tr></tbody></table>

#### **Sample Code**

```javascript
var commentLines = 'This is a test comment';
try{
	var addCommentInput ={
		Comment: commentLines,
		AuthAccountId: '1234',
		LoginName: 'test.account@test.com',
		Name: 'test account'
	};
	var documentInfoString = straatos.adapter.addDocumentComment(addCommentInput);
}
catch(err){
	console.log('error:' + err);
}
```

#### **Sample Response**

Upon success, response body contains an empty string (“”).

***

### **Image Detect**

#### **Input Parameters**

<table><thead><tr><th width="357.6363525390625">Name</th><th>Description</th></tr></thead><tbody><tr><td>DocumentId</td><td>DocumentId is the unique identifier for a document. This is an optional parameter. (default: _documentId)</td></tr><tr><td>InputAdditionalDataKey</td><td>When set, use an additionalData file as input, otherwise use OriginalUrl (or, if empty, the preview URL on page level)</td></tr><tr><td>PageIndex</td><td>0-based pageIndex of the page to use.</td></tr><tr><td>EnableFaceDetection</td><td>When returning the execution result, this parameter specifies whether or not face detection should be considered</td></tr><tr><td>EnableLandmarkDetection</td><td>Specifies whether face landmark detection should be performed to determine whether the face is forward/upright and to validate the result of the face detection.</td></tr><tr><td>MinimumMatchingScore</td><td>This value specifies the minimum matching score that should be used when identifying the flag pattern.</td></tr></tbody></table>

#### **Output Status**

<table><thead><tr><th width="358.5455322265625">Value</th><th>Description</th></tr></thead><tbody><tr><td>-1</td><td>If there is an error while parsing command line arguments or any file fails to load/save</td></tr><tr><td>0</td><td>If there is a global negative match</td></tr><tr><td>1</td><td>If there is a global positive match</td></tr></tbody></table>

#### **Sample Output JSON**

```json
{
	"FaceDetectionEnabled": true,
	"LandmarkDetectionEnabled": true,
	"FlagFound": true,
	"FaceFound": false,
	"FlagScore": 0.9959738254547119,
	"DocBottomLeftX": 43.44289779663086,
	"DocBottomLeftY": 1388.8232421875,
	"DocBottomRightX": 2211.49609375,
	"DocBottomRightY": 1394.5150146484375,
	"DocTopLeftX": -7.8344855308532715,
	"DocTopLeftY": 0.8703601360321045,
	"DocTopRightX": 2182.6748046875,
	"DocTopRightY": 2.0112831592559814,
	"FaceBottomLeftX": 244.07904052734375,
	"FaceBottomLeftY": 1130.546875,
	"FaceBottomRightX": 658.9694213867188,
	"FaceBottomRightY": 1131.473388671875,
	"FaceTopLeftX": 229.14334106445312,
	"FaceTopLeftY": 708.306396484375,
	"FaceTopRightX": 645.33544921875,
	"FaceTopRightY": 708.9693603515625,
	"FlagBottomLeftX": 133.9904022216797,
	"FlagBottomLeftY": 372.49267578125,
	"FlagBottomRightX": 411.7124328613281,
	"FlagBottomRightY": 372.79376220703125,
	"FlagTopLeftX": 123.77064514160156,
	"FlagTopLeftY": 88.54669189453125,
	"FlagTopRightX": 402.07513427734375,
	"FlagTopRightY": 88.7286148071289,
}
```

<table><thead><tr><th width="358.54541015625">Name</th><th>Description</th></tr></thead><tbody><tr><td>FaceDetectionEnabled</td><td>Indicates whether face detection was enabled.</td></tr><tr><td>LandmarkDetectionEnabled</td><td>Indicates whether landmark detection was enabled.</td></tr><tr><td>FaceFound</td><td>Indicates whether a face was discovered in the document's image.</td></tr><tr><td>FlagFound</td><td>Indicates whether or not the flag pattern was correctly identified.</td></tr><tr><td>FlagScore</td><td>The resulting score for identifying flag patterns.</td></tr><tr><td>Doc...</td><td>- 4 point coordinate for the document boundaries on the input image.</td></tr><tr><td>Face...</td><td>- 4 point coordinate for the face boundaries on the input image.</td></tr><tr><td>Flag...</td><td>- 4 point coordinate for the flag pattern boundaries on the input image.</td></tr></tbody></table>

#### **Sample Code**

```javascript
var ImageInfo = {
    InputAdditionalDataKey: "attachment:image/jpeg:FrontID-RV (1).jpg",
    EnableFaceDetection: true
};

console.log(JSON.stringify(ImageInfo));

try {
    var outputJson = JSON.parse(
        JSON.parse(straatos.adapter.imageDetect(ImageInfo))
    );
    console.log(JSON.stringify(outputJson));
} catch (err) {
    console.log('error: ' + err);
}
```

#### **Sample Response**

```json
{
	""DocBottomLeftX"": -13.175889015197754,
	""DocBottomLeftY"": 1418.9727783203125,
	""DocBottomRightX"": 2221.368408203125,
	""DocBottomRightY"": 1447.650390625,
	""DocTopLeftX"": 18.879119873046875,
	""DocTopLeftY"": -25.148832321166992,
	""DocTopRightX"": 2214.426025390625,
	""DocTopRightY"": 22.742834091186523,
	""FaceDetectionEnabled"": false,
	""FaceFound"": false,
	""FlagBottomLeftX"": 141.9219207763672,
	""FlagBottomLeftY"": 356.0522766113281,
	""FlagBottomRightX"": 425.9892578125,
	""FlagBottomRightY"": 361.57977294921875,
	""FlagFound"": true,
	""FlagScore"": 0.9895056486129761,
	""FlagTopLeftX"": 147.8835906982422,
	""FlagTopLeftY"": 66.41143035888672,
	""FlagTopRightX"": 430.9324645996094,
	""FlagTopRightY"": 72.42932891845703,
	""LandmarkDetectionEnabled"": false
}
```

***

### **Add Additional Data**

#### **Input Parameters**

<table><thead><tr><th width="357.6363525390625">Name</th><th>Description</th></tr></thead><tbody><tr><td>DocumentId</td><td>DocumentId is the unique identifier for a document. This is an optional parameter. (default: _documentId)</td></tr><tr><td>FormData</td><td>The actual content of the data file.</td></tr><tr><td>Extension</td><td>The extension (=filetype) of the file to store.</td></tr><tr><td>Key</td><td>AdditionalData is stored under this key.</td></tr></tbody></table>

#### **Sample Code**

```javascript
var formData = straatos.newFormData();
var testXml = '<additionalData>Test</additionalData>';

formData.append(testXml);
addAdditionalDataStatus = 'False';

try {
    var output = straatos.adapter.addAdditionalData(
        docID,
        formData.getByteArray(),
        '.xml',
        testKey
    );
    console.log(JSON.stringify(output));
} catch (err) {
    console.log('error: ' + err);
}
```

#### **Result**

Upon success, response body contains an empty string (“”).

***

### **Add Additional Data with URL**

This method is preferred over AddAdditionalData, because it does not load the whole file in memory.

#### **Sample Code**

```javascript
try {
    straatos.adapter.addAdditionalDataWithUrl({
        DocumentId: straatos.documentId,
        AdditionalDataKey: 'UrlKey',
        Extension: '.jpeg',
        FileUrl: 'https://images.unsplash.com/photo-1509043759401-136742328bb3'
    });
} catch (err) {
    console.log('error: ' + err);
}
```

#### **Result**

On success, the response body contains an empty string (“”).

***

### **Remove Additional Data**

#### **Sample Code**

```javascript
try {
    // Remove additional data
    straatos.adapter.removeAdditionalData({
        AdditionalDataKey: 'HtmlToPDF2'
    });
} catch (err) {
    console.log('Err Remove Additional Data: ' + err);
}
```

***

### **Detect Barcodes**

{% hint style="info" %}
This is an older version of the Detect Barcodes. It is still recommend that you use [Detect Barcodes V2.](#_Detect_Barcodes_V2)
{% endhint %}

{% hint style="info" %}
&#x20;In most cases, no additional parameters are needed. If no parameters are defined, the engine will try to detect all Barcodes on the Original Document of the current Document.
{% endhint %}

#### **Input Parameters**

<table><thead><tr><th width="359.4544677734375">Name</th><th>Description</th></tr></thead><tbody><tr><td>DocumentId</td><td>DocumentId is the unique identifier for a document. This is an optional parameter. (default: _documentId)</td></tr><tr><td>Faster</td><td>When enabled, an algorithm makes additional attempts to locate a disable barcode. This is an optional value.</td></tr><tr><td>Formats</td><td><p>[Optional] The barcode format to look for. Possible values are: 2D Barcodes:</p><p></p><ul><li>QR.</li><li>MicroQR.</li><li>DATA_MATRIX.</li><li>PDF417.</li><li>1D Barcodes.</li><li>CODABAR.</li><li>CODE_39.</li><li>EAN8.</li><li>EAN_13.</li><li>ITF.</li><li>UPC_A.</li><li>UPC_E.</li></ul></td></tr><tr><td>PdfMatchPattern</td><td>[Optional] Regular expression to match. Only works if the original document is a PDF. This is an optional value.</td></tr><tr><td>PageIndexes</td><td>The 0-based pageIndex(es) of the pdf document to which barcodes should be detected. To specify multiple pages, use a comma to separate indexes (,). This is an optional value.</td></tr></tbody></table>

{% hint style="info" %}
The earlier version of barcode engine (pre July 2021) is still available and can be used with the following function straatos.adapter.detectBarcodes
{% endhint %}

#### **Sample Code**

```javascript
var detectBarcodes = {
    Formats: ['QR']
    // PageIndexes: 0,
    // InputAdditionalDataKey: 'attachment:image/jpeg:QRCoded.jpg',
    // PdfMatchPattern: /[a-zA-Z]{4}-\d{4}-\d{6}$/
};

detectBarcodesStatus = 'False';

try {
    var barcodes = straatos.adapter.detectBarcodesV2(detectBarcodes);
    console.log(JSON.stringify(barcodes));
} catch (err) {
    console.log('error: ' + err);
}
```

#### **Sample Response**

```json
{
    "NumberOfBarcodesDetected": 1,
    "Pages": [
        {
            "Barcodes": [
                {
                    "Coordinates": [
                        { "X": 60, "Y": 129 },
                        { "X": 60, "Y": 57 },
                        { "X": 132, "Y": 57 },
                        { "X": 120, "Y": 117 }
                    ],
                    "Type": "QR_CODE",
                    "Value": "This is a QR Code by CumulusPro"
                }
            ],
            "PageNumber": 1
        },
        {
            "Barcodes": [],
            "PageNumber": 2
        }
    ]
}
```

***

### **Detect Barcodes V2**

#### **Input Parameters**

<table><thead><tr><th width="357.6363525390625">Name</th><th>Description</th></tr></thead><tbody><tr><td>DocumentId</td><td>DocumentId is the unique identifier for a document. This is an optional parameter. (default: _documentId)</td></tr><tr><td>PageIndexes</td><td>An array of the page(s) that should be scanned. The pages should be defined as 0-based index numbers.</td></tr><tr><td>Formats</td><td><p>An array of barcode format(s) to look for. Possible values are:</p><ul><li>QR.</li><li>MicroQR.</li><li>DATA_MATRIX.</li><li>PDF417.</li><li>CODABAR.</li><li>CODE_39.</li><li>EAN_8.</li><li>EAN_13.</li><li>ITF.</li><li>UPC_A.</li><li>UPC_E.</li></ul><p></p><p>GdPicture options:</p><ul><li>Industrial2of5.</li><li>Inverted2of5.</li><li>Inverted2of5.</li><li>Interleaved2of5.</li><li>Iata2of5.</li><li>Matrix2of5.</li><li>Code39.</li><li>Codeabar.</li><li>BcdMatrix.</li><li>DataLogic2of5.</li><li>Code128.</li><li>CODE93.</li><li>EAN13.</li><li>UPCA.</li><li>EAN8.</li><li>UPCE.</li><li>ADD5.</li><li>ADD2.</li></ul></td></tr></tbody></table>

#### **Sample Code**

```javascript
try {
    var barcodes = straatos.adapter.detectBarcodesV2({});
    console.log(JSON.stringify(barcodes));
} catch (err) {
    console.log('error: ' + err);
}
```

***

### **Get Account**

#### **Input Parameters**

<table><thead><tr><th width="358.54541015625">Name</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td>The id of the account (AuthAccount)</td></tr></tbody></table>

#### **Response Parameters**

The response body contains an object with the following properties:

<table><thead><tr><th width="357.6363525390625">Name</th><th>Description</th></tr></thead><tbody><tr><td>Id</td><td>The id of the account</td></tr><tr><td>ManagerAuthAccountId</td><td>The (optional) id of the user's manager as configured in Admin Panel</td></tr><tr><td>LoginName</td><td>The login name (email address)</td></tr><tr><td>Name</td><td>The (optional) name as configured in Admin Panel</td></tr><tr><td>UserIdentifier</td><td>The (optional) user identifier as configured in Admin Panel</td></tr><tr><td>Roles</td><td>A array of roles, each with its own Id, Name, and Functions (array of functions containing Id, Name)</td></tr></tbody></table>

#### **Sample Code**

```javascript
var input = {
    id: accountId
};

try {
    var output = straatos.adapter.getAccount(input);
    console.log(JSON.stringify(output));
} catch (err) {
    console.log('error: ' + err);
}
```

#### **Sample Response**

```json
{
    "Id": 20283,
    "LoginName": "test.account@test.com",
    "ManagerAuthAccountId": 1234,
    "Name": "Test Account",
    "Roles": [
        {
            "Functions": [
                {
                    "Id": 3,
                    "Name": "My Home"
                }
            ],
            "Id": 11064,
            "Name": "Myhome test"
        }
    ],
    "UserIdentifier": ""
}
```

***

### **List Accounts For Organization**

#### **Sample Code**

```javascript
listAccountForOrganisationStatus = 'False';

try {
    var output = straatos.adapter.listAccountsForOrganization({});
    console.log(JSON.stringify(output));
} catch (err) {
    console.log('error: ' + err);
}
```

#### **Sample Response**

Response body contains an array of objects with properties as detailed under Get Account section.

```json
{
    "Id": 20283,
    "LoginName": "test.account@test.com",
    "ManagerAuthAccountId": 1234,
    "Name": "Test Account",
    "Roles": [
        {
            "Functions": [
                {
                    "Id": 3,
                    "Name": "My Home"
                }
            ],
            "Id": 11064,
            "Name": "Myhome test"
        }
    ],
    "UserIdentifier": ""
}
```

***

### **List Accounts For Manager**

#### **Input Parameters**

<table><thead><tr><th width="359.45458984375">Name</th><th>Description</th></tr></thead><tbody><tr><td>managerId</td><td>The id of the manager's account</td></tr></tbody></table>

#### **Sample Code**

```javascript
var input = {
    managerId: managerId
};

try {
    var output = straatos.adapter.listAccountsForManager(input);
    console.log(JSON.stringify(output));
} catch (err) {
    console.log('error: ' + err);
}
```

#### **Sample Response**

Response body contains an array of objects with properties as detailed under Get Account.

```json
{
    "Id": 20283,
    "LoginName": "test.account@test.com",
    "ManagerAuthAccountId": 1234,
    "Name": "Test Account",
    "Roles": [
        {
            "Functions": [
                {
                    "Id": 3,
                    "Name": "My Home"
                }
            ],
            "Id": 11064,
            "Name": "Myhome test"
        }
    ],
    "UserIdentifier": ""
}
```

***

### **Face Detection**

This method detects whether image contains face, for example, processing of passports and identification cards. Also able to rotate image to an upright posture in relation to the image and crop the document if the background is white.

The FaceDetection module requires a jpg as an input image.

#### **Input Parameters**

<table><thead><tr><th width="358.5455322265625">Name</th><th>Description</th></tr></thead><tbody><tr><td>DocumentId</td><td>DocumentId is the unique identifier for a document. This is an optional parameter. (default: _documentId)</td></tr><tr><td>InputAdditionalDataKey</td><td>When set, an additionalData file is used as input; otherwise, OriginalUrl is used (or, if empty, the preview URL on page level)</td></tr><tr><td>CroppingMargin</td><td>Specifies the margin which is to be left for cropping</td></tr><tr><td>Threshold</td><td>Threshold value</td></tr><tr><td>EdgeRatio</td><td>Ratio of the edges</td></tr><tr><td>NoiseRatio</td><td>Noise Ratio</td></tr></tbody></table>

#### **Sample Code**

```javascript
var docID = _documentId;

var documentInfoInput = {
    DocumentId: docID,
    InputAdditionalDataKey: "attachment:image/jpeg:image.jpg",
    CroppingMargin: 5,
    Threshold: 90,
    EdgeRatio: 1,
    NoiseRatio: 15
};

try {
    var output = JSON.parse(
        JSON.parse(straatos.adapter.orientationFinder(documentInfoInput))
    );
    console.log(JSON.stringify(output));
} catch (err) {
    console.log('error: ' + err);
}
```

#### **Sample Response**

The result is a processed image (turned upright and cropped) as well as JSON containing whether face was found, document was detected, coordinates where document was detected, coordinates where face was detected as well as score of the face:

```json
{
	""URL"": ""https://effektif-connector-cpro-	ch.cumuluspro.net/ConnectorService.svc/json/Storage/ae1666df-d7b8-47d5-	b1b4-f1d4143a088d.jpg"",
	""DocBottomLeftX"": 10.062535285949707,
	""DocBottomLeftY"": 1416.6976318359375,
	""DocBottomRightX"": 2282.43701171875,
	""DocBottomRightY"": 1416.6976318359375,
	""DocDetected"": true,
	""DocTopLeftX"": 10.062535285949707,
	""DocTopLeftY"": -19.61455535888672,
	""DocTopRightX"": 2282.43701171875,
	""DocTopRightY"": -19.614511489868164,
	""FaceBottomLeftX"": 260.82867431640625,
	""FaceBottomLeftY"": 1112.6834716796875,
	""FaceBottomRightX"": 644.717529296875,
	""FaceBottomRightY"": 1112.6834716796875,
	""FaceFound"": true,
	""FaceScore"": 0.6723385453224182,
	""FaceTopLeftX"": 260.82867431640625,
	""FaceTopLeftY"": 728.0123291015625,
	""FaceTopRightX"": 644.717529296875,
	""FaceTopRightY"": 728.0123291015625
}

```

***

### **Split Document**

Split a document into two documents. Original documents will contain first pages, newly created second document will contain all documents have pageIndex >= specified PageIndex. After document is split, MessageWorkflow call to newly created document should be done to allow further processing of document by the Straatos engine.

#### **Input Parameters**

<table><thead><tr><th width="359.45458984375">Name</th><th>Description</th></tr></thead><tbody><tr><td>WorkflowInstanceId</td><td>The effective workflowInstanceId belonging to the documentId</td></tr><tr><td>PageIndex</td><td>0-based index on where to split the document. All pages >= PageIndex will be part of the new documentId</td></tr><tr><td>CopyFieldValues</td><td>When true, the new document will have variable values of the original document.</td></tr></tbody></table>

Upon success, a JSON with the following fields is returned:

<table><thead><tr><th width="358.54541015625">WorkflowInstanceId</th><th>The effective workflowInstanceId belongs to the new document.</th></tr></thead><tbody><tr><td>DocumentId</td><td>The DocumentId belonging to the newly created document.</td></tr></tbody></table>

#### **Sample Code**

```javascript
var docID = _documentId;

try {
    var splitInput = {
        WorkflowInstanceId: straatos.getWorkflowInstanceIdByDocumentId(docID),
        PageIndex: 1
    };

    var splitOutput = straatos.adapter.splitDocument(splitInput);
    console.log(JSON.stringify(splitOutput));

} catch (err) {
    console.log('error: ' + err);
}
```

#### **Sample Response**

```json
{
	"DocumentId": 946919,
	"WorkflowInstanceId": "59c21481b3ac1616f09fe22c"
}
```

***

### **Merge Documents**

#### **Input Parameters**

<table><thead><tr><th width="358.54541015625">Name</th><th>Description</th></tr></thead><tbody><tr><td>DocumentId1</td><td>The documentId of the first document</td></tr><tr><td>DocumentId2</td><td>The documentId of the second document</td></tr><tr><td>WorkflowInstanceId2</td><td>The WorkflowInstanceId was known by the straatos engine of the second documentId</td></tr></tbody></table>

#### **Sample Code**

```javascript
try {
    var mergeRequest = {
        DocumentId1: docID1,
        DocumentId2: docID2,
        WorkflowInstanceId2: WorkflowInstanceId2
    };

    var mergeResult = straatos.adapter.mergeDocuments(mergeRequest);
    console.log(JSON.stringify(mergeResult));

} catch (err) {
    console.log('error: ' + err);
}
```

#### **Result**

If successful, response body will contain “ok”, and “error” when not successful.

***

### **Delete Document Page**

<table><thead><tr><th width="357.6363525390625">Name</th><th>Description</th></tr></thead><tbody><tr><td>DocumentId</td><td>DocumentId is the unique identifier for a document. This is an optional parameter. (default: _documentId)</td></tr><tr><td>PageIndex</td><td>0-based index of the page to delete.</td></tr></tbody></table>

#### **Sample Code**

```javascript
try {
    var deleteInput = {
        PageIndex: 0
    };

    console.log(JSON.stringify(deleteInput));

    var deleteOutput = straatos.adapter.deleteDocumentPage(deleteInput);
    console.log(JSON.stringify(deleteOutput));

} catch (err) {
    console.log('error: ' + err);
}
```

#### **Result**

If successful, the response body contains an empty string (“”).

***

### **Html To Pdf**

#### **Input Parameters**

<table><thead><tr><th width="359.4544677734375">Name</th><th>Description</th></tr></thead><tbody><tr><td>DocumentId</td><td>The unique identifier of the document for which the PDF should be created.</td></tr><tr><td>PageSize</td><td>The PDF page size (for example A4).</td></tr><tr><td>OutputAdditionalDataKey</td><td>The Additional Data Key in which the document can be found. For example 'pdf-audit'.</td></tr><tr><td>PrependPDFUrl</td><td>You can specify either PrependPDFUrl or PrependPDFAdditionalData (key). This field must point to an existing PDF file. The PDF will be prepended with the new HTML-generated PDF. Intended for use in creating cover pages for pre-existing documents.</td></tr><tr><td>PrependPDFAdditionalData</td><td>You can specify either PrependPDFUrl or PrependPDFAdditionalData (key). This field must point to an existing PDF file. The PDF will be prepended with the new HTML-generated PDF. Intended for use in creating cover pages for pre-existing documents.</td></tr><tr><td>AppendPDFUrl</td><td>You can specify either AppendPDFUrl or AppendPDFAdditionalData (key). This field must point to an existing PDF file. The PDF will be appended to the new HTML-based PDF. Ideal for creating audit trails and exporting documents that are attached to an existing document.</td></tr><tr><td>AppendPDFAdditionalData</td><td>You can specify either AppendPDFUrl or AppendPDFAdditionalData (key). This field must point to an existing PDF file. The PDF will be appended to the new HTML-based PDF. Ideal for creating audit trails and exporting documents that are attached to an existing document.</td></tr><tr><td>AppendPDFAdditionalData</td><td>You can specify either AppendPDFUrl or AppendPDFAdditionalData (key). This field must point to an existing PDF file. The PDF will be appended to the new HTML-based PDF. Ideal for creating audit trails and exporting documents that are attached to an existing document.</td></tr><tr><td>Landscape</td><td>Boolean, If the value is not set or is false, the value is Portrait.</td></tr><tr><td>HTML</td><td>The HTML code of the file.</td></tr><tr><td>Margin</td><td>If empty, the default value is 36.</td></tr></tbody></table>

The Example code below fetches users who have participated in User Task (for example, Approval). It then generates HTML code that includes a table with the date, username, and process step information. Finally, HTMLtoPDF function produces PDF and adds extra Data to Task. The code returns the document’s URL.

Output PDF looks like this:

<figure><img src="/files/a67f6OiMviprRIp5e0bU" alt=""><figcaption></figcaption></figure>

#### **Sample Code**

```javascript
var accountsString = straatos.adapter.listAccountsForOrganization({});

var accountLookup = {};

if (accountsString.length > 0) {
    accountsString.forEach(function (account) {
        accountLookup[account.Id] = account.Name ? account.Name : account.LoginName;
    });
}

var lines = '';

var history = JSON.parse(straatos.history());

history.activityInstances.forEach(function (activityInstance) {
    if (activityInstance.activityName) {
        if (esc(accountLookup[activityInstance.triggerUserId]).length != 0) {
            lines +=
                '<tr>' +
                '<td>' + moment(activityInstance.end).lang('de').format('LLL') + '</td>' +
                '<td>' + esc(accountLookup[activityInstance.triggerUserId]) + '</td>' +
                '<td>' + activityInstance.activityName + '</td>' +
                '</tr>';
        }
    }
});

var htmlToPdf = {
    DocumentId: _documentId,
    PageSize: 'A4',
    OutputAdditionalDataKey: 'new-pdf-audit',
    PrependPDFAdditionalData: 'abbyy-pdf-searchable',
    HTML: html()
        .replace(/#tablelines#/, lines)
        .replace(/#DocumentID#/, _documentId)
};

var outputHTMLtoPDF = straatos.adapter.htmlToPDF(htmlToPdf);
console.log('outputPDF URL: ' + outputHTMLtoPDF);

function esc(value) {
    if (typeof value === 'undefined') return '';
    return value;
}

function hereDoc(f) {
    return f.toString()
        .replace(/^[^\/]+\/\*!?/, '')
        .replace(/\*\/[^\/]+$/, '');
}

function html() {
    return hereDoc(function () { /*!
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>HTML Table Layout with CSS Style - 3 Column</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
    <style type="text/css">

    html, body {
      height: 100%;
    }

    body {
      margin: 0;
      font-family: 'Lato', sans-serif;
      font-size: 1.2rem;
      font-size: 12px;
      line-height: 16px;
      margin: 30px;
    }

    svg {
      width: 20%;
      vertical-align: middle;
      position: absolute;
      top: 50%;
      -webkit-transform: translateY(-50%);
      transform: translateY(-50%);
      display: inline-block;
      float: left;
    }

    .table {
      margin: 30px;
    }

    table.layout {
      border: 1px #ddd solid;
      width: 100%;
    }

    tr {
      height: 20px;
      border: 1px #ddd solid;
    }

    tr:nth-child(even) {
      background-color: rgba(17,76,143,0.2);
    }

    td {
      padding: 2px 5px;
    }

    th.header {
      color: white;
      background: #114C8F;
      text-align: left;
      padding: 2px 5px;
    }

    </style>
    </head>
    <body>

    <header>
      <div style="position: relative; display: block; border-bottom: 2px #114C8F solid; height: 75px;">
        <svg xmlns="http://www.w3.org/2000/svg" version="1.1" x="0" y="0" width="808.6" height="127.3" viewBox="0 0 808.6 127.3" enable-background="new 0 0 808.611 127.312" xml:space="preserve"><path fill="#114C8F" d="M281.1 118.5c-3.1 1.5-10.6 3.4-20 3.4 -27.1 0-41.1-17-41.1-39.4 0-26.8 19.1-41.6 42.9-41.6 9.2 0 16.2 1.7 19.3 3.5l-3.7 14c-3.5-1.5-8.5-2.9-14.9-2.9 -14 0-24.9 8.5-24.9 26 0 15.7 9.3 25.6 25 25.6 5.5 0 11.3-1 14.9-2.6L281.1 118.5zM340.7 102.3c0 7.5 0.2 13.5 0.5 18.3h-15.4l-0.8-8h-0.3c-2.2 3.5-7.6 9.3-17.8 9.3 -11.6 0-20-7.2-20-24.8V63.7h17.7v30.6c0 8.3 2.7 13.3 9 13.3 4.9 0 7.8-3.4 8.9-6.2 0.5-1 0.7-2.3 0.7-3.8V63.7h17.7V102.3zM514.2 37.9h17.7v82.7h-17.7V37.9zM596.9 102.3c0 7.5 0.2 13.5 0.5 18.3h-15.4l-0.8-8h-0.3c-2.2 3.5-7.6 9.3-17.8 9.3 -11.6 0-20-7.2-20-24.8V63.7h17.7v30.6c0 8.3 2.7 13.3 9 13.3 4.9 0 7.8-3.4 8.9-6.2 0.5-1 0.7-2.3 0.7-3.8V63.7h17.7V102.3zM608.1 105.2c3.3 2 10 4.2 15.2 4.2 5.4 0 7.6-1.7 7.6-4.7 0-3-1.8-4.4-8.3-6.6C610.8 94.2 606.2 87.8 606.4 81c0-10.7 9.1-18.7 23.2-18.7 6.6 0 12.5 1.6 16 3.4l-3 12.2c-2.6-1.4-7.6-3.3-12.3-3.3 -4.3 0-6.8 1.7-6.8 4.5s2.2 4.2 9.2 6.6c10.8 3.7 15.3 9.3 15.4 17.6 0 10.7-8.3 18.5-24.6 18.5 -7.4 0-14.1-1.7-18.4-4.1L608.1 105.2zM657 43.2c5.2-0.9 12.3-1.6 21.9-1.6 10.5 0 18.1 2.2 23.1 6.4 4.7 3.8 7.7 10 7.7 17.4 0 7.5-2.3 13.5-6.6 17.7 -5.8 5.7-14.7 8.5-24.8 8.5 -2.7 0-5-0.1-7-0.6v29.7h-14.2V43.2zM671.2 79.6c1.9 0.6 4.1 0.7 7 0.7 10.7 0 17.2-5.4 17.2-14.4 0-8.7-6.1-13.3-16-13.3 -4 0-6.8 0.4-8.3 0.7V79.6zM717.2 82.2c0-7.7-0.1-13.3-0.5-18.3h12.3l0.6 10.7h0.3c2.8-7.9 9.4-12 15.6-12 1.4 0 2.2 0.1 3.4 0.4v13.4c-1.3-0.2-2.6-0.3-4.3-0.3 -6.7 0-11.5 4.3-12.8 10.8 -0.2 1.3-0.3 2.8-0.3 4.3v29.5h-14.3V82.2zM808.6 91.7c0 20.8-14.7 30.2-29.1 30.2 -16 0-28.4-10.9-28.4-29.2 0-18.6 12.2-30 29.3-30C797.3 62.6 808.6 74.5 808.6 91.7zM765.9 92.3c0 10.9 5.5 19.2 14.1 19.2 8.2 0 13.9-7.9 13.9-19.4 0-8.8-4-19.1-13.7-19.1C770 73 765.9 82.9 765.9 92.3z"></path><path fill="#114C8F" d="M163.5 127.3H49.8C22.3 127.3 0 105 0 77.5c0-22.8 15.7-42.6 37.3-48.2C46.9 11.3 65.6 0 86.3 0c21.1 0 40.3 12.1 49.7 30.6 15.8 3.5 28.9 14.8 34.6 29.8 15.2 3.3 26.7 16.9 26.7 33.1C197.4 112.1 182.2 127.3 163.5 127.3zM87.5 19.5c-14.2 0-27 8.5-32.4 21.7l-2.3 5.5 -5.9 0.8c-14.3 2-25.1 14.4-25.1 28.9 0 16.1 13.1 29.2 29.2 29.2h113.7c7.3 0 13.2-5.9 13.2-13.2 0-7.2-5.8-13.1-13-13.2 -0.2 0-0.4 0-0.6 0l-8.7 0.3 -1.7-8.5c-2.4-11.8-12.5-20.8-24.6-21.8l-6.6-0.5 -2.3-6.2C115.3 28.7 102.1 19.5 87.5 19.5z"></path></svg>
        <h1 style="position:absolute;width:75%;padding:10px;color:#555;margin-left: 25%;padding: 10px;border-left:2px #555 solid;bottom:0;">Audit Trail</h1>
      </div>
    </header>
    <article class="table">
      <h3>Invoice Approval</h3>
      <table class="layout">
        <tr>
          <th class="header datum">Date and Time</th>
          <th class="header benutzer">User</th>
          <th class="header prozess">Processstep</th>
        </tr>
        #tablelines#
        <!--
        <tr>
          <td>16. Mai 2017 19:49</td>
          <td>Stephan Wolf</td>
          <td>Visierung Stephan Wolf</td>
        </tr>
        -->
      </table>
    </article>
    </body>
    </html>
    */});
}
```

#### **Result**

PDF is attached as additional Data and URL to PDF.

***

### **Set Document Restriction**

#### **Input Parameters**

<table><thead><tr><th width="356.727294921875">Name</th><th>Description</th></tr></thead><tbody><tr><td>Url</td><td>The URL to the document to grant access to.</td></tr><tr><td>MinutesFromNow</td><td>The duration of access to the document in minutes. The number of minutes that have passed since the script was run (not from the creation of the task).</td></tr><tr><td>AccessCount</td><td>You can specify either PrependPDFUrl or PrependPDFAdditionalData (key). This field must point to an existing PDF file. The PDF file will be prepended with the new HTML-based PDF. Intended for use in creating cover pages for pre-existing documents.</td></tr></tbody></table>

#### **Sample Code**

The following code shows how to test access toa document. In the first part, the URL for additionalData file 'test-xml' is retrieved. Then, script tries to access documents without granting access, resulting in 'Fail. Script then allows access to document once and then tests access again, indicating that access is now granted.

```javascript
var documentInfo = straatos.adapter.getDocumentInfo();

var additionalDataUrl = documentInfo.additionalData
    .filter(function (additionalData) {
        return additionalData.key == 'test-xml';
    })[0].url;

// Assuming workflow-level "Documents Public Accessible" is set to Never
// Test if the file is accessible without webservice key or valid session ID.
straatos.ajax({
    url: additionalDataUrl
}).done(function (data) {
    // The access was successful, hence the test failed as we expected not to have access to the document.
    console.log('DocRestriction Failed: should not be accessible');
    DocumentRestrictions = 'False';
}).fail(function (response, error) {
    // The access was unsuccessful, which we expected, so the test was successful.
    console.log('DocRestriction Succeeded: could not access');
    if (DocumentRestrictions != 'False') DocumentRestrictions = 'OK';
});

// Set a one-time access to the document
straatos.adapter.setDocumentRestrictions({
    URL: additionalDataUrl,
    AccessCount: 1
});

// Test if the document can be accessed
straatos.ajax({
    url: additionalDataUrl
}).done(function (data) {
    console.log('Succeeded: could access once');
    if (DocumentRestrictions != 'False') DocumentRestrictions = 'OK';
}).fail(function (response, error) {
    console.log('Failed: should be accessible once');
    DocumentRestrictions = 'False';
});

```

***

### **Zip**

#### **Input Parameters**

<table><thead><tr><th width="357.6363525390625">Name</th><th>Description</th></tr></thead><tbody><tr><td>AdditionalDataKey</td><td>The additionalData is placed under this key (not the URL)</td></tr><tr><td>Files</td><td><p>A File array. Each object in the array should be a JSON object containing 2 (out of possible 3) keys:</p><p></p><ul><li>Filename - The name of the file that should be included in the zip.</li></ul><p></p><ul><li>SourceURL - The URL to the document to be added.</li></ul><p></p><ul><li>UTF8Content.</li></ul></td></tr><tr><td>DocumentId</td><td>Optional, if not specified the current document will be used.</td></tr><tr><td>TimeOutMs</td><td>Optional timeout in Milliseconds, If no timeout value is specified, the default value of 90 seconds is used.</td></tr></tbody></table>

#### **Sample Code**

The following code adds file from additional Data to ZIP file named 'zip'

```javascript
var returnURL = straatos.adapter.zip(zipParameters);
```

```javascript
var zipParameters = {
    AdditionalDataKey:'zip',
    Files:[
        {SourceUrl: additionalDataUrl, FileName:'123.xml'}
    ]
};
```

***

### **Unzip**

#### **Input Parameters**

<table><thead><tr><th width="359.4544677734375">Name</th><th>Description</th></tr></thead><tbody><tr><td>AdditionalDataPrefix</td><td>Prefix for each additional data entry created from the zip file</td></tr><tr><td>AdditionalDataKey</td><td>The Key of the additionalData where the ZIP file is stored</td></tr><tr><td>DocumentId</td><td>Optional, if not specified the current document will be used.</td></tr><tr><td>IgnoreDirectoryInfo</td><td>Ignore the directory information in the ZIP file as an option. If it is true, all entries in the additional data key will be extracted without path information. The default value is false.</td></tr><tr><td>IncludeHiddenFiles</td><td>Optional option to include files that have a name string with '.'. The default value is false.</td></tr><tr><td>TimeoutMs</td><td>Optional timeout in Milliseconds, if no timeout value is specified, the default value of 90 seconds is used.</td></tr></tbody></table>

#### **Sample Code**

The following code extracts data from zip file and adds data as additional data with prefix 'Unzip-'.

```javascript
straatos.adapter.unzip({AdditionalDataPrefix:'Unzip-',AdditionalDataKey:'zip'});
```

***

### **Pdf To Image**

#### **Input Parameters**

<table><thead><tr><th width="357.6363525390625">Name</th><th>Description</th></tr></thead><tbody><tr><td>EndpageNumber</td><td>End (1 based) page number. The default value is 0, which includes all pages. This is an optional parameter.</td></tr><tr><td>JPGQuality</td><td>An optional value between 0-100. Default is 40.</td></tr><tr><td>DocumentId</td><td>If not specified, the current document will be used. This is an optional parameter.</td></tr><tr><td>OutputAdditionalDataKeyPrefix</td><td>Optional prefix for the generated additional data keys (default is 'page' and will be suffixed by e.g. '-0001.jpg')</td></tr><tr><td>OutputTiff</td><td>If true, a multipage TIFF file will be generated, default is false (JPG).</td></tr><tr><td>PDFURL</td><td>URL pointing to the PDF file.</td></tr><tr><td>ResolutionDPI</td><td>Optional value in DPI, default is 150.</td></tr><tr><td>StartPageNumber</td><td>Optional, start (1 based) page number. The default value is 0, which includes all pages.</td></tr><tr><td>TimeoutMs</td><td>Optional timeout in Milliseconds, if no timeout value is specified, the default value of 90 seconds is used.</td></tr><tr><td>UserPassword</td><td>Optional, password to access password-protected PDF files.</td></tr></tbody></table>

#### **Sample Code**

The following code creates TIF file from PDF in 300dpi:

```javascript
straatos.adapter.pdfToImage(
    {
    JPGQuality:'90', 
    OutputAdditionalDataKeyPrefix:'testTIF', 
    PDFURL:OriginalUrl, 
    ResolutionDPI:'300',
    OutputTiff:'true'
    }
);
```

***

### **Create Merge PDF**

#### **Input Parameters**

<table><thead><tr><th width="358.54541015625">Name</th><th>Description</th></tr></thead><tbody><tr><td>CompressionLevel</td><td><p>Optional, compression level, default is 'normal'. Available options are:</p><p></p><ul><li>AboveNormal.</li><li>BelowNormal.</li><li>Best.</li><li>BestSpeed.</li><li>NoCompression.</li><li>Normal.</li></ul></td></tr><tr><td>Orientation</td><td><p>Optional page orientation. Available options are:</p><ul><li>Portrait.</li><li>Landscape.</li></ul></td></tr><tr><td>DocumentId</td><td>Optional, if not specified the current document will be used.</td></tr><tr><td>OutputAdditionalDataKey</td><td>Optional additional data key, default is 'merge.pdf'.</td></tr><tr><td>PageSize</td><td><p>Optional page size. Available options are:</p><ul><li>Letter.</li><li>Note.</li><li>Legal.</li><li>A0.</li><li>A10.</li><li>B0.</li><li>B5.</li><li>ArchA.</li><li>ArchE.</li><li>Fisa.</li><li>HalfLetter.</li><li>Letter11x7.</li><li>Ledger.</li></ul></td></tr><tr><td>Files</td><td>An array of file descriptions, one entry for each PDF file or image to append. Each entry is formatted as follows: {RL:'https://...', StartIndex: 0, Length: 99, Password: '...'}. Only the URL is required and point to a PDF or image file.</td></tr><tr><td>TimeoutMs</td><td>Optional timeout in Milliseconds, if no timeout value is specified, the default value of 90 seconds is used.</td></tr><tr><td>Password</td><td>Optional, password to access password-protected PDF files.</td></tr></tbody></table>

#### **Sample Code**

The following code merges two PDF files.

```javascript
// Create a MergePDF from two PDFs
var documentInfo = straatos.adapter.getDocumentInfo();

var secondPDFUrl = documentInfo.additionalData
    .filter(function (additionalData) {
        return additionalData.key == 'HtmlToPDF2';
    })[0].url;

straatos.adapter.createMergePDF({
    OutputAdditionalDataKey: 'createMergePDF.pdf',
    Files: [
        { URL: outputHTMLtoPDF },
        { URL: secondPDFUrl }
    ]
});

```

***

### **Create Searchable Pdf**

#### **Input Variables**

```json
{  
    DocumentId:'9223372036854775807',
    OutputAdditionalDataKey:'yourDataKey',
    InputImageFile: 'd75b5fad-cdb0-471c-8532-6a97d92727a3.pdf',
    InputJsonFile: '757db782-aaa3-4cef-884a-bd9c7e0d200b.json'
}
```

#### **Sample Code**

You can get InputImageFile and InputJsonFile from a call to GetDocumentInfo, or you can store the value that is returned when you add additional data with call to AddAdditionalData().

```javascript
var documentInfo = straatos.adapter.getDocumentInfo();

var thePdfUrl = documentInfo.additionalData
    .filter(function (additionalData) {
        return additionalData.key == 'HtmlToPDF';
    })[0].url;

var jsonFile = documentInfo.additionalData
    .filter(function (additionalData) {
        return additionalData.key == 'HtmlToPDF';
    })[0].url;

var pfdFileName = straatos.adapter.createSearchablePdf({
    "DocumentId": 1234,
    "OutputAdditionalDataKey": "MyPDF",
    "InputImageFile": thePdfUrl,
    "InputJsonFile": jsonFile
});
```

***

### **Set Error**

Straatos.setError is used to set an error to a task when a task has an error.

#### **Sample Code**

```javascript
straatos.setError("Error Successfully Set");
```

***

### **Create Account**

#### **Input Parameters**

<table><thead><tr><th width="356.727294921875">Name</th><th>Description</th></tr></thead><tbody><tr><td>LoginName</td><td>Login credentials.</td></tr><tr><td>Email Address</td><td>Login email address.</td></tr><tr><td>Name</td><td>Name of the person/account.</td></tr><tr><td>UserIdentifier</td><td>Similar to Login Name.</td></tr><tr><td>Password</td><td>Optional, password to create new user.</td></tr><tr><td>Roles</td><td>Defining the roles to be added to the account.</td></tr></tbody></table>

#### **Sample Code**

The following code creates a new user.

```javascript
var newAccount = {
    LoginName: 'test@cumuluspro.com',
    EmailAddress: "",
    Name: 'Test Account',
    UserIdentifier: 'test@cumuluspro.com',
    Password: "<password>",
    Roles: []
};

console.log(JSON.stringify(newAccount));

try {
    straatos.adapter.createAccount(newAccount);
} catch (err) {
    straatos.setError(err);
}
```

***

### **Get Account**

#### **Input Parameters**

<table><thead><tr><th width="357.6363525390625">Name</th><th>Description</th></tr></thead><tbody><tr><td>Id</td><td>Account ID is associated with account for which information is required.</td></tr></tbody></table>

#### **Sample Code**

The following code fetches user account information.

```javascript
var validInput = { Id: validAccountId };

try {
    var account = straatos.adapter.getAccount(invalidInput);
    console.log(JSON.stringify(account));
} catch (err) {
    straatos.setError(err);
}
```

#### **Sample Response**

Below is output from Get Account.

```json
{
    "WebServiceKey": null,
    "EffektifWorkflowId": null,
    "Id": 4001,
    "ManagerAuthAccountId": null,
    "LoginName": "test@cumuluspro.com",
    "EmailAddress": "",
    "Name": "Test Account",
    "UserIdentifier": null,
    "Password": null,
    "Roles": []
}
```

***

### **Update Account**

#### **Input Parameters**

<table><thead><tr><th width="355.8182373046875">Name</th><th>Description</th></tr></thead><tbody><tr><td>LoginName</td><td>Login credentials.</td></tr><tr><td>Email Address</td><td>Login email address.</td></tr><tr><td>Name</td><td>Name of the person/account.</td></tr><tr><td>UserIdentifier</td><td>Similar to Login Name.</td></tr><tr><td>Password</td><td>Optional, password to update user.</td></tr><tr><td>Roles</td><td>Defining the access to the roles for the account.</td></tr></tbody></table>

#### **Sample Code**

The following code updates user account information.

```javascript
try {
    var accounts = straatos.adapter.updateAccount(newAccount);
    console.log('newAccount: ' + JSON.stringify(accounts));
} catch (err) {
    straatos.setError(err);
}
```

#### **Sample Response**

Below is output from updateAccount.

```json
{
    "WebServiceKey": "<webserviceKey>",
    "EffektifWorkflowId": "<workflowid>",
    "Id": 4001,
    "ManagerAuthAccountId": null,
    "LoginName": "test@cumuluspro.com",
    "EmailAddress": "",
    "Name": "Test Account Updated",
    "UserIdentifier": "test@cumuluspro.com",
    "Password": null,
    "Roles": []
}
```

***

### **Delete Account**

#### **Input Parameters**

<table><thead><tr><th width="359.4544677734375">Name</th><th>Description</th></tr></thead><tbody><tr><td>ID</td><td>ID of account that needs to be deleted.</td></tr></tbody></table>

#### **Sample Code**

The following code deletes the user's account.

```javascript
var input = { Id: newAccountId };

try {
    straatos.adapter.deleteAccount(input);
} catch (err) {
    straatos.setError(err);
}
```

***

### **Start Workflow**

#### **Input Parameters**

<table><thead><tr><th width="358.54541015625">Name</th><th>Description</th></tr></thead><tbody><tr><td>workflowid</td><td>Workflow ID of workflow where new task should be started. If it is the same workflow, can be passed with straatos.workflowId.</td></tr><tr><td>startActivityId</td><td>Start activity ID of start event which should start the workflow.</td></tr><tr><td>Data</td><td>indexfielddata to be passed.</td></tr><tr><td>workflowconfiguration</td><td>Numeric (short) workflow ID which is also visible in Admin Panel. Alternative to specify workflowid.</td></tr><tr><td>webservice Key</td><td>(Optional, not needed to start a workflow in your own organisation). If you want to start a workflow in another organisation, enter that workflows webServiceKey here.</td></tr><tr><td>filetype</td><td>If original document is provided, provide filetype (pdf, tif, jpg).</td></tr><tr><td>documenturls</td><td>URL(s) to documents that need to be added as original document.</td></tr></tbody></table>

#### **Sample Code for Interact API**

```javascript
var conf = {
    "workflowid": "59d39db00eb0834790670e8d",
    "data": {
        "AutoTest": "Jeroen",
        "SomethingElse": "No"
    },
    "documentUrls": [
        "https://yourdomain/s3fs-public/thumbnails/image/2018/12/11/17/gettyimages-1048042404.jpg"
    ],
    "startActivityId": "6851",
    "additionalDatas": [
        {
            "key": "jb",
            "index": 0,
            "url": "https://yourdomain/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"
        }
    ],
    "filetype": "jpg",
    "webServiceKey": "199aa86e-c6f4-4901-b169-740dacd38dba"
};

straatos.adapter.startWorkflow(conf);
```

#### **Sample Code for Script Task**

```javascript
var conf = {
    "workflowConfiguration": "1234",
    "data": {
        "AutoTest": "Jeroen",
        "SomethingElse": "No"
    },
    "documentUrls": [
        "https://yourdomain/s3fs-public/thumbnails/image/2018/12/11/17/gettyimages-1048042404.jpg"
    ],
    "startActivityId": "6851",
    "additionalDatas": [
        {
            "key": "jb",
            "index": 0,
            "url": "https://yourdomain/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"
        }
    ],
    "filetype": "jpg",
    "webServiceKey": "199aa86e-c6f4-4901-b169-740dacd38dba"
};

straatos.startWorkflow(conf);

```

***

### **Get File As String / Get File As Base64 / Get File As ByteArray**

#### **Input Parameters**

<table><thead><tr><th width="357.6363525390625">Name</th><th>Description</th></tr></thead><tbody><tr><td>DocumentId</td><td>Straatos documentId of task from where to get file content. Required from interact API or when it is from different task.</td></tr><tr><td>FileUrl</td><td>URL to document to retrieve content from.</td></tr><tr><td>WebServiceKey</td><td>Only required if file is retrieve from workflow outside current workflow or if called from interact API.</td></tr></tbody></table>

#### **Sample Code**

```javascript
var url = '7756d1cc-f0b7-456c-b862-fb62a62bf3fc.tif';

var base64 = straatos.adapter.getFileAsBase64({
    FileUrl: url,
    DocumentId: 6141667
});
```

***

### **List Roles for Organisation**

#### **Input Parameters**

<table><thead><tr><th width="356.7271728515625">Name</th><th>Description</th></tr></thead><tbody><tr><td>credentials</td><td>Login credentials</td></tr><tr><td>ID</td><td>ID of account holder</td></tr><tr><td>Functions</td><td>Function/role of account holder.</td></tr></tbody></table>

#### **Sample Code**

The following code fetches a list of roles available in organisation.

```javascript
try {
    var output = straatos.adapter.listRolesForOrganization();
} catch (err) {
    straatos.setError(err);
}
```

#### **Sample Response**

Following code output from ListRolesFromOrganisation.

```json
[
    {
        "Id": <ID>,
        "Name": "Admin",
        "Functions": 
        [{
            "Id": <ID>,
            "Name": "AdminPanel"
        }]
    },
    {
        "Id": <ID>,
        "Name": "Myhome test",
        "Functions":
        [{
            "Id": <ID>,
            "Name": "My Home"
        }]
    },
    {
        "Id": <ID>,
        "Name": "scan",
        "Functions":
        [
            {
                "Id": <ID>,
                "Name": "My Home"
            },
            {
                "Id": <ID>,
                "Name": "Scan+"
            }
        ]
    }
]
```


# Straatos Script Service API

This articles describes Straatos Scrip Service API

Straatos engine provides JavaScript activity. This document describes available calls for developers writing JavaScript activities.

### Available Variables

Constants are declared and initialised by Straatos. They cannot be changed, just queried.

{% hint style="info" %}
Constants are case sensitive.
{% endhint %}

<table><thead><tr><th width="324.90911865234375">Name</th><th>Description</th></tr></thead><tbody><tr><td>workflowId</td><td>ID of workflow this workflowInstance is in. WorkflowId changes every time workflow is (re-)published.</td></tr><tr><td>workflowName</td><td>Name of workflow</td></tr><tr><td>workflowInstanceId</td><td>Unique ID of every workflowInstance. This will not change as long as the instance is in the workflow.</td></tr><tr><td>activityId</td><td>Uniquely identifies activity within current workflow.</td></tr><tr><td>activityName</td><td>Name of Script activity</td></tr><tr><td>activityInstanceId</td><td>Increasing sequence number representing logId of activity</td></tr><tr><td>activityInstanceDate</td><td>Date that activity execution started</td></tr><tr><td>workflowInstanceDate</td><td>Date the workflowInstance arrived in the workflow</td></tr><tr><td>console</td><td>Object with method log(String). Output will appear in efektif log.</td></tr></tbody></table>

***

### Utility Methods

JavaScript activity provides “Straatos”-object containing several methods providing functionality. The following are description of these methods:

#### Generate a UUID

Generate a UUID (or GUID), please use:

```javascript
var guid = straatos.uuid();
```

***

### Sequence Number

The method nextSequenceNumber() generates sequence number that is unique for the workflow.

Identifier makes it possible to have several sequences in one process:

<table><thead><tr><th width="324.90911865234375">Name</th><th>Description</th></tr></thead><tbody><tr><td>nextSequenceNumber()</td><td>Retrieves the next sequence number for the specified identifier</td></tr><tr><td>clearSequenceNumber()</td><td>Clears the sequence (ie it will start at 1 again)</td></tr></tbody></table>

#### Sample Code

```javascript
var id = straatos.nextSequenceNumber('sequence1');

straatos.clearSequenceNumber('sequence1'); // clears the sequence
```

***

### Getting Variables from Other WorkflowInstances in the Same Flow

Straatos provides two ways to get variables from other workflowInstances in the same workflow.

<table><thead><tr><th width="324.908935546875">Name</th><th>Description</th></tr></thead><tbody><tr><td>variablesByWorkflowInstanceId('')</td><td>Gets variables of workflowInstance defined by</td></tr><tr><td>variablesByDocumentId()</td><td>Gets variables of workflowInstance defined by (every workflowInstance also has unique documentId attached)</td></tr></tbody></table>

#### Sample Code

```javascript
var DocumentId = 12345;

var frontVariables =
    JSON.parse(straatos.variabesByDocumentId(DocumentId));

function value(name) {
    var values = frontVariables.filter(function (entry) {
        return entry.variableId == name;
    });

    return values.length > 0 ? values[0].value : null;
}

var FirstName = value('FirstNameF');
var LastName = value('LastNameF');
```

***

### Getting activityIds, documentId and workflowInstanceId

The ActivityId is used in multiple API methods, such as the message() method, to identify a specific activity within a workflow.

#### Getting ActivityId by Name

The method activityIdForName(activityName) allows you to retrieve the ActivityId when you provide an ActivityName.

Key Points:

* ActivityId is a unique identifier for an activity in a workflow.
* ActivityName is the user-defined name/description of an activity.
* The activityIdForName(activityName) method helps map the activity name to its corresponding ID.

<table><thead><tr><th width="324">Name</th><th>Description</th></tr></thead><tbody><tr><td>activityIdForName()</td><td>Returns activityId for the given activityName (only works for the current workflow, ie workflow the workflowInstance is in)</td></tr><tr><td>getActivityIdsByDocumentId()</td><td>Returns <strong>list of activityIds</strong> where workflowInstance defined by DocumentId is in (there is a 1:1 relation between documentId and workflowInstanceId).</td></tr><tr><td>getWorkflowInstanceIdByDocumentId()</td><td>Get workflowInstanceId (a string) for specified documentId</td></tr><tr><td>documentIdsForFilter()</td><td>Perform search on all documents on given variables</td></tr></tbody></table>

#### Sample Code

```javascript
var emailGroupId;

var documentIds = straatos.documentIdsForFilter({
    EmailUniqueId: emailGroupId
});

var activityId = straatos.activityIdForName('Wait for last Document');

var workflowInstances = [];

for (var i = 0; i < documentIds.length; i++) {
    var documentId = documentIds[i];
    if (documentId != _documentId) {
        workflowInstances.push({
            workflowInstanceId: straatos.getWorkflowInstanceIdByDocumentId(documentId)
        });
    }
}

var workflowMessageData = {
    workflowId: workflowId,
    activityId: activityId,
    workflowInstances: workflowInstances
};

console.log('workflowMessageData input: ' + JSON.stringify(workflowMessageData));

straatos.sendWorkflowMessage(workflowMessageData).fail (function (jqXHR, error) {
    straatos.SetError('Send Workflow Message: ' + error);
});
```

***

### Getting Variable Values

It is possible to get variables from other workflowInstances in the same workflow using these methods:

<table><thead><tr><th width="329.4544677734375">Name</th><th>Description</th></tr></thead><tbody><tr><td>variablesByDocumentId()</td><td>Gets JSON string containing all variables by documentId</td></tr><tr><td>variablesByWorkflowInstanceId()</td><td>Gets JSON string containing all variables by workflowInstanceId</td></tr></tbody></table>

***

### Converting to-and-from Byte Arrays

Several convenience methods are provided to convert to and from byte arrays.

<table><thead><tr><th width="329.4544677734375">Name</th><th>Description</th></tr></thead><tbody><tr><td>getBytes(inputString)</td><td>Converts inputString to byte array, using UTF-8 encoding.</td></tr><tr><td>getString(byte[])</td><td>Converts byte array to a string, using utf-8 character set.</td></tr><tr><td>getString(&#x3C;byte[]>, )</td><td>Convert byte array to a string, using specified character set.</td></tr></tbody></table>

***

### Base64 Encoding and Decoding

<table><thead><tr><th width="328.54541015625">Name</th><th>Description</th></tr></thead><tbody><tr><td>decodeBase64()</td><td>Returns (possibly binary) byteArray of base64 encoded string.</td></tr><tr><td>encodeBase64()</td><td>Returns base64 encoded string representation of (binary-) byteArray.</td></tr></tbody></table>

#### Sample Code

```javascript
try {
    var dataAcceptingSystemUrl = "https://<someDataAcceptingSystems URL>/documentimportsrv";

    // variables need to be defined before call to multiString
    ReferenceNumber103 = straatos.getWorkflowData('some.ref.number.' + EmailUniqueId);

    var base64String;
    var documentBase = AttachmentFileName.replace('.pdf','');
    var documentInfo = straatos.adapter.getDocumentInfo();

    straatos.ajax({
        url: documentInfo.originalURL + '?w=' + straatos.webServiceKey,
        dataType: 'binary'
    }).done(function (pdf) {
        base64String = straatos.encodeBase64(pdf);

        var documentData = multiString(function() {/** 
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:doc="http://nsServer.net/documentimportsrv">
<soapenv:Header/>
<soapenv:Body>
<doc:ImportDoc>
<doc:documentImportReq>
<doc:Docs>
<doc:Doc>
<doc:Content>#base64String#</doc:Content>
<doc:FileExt>pdf</doc:FileExt>
<doc:Filename>#AttachmentFileName#</doc:Filename>
<doc:FilenameBase>#documentBase#</doc:FilenameBase>
</doc:Doc>
</doc:Docs>
<doc:IdentifierNr>#ReferenceNumber103#</doc:IdentifierNr>
<doc:Type>DOCTYPE</doc:Type>
</doc:documentImportReq>
</doc:ImportDoc>
</soapenv:Body>
</soapenv:Envelope>
        **/});

        straatos.ajax({
            url: dataAcceptingSystemUrl,
            data: documentData,
            method: 'POST',
            contentType: 'text/xml; charset=UTF-8',
            dataType: 'text/xml',
            headers: {
                SOAPAction: 'dataAcceptingSystemUrl + /IDocumentImportSrv/ImportDoc"'
            }
        }).done(function (responseString) {
            console.log('Document Import Response: ' + responseString);
            if (responseString != '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><ImportDocumentResponse xmlns="http://nsServer.net/documentimportsrv"/></s:Body></s:Envelope>') {
                straatos.SetError('Response from document import service: ' + responseString);
            }
        }).fail(function (jqXHR, error) {
            straatos.SetError('document import service: ' + error);
            console.log('Document Import Service: ' + error);
        });

    }).fail(function (jqXHR, error) {
        straatos.SetError('Get original: ' + error);
    });

} catch(err) {
    straatos.SetError('error: ' + error);
    console.log('error: ' + err);
}

// Hack that converts multi line comment to multi line string
function multiString(f) {
    var result = f.toString().replace('function() {/**', '').replace('**/}', '');
    result = result.replace(/#([^#]+)#/g, function (match, variable) {
        // console.log('replacing ' + match + ', variable: ' + variable + ', value: ' + eval(variable));
        return eval(variable);
    });
    return result;
}
```

***

### Workflow Data

Functionality is provided to store and retrieve data on workflow level. This data remains available when the workflow is re-published.

<table><thead><tr><th width="328.54541015625">Name</th><th>Description</th></tr></thead><tbody><tr><td>setWorkflowData(, )</td><td>Sets workflow data.</td></tr><tr><td>getWorkflowData()</td><td>Gets workflow data for specified key</td></tr><tr><td>removeWorkflowData()</td><td>Removes workflow data for specified key</td></tr><tr><td>clearAllWorkflowData()</td><td>Removes all workflow data for current workflow</td></tr></tbody></table>

Example:

```javascript
straatos.getWorkflowData('reference-' + EmailUniqueId);
```

***

### Messaging Other WorkflowInstances

Send other (waiting) workflowInstances a message that they can continue the workflow.

<table><thead><tr><th width="328.54541015625">Name</th><th>Description</th></tr></thead><tbody><tr><td>sendWorkflowMessage({})</td><td>Sends a message to workflowInstance. Message should contain workflowId, activityId and an array of workflowInstances to message. Optionally variables per workflowInstance. See example below.</td></tr></tbody></table>

Parameters:

* workflowId:
  * ID (a guid) of current workflow.
* activityId:
  * ID (a string) of activity. See activityForName() method to get activityId via activityName.
* workflowInstances:
  * List of one or more workflowInstances that should receive the message.

Each workflowInstance should contain workflowInstanceId and optionally list named variables of id-value pairs.

#### Sample Code

```javascript
var workflowInstanceId = '';

var messageInput = {
    workflowId: workflowId,
    activityId: activityId,
    workflowInstances: [{
        workflowInstanceId: workflowInstanceId,
        variables: [
            {'id' : 'Variable1', 'value' : 'string123'},
            {'id' : 'Var2', 'value' : 123 }
        ]
    }]
};

straatos.sendWorkflowMessage(messageInput)
.done(function () {
    console.log('Ok');
}).fail(function (jqXHR, error) {
    straatos.SetError('Message error: ' + error);
});
```

***

### Calling Web Services (Ajax Support)

Straatos provides an api to call web services. The way it can be used is similar to a jQuery Ajax call, however, it supports a subset of the functionality.

This Ajax call can also be used to call additional functionality the Straatos REST API provides. For more information, please open the link below.

<https://docs.google.com/document/d/1ui5UhztqodEmLn6rY36AQ00rUsiLKfwNNvXdzLw6CJ0/edit?ts=5829c792#bookmark=id.fccwvtqnhhu3>

<table><thead><tr><th width="326.727294921875">Name</th><th>Description</th></tr></thead><tbody><tr><td>ajax()</td><td>Performs the call. See table below for the request options</td></tr></tbody></table>

Request specification:

<table><thead><tr><th width="327.63623046875">Name</th><th>Description</th></tr></thead><tbody><tr><td>url</td><td>Required: Complete url to call. Calls to urls containing localhost are not allowed.</td></tr><tr><td>data</td><td>Data you want to pass, or the multipart object from straatos.newFormData call</td></tr><tr><td>method</td><td>Possible values are GET, POST, PUT, DELETE and OPTIONS. When not specified, it defaults to GET</td></tr><tr><td>contentType</td><td>Optional contentType of data to be sent, default is 'application/json'</td></tr><tr><td>dataType</td><td>Optional contentType of expected data for example: 'binary' or 'text/html'</td></tr><tr><td>headers</td><td>Optional array with headers that will be passed to the call</td></tr><tr><td>timeout</td><td>Optional timeout in milliseconds. The default is 60 seconds. This one parameter specifies connectTimout, requestTimeout and socketTimeout.</td></tr></tbody></table>

#### Sample Code

```javascript
try {
    straatos.ajax({
        url: externalAPIURL,
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        data: JSON.stringify({'client_id': '', 'client_secret': ''})
    }).done(function (output) {
        var response = JSON.parse(output);
        console.log('++ response: ' + JSON.stringify(response));
        token = response.access_token;
    }).fail(function (jqXHR, error) {
        straatos.setError('Access Token Error: ' + error);
        console.log('Access Token Error: ' + error);
    });
} catch(err) {
    console.log('Get Access Token Error: ' + err);
}
```

***

### Multipart Support

Multipart support is available to create multipart messages. If boundaries are needed between parts, they should be added manually by the developer.

To get a new Multipart object, call straatos.newFormData().

#### Adding Data

To add data to multipart objects, call one of these methods:

<table><thead><tr><th width="327.6363525390625">Name</th><th>Description</th></tr></thead><tbody><tr><td>append()</td><td>Adds a string, this string will be utf-8 encoded</td></tr><tr><td>append(, )</td><td>Adds a string with a custom character set. Values used can be ‘utf-8’, or any of the character sets from the table below.</td></tr><tr><td>append(&#x3C;byte []>)</td><td>Appends a byte array to multipart object</td></tr></tbody></table>

#### Getting Data

To get the data from the multipart object, call one of these methods:

<table><thead><tr><th width="327.6363525390625">Name</th><th>Description</th></tr></thead><tbody><tr><td>getByteArray()</td><td>Returns byte array (byte[]) representing multipart data</td></tr><tr><td>toString()</td><td>Returns utf-8 decoded string of multipart data</td></tr></tbody></table>

#### Sample Code

```javascript
var multipart = straatos.newFormData();

multipart.append('This is string 1');

var boundaryName = 'Straatos-' + straatos.uuid(); //The Boundary Name must be unique as part of the entire post. Hence in this case we use 'Straatos- and a unique ID' to make it unique.

var boundary = '--' + boundaryName + '\r\n';

var multipart = straatos.newFormData();

multipart.append(boundary);

multipart.append('Content-Type: ' + mimeType + '\r\n');

multipart.append('Content-Disposition: document; name="' + documentName + '"; filename="' + fileName + '"\r\n');

multipart.append('\r\n');

multipart.append(fileContents);

multipart.append('\r\n');

multipart.append(boundary);

multipart.append('Content-Type: application/json; charset=UTF-8\r\n');

multipart.append('Content-Disposition: meta\r\n');

multipart.append('\r\n');

multipart.append(JSON.stringify(metadata) + '\r\n');

multipart.append('--' + boundaryName + '--\r\n'); //The last Boundary must have the two dashes (--) at the end.

straatos.ajax({
    url: APIBaseURL + '/api/v1/delivery',
    method: 'POST',
    data: multipart,
    contentType: 'multipart/related; boundary="' + boundaryName + '"', //Note: The Boundary Name needs to be in double quotes and must be defined here.
    headers: {
        'Authorization': 'Bearer ' + tokenResult.access_token
    }
}).done(function (response) {
    console.log('Peax response: ' + response);
    PeaxUploadId = JSON.parse(response).id;
}).fail(function (jqXHR, error) {
    straatos.setError('Peax upload: ' + error);
});
```

***

### Getting History or Audit Trail Info

This API call returns JSON string containing history of the document. This will not include the currently executed step.

* straatos.history() returns json string containing history of the current workflowInstance (not including current running activity).
* straatos.history(number documentId) returns json string containing history of workflowInstance identified by documentId provided. This document must be part of the same workflow as the calling document.

Since a string is returned, JSON.parse() should be called on the string before accessing json objects within the returned data.

#### Sample Code

```javascript
// Example:
var hist_str = straatos.history();
var hist = JSON.parse(hist_str);
console.log(JSON.stringify(hist)); // prints the whole history object
console.log('WorkflowInstance started at: ' + JSON.stringify(hist.start));
console.log('Nr of log entries: ' + hist.activityInstances.length);

// Example with documentId:
var hist_str2 = straatos.history(877603);
var hist2 = JSON.parse(hist_str2);
console.log(JSON.stringify(hist2)); // prints the whole history object
console.log(JSON.stringify(hist2.start));
console.log('Second: ' + hist2.activityInstances.length);
```

***

### setSecret and getSecret

The Set Secret and Get Secret functions provided by the Script task or Interact API enable the secure storage of sensitive data such as passwords, tokens, API keys, and connection strings.

How It Works:

* setSecret:&#x20;
  * This function securely stores the data in Straatos's vault.

* getSecret:&#x20;
  * This function retrieves the stored data from the vault for use within the workflow.

Best Practices:

* It is crucial not to store secrets directly in script code. Instead, utilize the setSecret and getSecret functions to manage sensitive data securely.

#### Storing a Secret

```javascript
var result = straatos.setSecret('mySecretName', 'mySecretValue');
```

The above code stores the return value in a variable. That variable will either contain a 'true' or 'false' value, depending on if the storing of the secret was successful. This result should be checked by the code.

#### Retrieving a Secret

```javascript
var secret = straatos.getSecret('mySecretName');
```

***

### Database (SQL) Queries

The straatos.data.query lets user connect to a database and execute SQL queries. This function can be used to read data from Database (Select), but also to update, truncate, drop databases (tables).

The sample code below shows how a database is updated.

```javascript
var sqlUpdate = 'DECLARE @UNI UNIQUEIDENTIFIER ' +
'SET @UNI = NEWID() ' +
'INSERT INTO BBAuditLog (id,AuditLogRecordId,UserName, EventDate, WorkflowStep, BatchId, Area, RecordName, RecordValue) ' +
'OUTPUT @@RowCount as RowsAffected ' +
'VALUES (NewID(),@AuditLogRecordId,@UserName,@EventDate,@WorkflowStep,@BatchId,@Area,@RecordName,@RecordValue);';

var sqlParam = {
    '@AuditLogRecordId': AuditLogRecordId,
    '@UserName': LastSavedBy,
    '@EventDate': moment(LastSavedDateTime).format('YYYY-MM-DDThh:mm:ssZ'),// LastSavedDateTime,
    '@WorkflowStep': ReportType,
    '@BatchId':BatchId,
    '@Area':'Header'
};

var dbConnString = 'Server=<ServerName>,1433;Database=<DBName>;Trusted_Connection=False;Encrypt=True;Connection Timeout=30;TrustServerCertificate=False';
var dbUser = '<Username>';
var dbPassword = '<Password>';

var query = {
    ConnectionString: dbConnString,
    User: dbUser,
    Password: dbPassword,
    SqlQuery: sqlUpdate,
    Parameters: sqlParam
};

var sqlresult = straatos.data.query(query);
```

***

### Supported Character Sets

Supported charsets (java might support more, but this is the minimum).

* US-ASCII Seven-bit ASCII, a.k.a. ISO646-US.
* ISO-8859-1 ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1.
* UTF-8 Eight-bit UCS Transformation Format.
* UTF-16BE Sixteen-bit UCS Transformation Format, big-endian byte order.
* UTF-16LE Sixteen-bit UCS Transformation Format, little-endian byte order.
* UTF-16 Sixteen-bit UCS Transformation Format, byte order identified by an optional byte-order mark.


# Straatos XML API

This article describes Straatos XML API

### New XML Document

Create new XML document. The documentElementName can contain namespace prefix (e.g. `ns:company`) if documentElementNamespace is provided. The documentElementNamespace is optional — for elements without namespace this parameter should not be specified.

#### Input Parameters

<table><thead><tr><th width="192.181884765625">Name</th><th>Description</th></tr></thead><tbody><tr><td>string ElementName</td><td>Name of root element</td></tr><tr><td>string Namespace</td><td>[Optional] Namespace of element</td></tr></tbody></table>

#### Sample Code

```javascript
var xmlnsDocument = straatos.newXMLDocument('ns:root', 'https://www.cumuluspro.com/api/1.0');

console.log(xmlDocument.xml);
```

#### Result

```xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<ns:root xmlns:ns="https://www.cumuluspro.com/api/1.0"/>
```

***

### Parse XML

Parse `data` parameter (either a `byte[]` or `string`) containing XML and returns XML document.

#### Input Parameters

<table><thead><tr><th width="193.0908203125">Name</th><th>Description</th></tr></thead><tbody><tr><td>string Xml</td><td>XML string</td></tr></tbody></table>

#### Sample Code

```javascript
var xmlString = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' +
'<root>' +
'<element>element value 1</element>' +
'<element>element value 2</element>' +
'</root>';

var xmlDocument = straatos.parseXML(xmlString);
```

#### Sample Code with XML Namespace

```javascript
var xmlnsString = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' +
'<ns:root xmlns:ns="https://www.cumuluspro.com/api/1.0">' +
'<ns:element>element value 1</ns:element>' +
'<ns:element>element value 2</ns:element>' +
'</ns:root>';

var xmlnsDocument = straatos.parseXML(xmlnsString);
```

#### Result

XML document object

***

### Add Element

Adds child element to current element. If `namespaceURI` is specified, `name` can contain a prefix, e.g. `ns:company`. For elements without namespace, no `namespaceURI` should be specified.

#### Input Parameters

<table><thead><tr><th width="194">Name</th><th>Description</th></tr></thead><tbody><tr><td>string ElementName</td><td>Name of element</td></tr><tr><td>string Namespace</td><td>[Optional] Namespace of element</td></tr></tbody></table>

#### Sample Code

```javascript
var xmlDocument = straatos.newXMLDocument('root');

var rootElement = xmlDocument.documentElement;

var element1 = rootElement.addElement('element');

element1.text = 'element value 1';

var element2 = rootElement.addElement('element');

element2.text = 'element value 2';

console.log(xmlDocument.xml);
```

#### Result

```xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<root>

<element>element value 1</element>

<element>element value 2</element>

</root>
```

***

### Select Multiple Elements

Select elements using given XPath expression, relative to current element. Optionally, namespaces can be specified, e.g. `{ 'ns': 'urn:my—urn', 'ns2': 'urn:my-urn-2' }`.

#### Input Parameters

<table><thead><tr><th width="193.09088134765625">Name</th><th>Description</th></tr></thead><tbody><tr><td>string Xpath</td><td>Xpath of element</td></tr><tr><td>Namespace</td><td>[Optional] Namespace prefix: namespace of element</td></tr></tbody></table>

#### Sample Code

```javascript
var xmlDocument = straatos.newXMLDocument('root');

var addMultipleElementsStatus = 'fail';

var rootElement = xmlDocument.documentElement;

var element1 = rootElement.addElement('element');

element1.text = 'element value 1';

var element2 = rootElement.addElement('element');

element2.text = 'element value 2';

var elements = rootElement.selectElements('/root/element');

elements.forEach(function (element, index) {

  console.log('element at index ' + index + ': ' + element.text);

});
```

#### Sample Code with XML Namespace

```javascript
var xmlnsDocument = straatos.newXMLDocument('ns:root', 'https://www.cumuluspro.com/api/1.0');

var rootnsElement = xmlnsDocument.documentElement;

var nselement1 = rootnsElement.addElement('ns:element', 'https://www.cumuluspro.com/api/1.0');

nselement1.text = 'ns:element value 1';

var nselement2 = rootnsElement.addElement('ns:element', 'https://www.cumuluspro.com/api/1.0');

nselement2.text = 'ns:element value 2';

var nselements = rootnsElement.selectElements('/ns:root/ns:element', { 'ns': 'https://www.cumuluspro.com/api/1.0' });

nselements.forEach(function (element, index) {

  var elementValue = 'ns:element value '+(index +1);

  console.log('element Value: ' + elementValue);

  if(element.text !== elementValue){
    selectElementStatus = 'fail';
  }

  console.log('element at index ' + index + ': ' + element.text);

});
```

#### Result

element at index 0: element value 1element at index 1: element value 2.

#### Result with XML Namespace

element at index 0: ns:element value 1.

element at index 1: ns:element value 2.

***

### Select Single Element

Select first element matching given XPath expression, relative to current element. Optionally, namespaces can be specified, e.g. `{ 'ns': 'urn:my—urn', 'ns2': 'my-urn-2' }`.

#### Input Parameters

<table><thead><tr><th width="193.0909423828125">Name</th><th>Description</th></tr></thead><tbody><tr><td>string Xpath</td><td>Xpath of element</td></tr><tr><td>Namespace</td><td>[Optional] Namespace prefix: Namespace of element</td></tr></tbody></table>

#### Sample Code

```javascript
var xmlDocument = straatos.newXMLDocument('root');

var rootElement = xmlDocument.documentElement;

var element1 = rootElement.addElement('element');

element1.text = 'element value 1';

var element2 = rootElement.addElement('element');

element2.text = 'element value 2';

console.log(xmlDocument.xml);

var elements = rootElement.selectSingleElement('/root/element');

console.log(elements.text);
```

#### Example with XML Namespace

```javascript
var xmlnsDocument = straatos.newXMLDocument('ns:root', 'https://www.cumuluspro.com/api/1.0');

var rootnsElement = xmlnsDocument.documentElement;

var nselement1 = rootnsElement.addElement('ns:element', 'https://www.cumuluspro.com/api/1.0');

nselement1.text = 'ns:element value 1';

var nselement2 = rootnsElement.addElement('ns:element', 'https://www.cumuluspro.com/api/1.0');

nselement2.text = 'ns:element value 2';

var nselements = rootnsElement.selectSingleElement('/ns:root/ns:element', { 'ns': 'https://www.cumuluspro.com/api/1.0' });

console.log(nselements.text);
```

#### Result

element value 1.

#### Result with XML Namespace

ns:element value 1.

***

### Remove Element

Removes element from document.

#### Sample Code

```javascript
var xmlDocument = straatos.newXMLDocument('root');

var rootElement = xmlDocument.documentElement;

var element1 = rootElement.addElement('element');

element1.text = 'element value 1';

var element2 = rootElement.addElement('element');

element2.text = 'element value 2';

element1.remove();
```

#### Result

```xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<root>

<element>element value 2</element>

</root>
```

***

### Add Attribute

Adds a new attribute to element. If `namespaceURI` is specified, `name` can contain prefix, e.g. `ns:attr`. For attributes without namespace, no `namespaceURI` should be specified.

#### Input Parameters

<table><thead><tr><th width="192.1817626953125">Name</th><th>Description</th></tr></thead><tbody><tr><td>string AttributeName</td><td>Attribute Name</td></tr><tr><td>string AttributeValue</td><td>Attribute value</td></tr><tr><td>string NameSpace</td><td>[Optional] Namespace of element</td></tr></tbody></table>

#### Sample Code

```javascript
var xmlDocument = straatos.newXMLDocument('root');

var rootElement = xmlDocument.documentElement;

rootElement.addAttribute('attr', 'attribute value');

console.log(xmlDocument.xml);
```

#### Sample Code with XML Namespace

```javascript
var xmlnsDocument = straatos.newXMLDocument('ns:root', 'https://www.cumuluspro.com/api/1.0');

var rootnsElement = xmlnsDocument.documentElement;

rootnsElement.addAttribute('ns:attr', 'attribute value', 'https://www.cumuluspro.com/api/1.0');

console.log(xmlDocument.xml);
```

#### Result

```xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<root attr="attribute value"></root>
```

#### Result with XML Namespace

```xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<ns:root xmlns:ns="https://www.cumuluspro.com/api/1.0" ns:attr="attribute value">

</ns:root>
```

***

### Select Attribute

Evaluates XPath expression relative to current element. Optionally, namespace can be specified.

#### Input Parameters

<table><thead><tr><th width="190.3636474609375">Name</th><th>Description</th></tr></thead><tbody><tr><td>string AttributeName</td><td>Attribute name</td></tr><tr><td>Namespace</td><td>[Optional] Namespace prefix: Namespace of element</td></tr></tbody></table>

#### Sample Code

```javascript
var xmlDocument = straatos.newXMLDocument('root');

var selectAttributeStatus = 'fail';

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('xpath string attr: ' + rootElement.stringValue('@attr'));
```

#### Example with XML Namespace

```javascript
var xmlnsDocument = straatos.newXMLDocument('ns:root', 'https://www.cumuluspro.com/api/1.0');

var rootnsElement = xmlnsDocument.documentElement;

rootnsElement.addAttribute('ns:attr', 'attribute value', 'https://www.cumuluspro.com/api/1.0');

var nselement1 = rootnsElement.addElement('ns:element', 'https://www.cumuluspro.com/api/1.0');

nselement1.text = 'ns:element value 1';

var nselement2 = rootnsElement.addElement('ns:element', 'https://www.cumuluspro.com/api/1.0');

nselement2.text = 'ns:element value 2';

nselement2.addAttribute('ns:elementAttr', '25', 'https://www.cumuluspro.com/api/1.0');

var attributeValue = rootnsElement.stringValue('@ns:attr', { 'ns': 'https://www.cumuluspro.com/api/1.0' });

console.log('xpath string attr: ' + attributeValue);
```

#### Result

xpath string attr: attribute value.

#### Result with XML Namespace

xpath string attr: attribute value.

***

### Select Element using Attribute

Evaluates XPath expression relative to current element. Optionally, namespace can be specified.

#### Input Parameters

<table><thead><tr><th width="192.18182373046875">Name</th><th>Description</th></tr></thead><tbody><tr><td>string AttributeFilter</td><td>Attribute filter.</td></tr><tr><td>Namespace</td><td>[Optional] Namespace prefix: Namespace of element.</td></tr></tbody></table>

#### Sample Code

```javascript
var xmlDocument = straatos.newXMLDocument('root');

var selectElementAttributeStatus = 'fail';

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';

var element = rootElement.stringValue('element[@elementAttr = "25"]');

console.log('xpath string query by attr: ' + element);
```

#### Example with XML Namespace

```javascript
var xmlnsDocument = straatos.newXMLDocument('ns:root', 'https://www.cumuluspro.com/api/1.0');

var rootnsElement = xmlnsDocument.documentElement;

rootnsElement.addAttribute('ns:attr', 'attribute value', 'https://www.cumuluspro.com/api/1.0');

var nselement1 = rootnsElement.addElement('ns:element', 'https://www.cumuluspro.com/api/1.0');

nselement1.text = 'ns:element value 1';

var nselement2 = rootnsElement.addElement('ns:element', 'https://www.cumuluspro.com/api/1.0');

nselement2.text = 'ns:element value 2';

nselement2.addAttribute('ns:elementAttr', '25', 'https://www.cumuluspro.com/api/1.0');

var attributeValue = rootnsElement.stringValue('ns:element[@ns:elementAttr = "25"]', { 'ns': 'https://www.cumuluspro.com/api/1.0' });

console.log('xpath string query by attr: ' + attributeValue);
```

#### Result

xpath string query by attr: element value 2.

#### Result with XML Namespace

xpath string query by attr: ns:element value 2.

***

### Remove Attribute

Removes attribute by name.

#### Input Parameters

string AttribueName.

#### Sample Code

```javascript
var xmlDocument = straatos.newXMLDocument('root');

var rootElement = xmlDocument.documentElement;

rootElement.addAttribute('attr', 'attribute value');

rootElement.removeAttribute('attr');

console.log(rootElement.xml);
```

#### Result

```xml
<?xml version="1.0" encoding="UTF-8"?>
<root></root>
```


# JavaScripts

The links below will direct you to the topics listed

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>Script Collection for Straatos</td><td><a href="/pages/5ad687ad69e20fe4cfbf50e653be2d46d60a5606">/pages/5ad687ad69e20fe4cfbf50e653be2d46d60a5606</a></td></tr><tr><td>Javascript Coding Standards and Best Practices</td><td><a href="/pages/79370a66b4d0b164e1131958c403c9934bb99042">/pages/79370a66b4d0b164e1131958c403c9934bb99042</a></td></tr></tbody></table>


# Script Collection for Straatos

This articles describes the Script Collection for Straatos

This page contains some samples and help for Scripts that can be used in Straatos.

* [Adjust Height of Table in Web Validation](#_Adjust_Height_of).
* [Line Items from Database](#_Line_Items_from).
* [Onwards (Move Document to Next Step)](#onwards-move-documents-to-next-step).
* [Sequence Numbering](#_Sequence_Numbering).
* [Show/Hide Fields](#_Show/Hide_Fields).
* [Timer](#_Timer).
* [Hide Table Columns in Web Validation](#_Hide_Table_Columns).
* [Enable/Disable Mandatory Option in Fields in Web Validation](#_Enable/Disable_Mandatory_Option).
* [Blank Page Removal](#_Blank_Page_Removal).
* [Error Handling with Error Event](#_Error_Handling_with).
* [Start New Workflow from Script](#_Start_New_Workflow).
* [AJAX Call with XML Data and Ampersand (&)](#_Ajax_Call_with).
* [Table Updates in Script Task](#_Table_Updates_in).
* [Table Updates in MyHome](#_Table_Updates_in_1).
* [Split Document](#_Split_Document).
* [Get File Size](#_Get_File_Size).

***

### **Adjust Height of Table in Web Validation**

It is useful to adjust the default height of the table in Web Validation (see red box area):

<figure><img src="/files/kgelNbNxBbOT5GHEcRzo" alt=""><figcaption></figcaption></figure>

You can do this by copying the following script into the 'Prescript' section of the workflow.

```
document.Tables[0].PanelHeight = 100;
cpapp.showHideTable(document);
cpviewer.reload();
```

If you use multiple Web Validation steps in a single process and want to display the table with different heights in different steps, you can use an if statement to do that.

```
if (cpapp._step.Name == "Name of WebValidation Step")
```

***

### **Line Items from Database**

This script allows you to retrieve and display line items from a database based on a specific Index Field value.

Example use case:

* When a PO Number is entered in an index field, the corresponding line items for that PO Number can be fetched from the database and displayed in Web Validation.

#### Configuration steps

1. Identify the Index Field that should trigger the line item retrieval.

* Example: PONumber.

2. Navigate to the 'Change Script' section of the selected Index Field.
3. Implement the script to fetch and populate line items dynamically.

Set the following options to on:

* Change Script Changes Field Definition.
* Change Script Changes Field Values.
* Change Script is Asynchronous.

In the 'Change Script', use the following code below.

```javascript
populateTable(field, fields);
function fieldByName(line, name) {
    return line.Fields.filter(function (field) { return field.Name === name; })[0];
}
function populateTable(field, fields){
    // Retrieve data from matching table
    var query = {
        User: 'DB user ID',
        Password: 'login password',
        SqlQuery: 'select * from DB table name where PONumber = @PONumber ' ,
        Parameters: {
            '@PONumber': value
        }  
    };
    try {
        var data = straatos.data.query(query);    
        if (data.ErrorMessage) {
            fields.PONumber.ErrorMessage = data.ErrorMessage;
        } else if (data.Records.length > 0) {
            var table = document.Tables[0];
            table.Body.Lines = [];
            for (var i=0; i<data.Records.length; i++) {
                var line = cpapp.addTableLine(table, table.Body.Lines);
                fieldByName(line, 'PONumber').Value = data.Records[i].PONumber ;
                fieldByName(line, 'LineNumber').Value = data.Records[i].LineNumber;
                fieldByName(line, 'Description').Value = data.Records[i].Description;
                fieldByName(line, 'PartNumber').Value = data.Records[i].PartNumber;
                fieldByName(line, 'Quantity').Value = data.Records[i].Quantity ;
                fieldByName(line, 'UOM').Value = data.Records[i].UOM;
                fieldByName(line, 'UnitPrice').Value = data.Records[i].UnitPrice;
                fieldByName(line, 'NetPrice').Value = data.Records[i].NetPrice;
            }      
        }
        finished();
    } catch(err) {
        fields.PONumber.ErrorMessage = err;
        finished();
    }
}
```

***

### **Onwards (Move Documents to Next Step)**

```
onwards = false;
```

Onwards is a boolean value that controls whether a workflow instance/document moves to the next activity after the script execution.

Default behavior:

* Default value:&#x20;
  * true.
* If true, the document automatically proceeds to the next step in the workflow.

Example use case

* Set onwards = false to keep a document in the current workflow step (e.g., if an error occurs and requires manual intervention).

***

### **Sequence Numbering**

```
straatos.nextSequenceNumber('someIdentifier’)
```

This function generates an incrementing number for a specified identifier.

Key features:

* The identifier can be reused across multiple processes.
* The generated number is unique for each identifier.
* It is the user's responsibility to ensure that is globally unique to prevent conflicts.

***

### **Show/Hide Fields**

This script applies to Web Validation Scripting.

In Web Validation, fields can be shown or hidden dynamically based on index field values.

Example use case:

* If a user selects 'Invoice' as the document type, specific Index Fields related to invoices should be displayed.
* If a user selects 'Correspondence', a different set of fields should be visible.

#### Implementation steps

1. Define the show/hide logic in the Workflow-Level Script Library.

* This ensures reusability across multiple scripts.

2. Call the function in relevant script sections to dynamically adjust visibility based on user input.

#### Best practice

* Store the function in the Script Library for centralized management and easier maintenance.

Enter the following code below.

```javascript
function hideInvoiceFields(fields, hide) {
    fields.InvoiceNumber.Hide = hide;
    fields.InvoiceDate.Hide = hide;
    fields.Subject.Hide = !hide;
    fields.Attention.Hide = !hide;
    fields.Reference.Hide = !hide;
}
function hideCorrespondenceFields(fields, hide) {
    fields.InvoiceNumber.Hide = !hide;    
    fields.InvoiceDate.Hide = !hide;
    fields.Subject.Hide = hide;
    fields.Attention.Hide = hide;
    fields.Reference.Hide = hide;
}
```

The above code inserts two functions. One to hide/unhide fields for Document type and the second function hides/unhides the fields for the Document type Correspondence. Both functions accept two parameters, firstly the fields, which is a collection of all index fields for the workflow, and secondly 'hide' which is a boolean true/false.

On the workflow level, go to the 'Change Script' section and set the following options to 'ON':

* Change Script Changes Field Definition.
* Change Script Changes Field Values.

With those options set to 'on', we system knows that the UI will be updated by the script. In the 'Change Script' enter the following code:

```javascript
hideCorrespondenceFields(fields, fields.DocumentType.Value == 'Invoice');
```

```javascript
hideInvoiceFields(fields, fields.DocumentType.Value == 'Correspondence');
```

The code will call the functions defined before and passes all the fields. Furthermore, depending on what the value is in the DocumentType field, the boolean 'hide' is set to true or false.

***

### **Timer**

Straatos supports a timer event. The timer event (officially the 'Timer Boundary Event') allows a task or document to be delayed at a predefined time.

Example use case:&#x20;

* Send an Invoice only on the invoice Date. Delay an error retry by 5 Minutes.

<figure><img src="/files/4JuONgPPPVSflBSEraaY" alt=""><figcaption></figcaption></figure>

The timer event can be setup based on three generic options.

<figure><img src="/files/4hQ6QPsxclRuEYoWhwGy" alt=""><figcaption></figcaption></figure>

Duration (in days, hours, minutes). This delays a task for a certain number of time from the time the task reaches this step.

Time Cycle based on a Cron Expressen: Supporting a delay to be sent on a specific time/date. For example every 1st of the Month, Every 10 Minutes etc.).

Workflow/Index field:&#x20;

* Based on a date/time of an index field.

Details on Index field date.

The value can be set in the following way:

* 2016-12-06T09:00:00+01:00
* The Time is optional. For example the following is valid:
  * 2016-12-06.&#x20;
    * In this case, the documents waiting in the timer event are released at midnight on the 6 December 2016. Midnight refers to UTC/GMT.
  * 2016-12-06T09:00:00:&#x20;
    * In this case, the time is set to 09:00 am UTC/GMT time.
  * 2016-12-06T09:00:00+01:00:&#x20;
    * In this case, the time is set to 09:00 UTC/GMT +1 (timezone).

Script to use to set a date:

```javascript
DueDate = '2016-12-06T09:00:00+10';
```

***

### **Hide Table Columns in Web Validation**

If you have created a table and want to display/hide certain columns depending on the workflow step, here is how it is done:

Example: User Task (Accounting Coding) will see the following table column fields:

* KontoListe.
* KostenstelleListe.
* Betrag

User Task (PO Exception) will see the following table column fields:

* ArtikelNr.
* Bezeichnung.
* Menge.
* ME.
* Preis.
* BetragCHF.

Script Library

```javascript
function hideLineItemFields(fields, hide) {
    $('#itable table tr > *:nth-child(4)').hide();
    $('#itable table tr > *:nth-child(5)').hide();
    $('#itable table tr > *:nth-child(6)').hide();
    $('#itable table tr > *:nth-child(7)').hide();
    $('#itable table tr > *:nth-child(8)').hide();
    $('#itable table tr > *:nth-child(9)').hide();
}
function hideAccountingFields(fields, hide) {
    $('#itable table tr > *:nth-child(1)').hide();
    $('#itable table tr > *:nth-child(2)').hide();
    $('#itable table tr > *:nth-child(3)').hide();
}
```

{% hint style="info" %}
Table column field start from 1
{% endhint %}

Pre Script:

```javascript
if (cpapp._step.Name == 'Kontrolle und Kontierung'') {
    hideLineItemFields(fields, true);
}
else if (cpapp._step.Name == 'PO Exception' ) {
    hideAccountingFields(fields, true);
}
```

***

### **Enable/Disable Mandatory Option for Fields in Web Validation**

Here is a script which enables/disables the field mandatory property. Below is the script 'mandatory' shall be call from function as 'true'.

```javascript
function EnableMandatory (fields,mandatory){
    fields.InvoiceNumber.IsRequired = mandatory;
}
function DisableMandatory (fields,mandatory){
    fields.InvoiceNumber.IsRequired = !mandatory;
}
```

***

### **Blank Page Removal**

The following script removes blank pages from a document.

Before executing the script:

1. Enable the 'Create Separate Pages from PDF' option in the Start Event settings.
2. Use the script below to detect and remove blank pages automatically.

Implementation

* The script scans each page to determine if it is blank and removes it accordingly.
* This ensures that only relevant content remains in the document.

```javascript
try {
    var documentInfo = straatos.adapter.getDocumentInfo();

    for (var p = documentInfo.documentPages.length - 1; p >= 0; p--) {
        var magickDetectInput = {
            DocumentId: _documentId,
            OutputFormat: 'info',
            ReturnOutput: true,
            PageIndex: p,
            Parameters:
            '-format "%[fx:mean>0.99?1:0]"'  //adjust parameters here to change blank page detection
        };

        try {
            var output = straatos.adapter.magick(magickDetectInput);
            if ('"1"' == output) {
                console.log('Magick output: ' + output + ', page index ' + p + ' should be removed.');
                var deletePageInput = {
                    PageIndex: p
                };
                try {
                    console.log(JSON.stringify(deletePageInput));
                    var deletePage = straatos.adapter.deleteDocumentPage(deletePageInput);
                    console.log(JSON.stringify(deletePage));
                } catch(error) {
                    straatos.setError('deletePage error:' + error);
                }
            }
        } catch(error) {
            straatos.setError('Magick error: ' + error);
        }
    }
} catch(error) {
    straatos.setError('documentInfo error: ' + error);
}
```

***

### **Error Handling with Error Event**

The error event is able to catch the error in a module and to route a task/document to a different flow in the process. The diagram below is a simple flow that catches an error event and routes it to a different step.

<figure><img src="/files/xYVcQ5nDPAq8gKUDpdiz" alt=""><figcaption></figcaption></figure>

The step 'Script simulate error' produces an error. The Error Event catches the error and routes the document to the step 'Read error message'.

The script error event is triggered by most modules automatically. When using a script task, then an error can be triggered using the following script.

```javascript
straatos.setError("Simulated error message");
```

In order to display the original error message (or to use the original error message in script) in the step 'Read error message', use the following code to retrieve the message.

```javascript
ErrorMessage = _errorMessage;
```

{% hint style="info" %}
The variable 'ErrorMessage' above is a Workflow Index field.
{% endhint %}

***

### **Start New Workflow from Script**

```javascript
var configUniqueId = straatos.uuid();
    var docUniqueId = straatos.uuid();
    straatos.ajax({
        url: 'https://effektif-connector.cumuluspro.net/ConnectorService.svc/json/UploadMetadata',
        data: JSON.stringify({
            ConfigurationUniqueId: '5ac4f9ab-7b0b-4982-bd75-533c1a2.....',
            UniqueId: configUniqueId,
            Documents: [{
                DocumentTypeUniqueId: '48e8c45d-ca8a-4106-8aec-fb741be.....',
                UniqueId: docUniqueId,
                DocumentFormat: 'PDF',
                Fields: [{
                    Name: 'OriginalDocumentId',
                    Value: '' + _documentId
                },{
                    Name: 'SupplierName',
                    Value: '' + SupplierName
                },{
                    Name: 'SupplierCode',
                    Value: '' + SupplierCode
                },{
                    Name: 'TranType',
                    Value: '' + TranType
                },{
                    Name: 'InvNo',
                    Value: '' + InvNo
                },{
                    Name: 'InvDate',
                    Value: '' + InvDate.format('YYYY-MM-DD')
                },{
                    Name: 'PONum',
                    Value: '' + PONum
                },{
                    Name: 'NET',
                    Value: '' + NET
                },{
                    Name: 'VAT',
                    Value: '' + VAT
                },{
                    Name: 'Gross',
                    Value: '' + Gross
                },{
                    Name: 'CostCentre',
                    Value: '' + CostCentre
                },{
                    Name: 'NominalCode',
                    Value: '' + NominalCode
                },{
                    Name: 'Department',
                    Value: '' + Department
                },{
                    Name: 'RowID',
                    Value: '' + RowID
                },{
                    Name: 'Table',
                    Value: JSON.stringify(table)
                }]
            }]
        }),
        method: 'POST'
    }).done(function (result) {
        console.log ('UploadMetadata ' + result);
        effektif.ajax({
            url: 'https://effektif-connector.cumuluspro.net/ConnectorService.svc/json/UploadDocument',
            data: pdf,
            contentType: 'application/pdf',
            headers: {
                'X-Configuration-Unique-Id': configUniqueId,
                'X-Document-Unique-Id': docUniqueId,
                'X-Page-Number': '1',
                'X-Number-Of-Pages': '1'
            },
            method: 'POST'
        }).done(function (result) {
            console.log ('UploadDocument ' + result);
        }).fail(function (jqXHR, error) {
            _errorMessage = 'UploadDocument ' + error;
            onwards = false;
        });
    }).fail(function (jqXHR, error) {
        _errorMessage = 'UploadMetadata ' + error;
        onwards = false;
    });
}).fail(function (jqXHR, error) {
    _errorMessage = 'Webmerge ' + error;
    onwards = false;
});
```

***

### **Ajax Call with XML Data and Ampersand (&)**

When sending data via an AJAX call with content type application/x-www-form-urlencoded, special characters like ampersand (&) require special handling.

Scenario:

If your data includes an ampersand, such as:

```javascript
xmlCopyEditJohnson & Johnson
```

In normal XML conversion, & is automatically converted to &:

```javascript
xmlCopyEditJohnson & Johnson
```

When using application/x-www-form-urlencoded, the ampersand (&) in & is still problematic because & is used as a parameter separator in URL-encoded data.

To resolve this, encode & as %26, so your XML becomes:

```javascript
xmlCopyEditJohnson %26amp; Johnson
```

With this, you are then able to send the data.

Sample code is below

```javascript
var strOutput = 'Johnson & Johnson';
    var encodedData = strOutput.replace('&','%26amp;');
    var formData = straatos.newFormData();
    formData.append('api_key=' + apiKey + '&document_id=' + xtractaDocumentId + '&document_status=' + vDocStatus  + '&submit=Submit' + "&field_data=" + encodedData);
    straatos.ajax({
        url: '',
        method: 'POST',
        contentType: 'application/x-www-form-urlencoded',
        data: formData
    }).done(function (responseXML) {
        console.log('Xtracta Response: '+responseXML);
        var returnedStatus =  straatos.parseXML(responseXML).documentElement.selectSingleElement('status').text;
        console.log(returnedStatus);
        if (returnedStatus == '200'){
            }
        else{
            straatos.SetError('Error: ' + response.documents_response.message);
        }
    }).fail(function (jqXHR, error) {
        console.log('Error:' + error);
        straatos.setError('Error: ' + error);
    });
```

{% hint style="info" %}
The var xOutput would be your XML body. The important line are the encodedData where all & are replaced by '%26amp;' then the form data is assigned. In the formData.append, you can add all the fields that need to be sent. At the end is the encodedData which contains modified XML.
{% endhint %}

***

### **Table Updates in Script Task**

In Straatos, table fields can be updated dynamically using scripts. The following example demonstrates how to:

* Access a table.
* Retrieve line items and fields.
* Perform calculations and assign values.

Example: Summing the LineTotal Field.

The script below:

1. Checks if there are any line items.
2. Iterates through each line item and retrieves the value of the LineTotal field.
3. Sums up all LineTotal values in the invlinesum variable.
4. Assigns the sum to the index field NetTotal.
5. Logs the result in the console.

```javascript
if (_table.body.lines.length) {
    for (var i = 0; i < _table.body.lines.length; i++) {
        invlinesum += parseFloat(_table.body.lines[i].LineTotal.value);
    }
    NetTotal = roundAmount(invlinesum);
    console.log('invlinesum:' + invlinesum);
    console.log('Net Total:' + NetTotal);
}
```

When users edit and delete line items in a MyHome task, the line numbering may become inconsistent. This script ensures that the LineNumber field remains sequential by renumbering all line items after changes.

How the Script Works:

1. Iterates through all line items in the table.
2. Checks if the Match field exists (i.e., not null or undefined).
3. Assigns a continuous number to the LineNumber field.

For the first column 'LineNumber' it assigns the value of the counter.

At the end (starting with \_table ={) the values are assigned to the table.

```javascript
if (_table.body.lines.length) {      
    for (var i = 0; i < _table.body.lines.length; i++) {
        counter = counter + 1;
        if(_table.body.lines[i]) {
            var tableLine = {
                LineNumber: { value: counter },
                Match : {value: _table.body.lines[i].Match? _table.body.lines[i].Match.value : ''},
                Quantity : {value: _table.body.lines[i].Quantity? _table.body.lines[i].Quantity.value : 0},
                PO : {value: _table.body.lines[i].PO ? _table.body.lines[i].PO.value : ''},
                VATRate : {value: _table.body.lines[i].VATRate ? _table.body.lines[i].VATRate.value : 0}
            };
            tableLines.push(tableLine);
        }
    }
   
    _table = {
        body: {
            lines: tableLines
        }
    };
}
```

***

### **Table Updates in MyHome**

The following function can be defined in the Script Library and used in My Home to update the table lines.

The script goes through each line item and sums up the LineTotal into the variable invlinesum. The invlinesum, after all amounts of the table are added is populated into the header field 'NetTotal'. This script can be executed when the table is updated to show the sum of an amount in a table.

```javascript
/ Check Sum Line item
function sumLineItem(fields, table) {
    var invlinesum = 0;
   
    if (table.body.rows.length > 0) {
        for (var i = 0; i < table.body.rows.length; i++) {
            if (table.body.rows[i].LineTotal) {
                invlinesum = invlinesum + parseFloat(table.body.rows[i].LineTotal);    
            }
        }
           
        // Check if Net Total = POP Total Net
        fields.NetTotal.Value = invlinesum;
        console.log('NetTotal: ' + fields.NetTotal.Value);
       
    }
}
```

The script below updates the line item values in My Home based on a lookup. In the Ajax call, a web service is called to return the Supplier data.

Based on the returned values, 4 table line items are updated.

```javascript
function fillGRNLineItemFields(poNumber, itemCode, rowIndex, fields, table, finished) {
    $.ajax({
       url: 'https://effektif-connector.cumuluspro.net/ConnectorService.svc/json/Interact//lookupGRNSupplierPartRef',
       method: 'POST',
       headers: {'X-Session-Id': Utils.readCookie('s')},
       data: JSON.stringify({ poNumber: poNumber, itemCode: itemCode })
   }).done(function (dataString) {
       var data = JSON.parse(dataString);
       if (data.ErrorMessage) {
           console.log('fillLineItemFields Query Error: ' + data.ErrorMessage);
       } else if (data.Records && data.Records.length == 1 ){
           table.body.fieldsForRow[rowIndex].GRNQuantity.Value = data.Records[0].Quantity;
           table.body.fieldsForRow[rowIndex].GRNItemDescription.Value = data.Records[0].ItemDescription;
           table.body.fieldsForRow[rowIndex].GRNUnitPrice.Value = data.Records[0].UnitPrice;
           table.body.fieldsForRow[rowIndex].GRNLineTotalNet.Value = data.Records[0].LineTotalValue;
       }
       finished();
   }).fail(function (jqXHR, error) {
       finished();
   });
}
```

***

### **Split Document**

```javascript
function splitDocument(index, documentType) {
    var docID = _documentId;
    try {
        var splitInput = {
            WorkflowInstanceId :straatos.getWorkflowInstanceIdByDocumentId(docID),
            PageIndex: index
        };
        var splitResult =  straatos.adapter.splitDocument(splitInput);
        var messageInput = {
            workflowId: workflowId,
            activityId: activityId,
            workflowInstances: [{
                workflowInstanceId: JSON.parse(splitResult).WorkflowInstanceId,
                variables: [{
                    id: 'DocumentType',
                    value: documentType
                }, {
                    id: 'PolicyNo',
                    value: PolicyNo
                }, {
                    id: 'OutputPath',
                    value: OutputPath
                }, {
                    id: 'BatchNo',
                    value: BatchNo
                }, {
                    id: 'POSNo',
                    value: POSNo
                }, {
                    id: 'ScanDate',
                    value: ScanDate
                }, {
                    id: 'SeqNo',
                    value: SeqNo
                }
                           ]
            }]
        };
        effektif.ajax({
            url: 'https://effektif-cpro-qa.azurewebsites.net/effektif-web/cp/message',
            data: JSON.stringify(messageInput),
            method: 'POST'
        }).done(function (messageResultString) {
            console.log('messageResultString: ' + messageResultString);
        }).fail(function (jqXHR, error) {
            _errorMessage = 'Message error: ' + error;
            onwards = false;
        });
    } catch (error) {
        _errorMessage = 'Delete page error: ' + error;
        onwards = false;
    }
}
splitDocument(NbDocPageIndex, 'DTB-NBDOC');
splitDocument(SuppDocPageIndex, 'DTB-SUPPDOC');
DocumentType = 'DTB-APPLFORM';
```

***

### **Get File Size**

When you need to get the file size of a document received, you can do this with the following script below.

```javascript
straatos.ajax({ url: url, method: 'GET'}).done(function(data, nothing, response) {
    console.log('Length: ' + data.length);
});
```


# JavaScript Coding Standards and Best Practices

This article defines a baseline JavaScript coding standard for function design and related readability practices.

### Core Principles

* Write functions that are easy to read.
* Prefer clarity and consistency over personal style preferences.
* Keep each function focused on one responsibility.
* Use names that communicate intent without requiring extra explanation.
* Return values should be predictable and consistent.

***

### Function Naming

Naming is one of the most important contributors to maintainability. A reader should understand what a function does from its name alone.

* Use camelCase for all function names, for example: `calculateTotal`, `getUserData`, `validateInvoiceDate`.

* Use descriptive names that clearly communicate the function’s purpose.

* Use verbs for action-oriented functions, such as get, set, calculate, build, format, validate, send, or update.

* Use nouns for variables or values rather than actions, such as `fullName`, `userAge`, `totalAmount`, or `invoiceDate`.

* Keep prefixes consistent across the codebase. For example, use get for retrieval, is or has for boolean checks, and set or update for state changes.

#### Recommended naming patterns

| Category          | Pattern                | Examples                                        |
| ----------------- | ---------------------- | ----------------------------------------------- |
| Action            | verb + noun            | `calculateTotal`, `printReport`, `buildPayload` |
| Retrieval         | get + noun             | `getUserName`, `getCustomerRecord`              |
| Assignment/update | set/update + noun      | `setStatus`, `updateInvoiceNumber`              |
| Boolean check     | is/has/can + condition | `isValidDate`, `hasAccess`, `canApprove`        |
| Formatting        | format + noun          | `formatCurrency`, `formatDisplayName`           |

#### Example

```javascript
function calculateTotal(items) {
  var total = 0;

  for (var i = 0; i < items.length; i++) {
    total += items[i].amount;
  }

  return total;
}
```

***

### Readability and Formatting

Consistent formatting lowers cognitive load. The goal is to make structure visible at a glance.

* Use consistent indentation throughout the codebase. Use either 2 spaces or 4 spaces, but do not mix them in the same file or project.

* Place opening braces on the same line as the function definition, conditional statement, or loop.

* Leave a blank line between function definitions to visually separate logical units.

* Use spacing consistently around operators, after commas, and between control blocks where readability benefits.

* Avoid deeply nested logic where a guard clause or helper function would make the flow easier to follow.

#### Example

```javascript
function getUserName(user) {
  if (!user) {
    return "";
  }

  return user.firstName + " " + user.lastName;
}

function printReport(reportName) {
  console.log(reportName);
}
```

#### Writting Comments

Comments should explain intent, business rules, assumptions, or non-obvious decisions. Do not use comments to restate what the code already says clearly.

* Write comments in clear, direct language and keep them concise.

* Explain why the code exists, any important constraint, or the reason for an unusual implementation choice.

* Place a short comment above the line or block it describes when that improves readability.

* Keep comments updated when the code changes. Outdated comments are worse than no comments.

* Avoid obvious comments such as “increment i” or “set total to total plus amount” when the code already makes that clear.

#### Example&#x20;

```javascript
// Validate the order before calculating any totals.
function processOrder(order) {
    validateOrder(order);

    var subtotal = calculateSubtotal(order.items);
    var tax = calculateTax(subtotal);

    return buildOrderSummary(subtotal, tax);
}

// Route invoices above the finance threshold for manual review.
function assignApprovalStatus(invoice) {
    if (invoice.totalAmount > 10000) {
        return "Manual Review";
    }

    return "Auto Approved";
}

```

#### Example to Avoid

```javascript
function calculateTotal(items) {
    var total = 0; // declare total variable and assign 0 to it

    for (var i = 0; i < items.length; i++) { // loop through items array
        total += items[i].amount; // add current item amount into total variable
    }

    return total; // return the total value
}
```

#### If/else formatting

If/else statements should be formatted so that each branch is visually clear. Always use braces, even for single-line branches, to reduce mistakes during future edits.

#### Example&#x20;

```javascript
function getAccessMessage(isLoggedIn, hasPermission) {
    if (!isLoggedIn) {
        return "Please log in.";
    } else if (!hasPermission) {
        return "Access denied.";
    } else {
        return "Access granted.";
    }
}
```

#### Example to Avoid

```javascript
function getStatus(code) {
    if (code === 1) {
        return "Open";
    } else {
        if (code === 2) {
            return "Closed";
        } else {
            if (code === 3) {
                return "Pending";
            } else {
                return "Unknown";
            }
        }
    }
}
```

***

### Function Length and Responsibility

Each function should do one thing well. Large functions that validate input, transform data, update state, and perform output in one block are harder to test and maintain.

* Keep functions focused on a single responsibility.

* Break overly long functions into smaller reusable helper functions when the logic naturally separates into steps.

* Avoid combining unrelated concerns such as data retrieval, formatting, and UI output in one function unless the scope is intentionally small.

* Where possible, make helper functions reusable and independently understandable.

#### Example

```javascript
function processOrder(order) {
  validateOrder(order);

  var subtotal = calculateSubtotal(order.items);
  var tax = calculateTax(subtotal);

  return buildOrderSummary(subtotal, tax);
}
```

***

### Return Values

A function that is expected to return a value should do so explicitly and consistently. Mixed return types make calling code harder to reason about.

* Always explicitly return a value when one is expected.

* Avoid mixing return types. For example, do not return a string in one branch and an object in another.

* Where no meaningful value needs to be returned, return nothing rather than returning inconsistent placeholders.

* Keep the return contract clear so that other developers know what to expect from the function.

#### Example

```javascript
function getStatusLabel(statusCode) {
  if (statusCode === 1) {
    return "Open";
  }

  if (statusCode === 2) {
    return "Closed";
  }

  return "Unknown";
}
```

#### Example to Avoid

```javascript
function getStatusData(statusCode) {
  if (statusCode === 1) {
    return "Open";
  }

  if (statusCode === 2) {
    return { label: "Closed" };
  }

  return false;
}
```

***

### Additional Best Practices

* Keep parameter names descriptive and aligned with the function’s purpose.
* Prefer early returns for invalid conditions when they simplify control flow.
* Avoid hidden side effects unless the function name clearly implies them.
* Use helper functions to remove repeated logic instead of copying blocks across multiple functions.
* During code review, evaluate whether a function can be understood quickly without needing surrounding context.

#### Code Review Checklist

| Area           | What to Verify                                                                                 |
| -------------- | ---------------------------------------------------------------------------------------------- |
| Naming         | Function name uses camelCase, starts with a verb where appropriate, and clearly states intent. |
| Responsibility | Function performs one logical task and does not bundle unrelated behavior.                     |
| Formatting     | Indentation, brace placement, spacing, and blank lines are consistent.                         |
| Parameters     | Inputs are clearly named and only required parameters are included.                            |
| Return value   | Return type is explicit and consistent across all execution paths.                             |
| Readability    | Variable names are meaningful and control flow is easy to follow.                              |
| Reusability    | Repeated logic has been extracted into smaller helper functions where useful.                  |


# JSON

The links below will direct you to the topics listed

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>JSON Coding Standards and Best Practices</td><td><a href="/pages/69de93f557f430b193c5c4a123814fccce31a00a">/pages/69de93f557f430b193c5c4a123814fccce31a00a</a></td></tr></tbody></table>


# JSON Coding Standards and Best Practices

This document defines a baseline JSON standard for configuration files, API payloads, and system data structures.

### Core Principles

* Keep JSON valid, predictable, and easy to parse.
* Prefer clear naming and stable structure over short or clever key names.
* Use consistent property ordering so similar objects read the same way.
* Choose the correct JSON type and keep that type stable for the same field.
* Keep objects focused and avoid deeply nested structures unless they add real clarity.

***

### Property Naming

Property names should be descriptive, stable, and consistent across the codebase. A reviewer should understand what each field represents without needing separate explanation.

* Use camelCase for JSON keys unless a system integration explicitly requires a different format.

* Use descriptive names that communicate the meaning of the field, for example `"customerName"` instead of `"cust"`.

* Use nouns for values and collections, such as `"documentId"`, `"fullName"`, or `"lineItems"`.

* Where a field exists only for reference or internal use, prefix it with an underscore when that convention is used in the project, for example `"_workflowNames"`.

#### Recommended JSON Property Patterns

| camelCase         | General keys                   | `"customerName"`, `"workflowIds"` |
| ----------------- | ------------------------------ | --------------------------------- |
| Boolean prefix    | True/false flags               | `"isActive"`, `"hasAccess"`       |
| Underscore prefix | Internal/reference-only fields | `"_workflowNames"`, `"_notes"`    |
| Consistent suffix | Identifiers and metadata       | `"documentId"`, `"createdDate"`   |

***

### Readability and Formatting

Formatting should help humans read the data quickly while keeping the JSON machine-safe.

* Use consistent indentation throughout the file. Two spaces is common for JSON, but the project should use one standard consistently.

* Use double quotes for all keys and string values, because valid JSON requires double quotes.

* Place each property on its own line when the object has multiple fields.

* Avoid trailing commas, because they are invalid in strict JSON and may break parsing.

* Use line breaks and indentation so nested objects and arrays are visually clear.

* Format example payloads consistently across documentation, configuration, and testing artifacts.

***

### Structure and Responsibility

Each object should represent one coherent unit of information. Related properties should stay together, and unrelated concerns should not be mixed into the same object without a clear reason.

* Keep each object focused on one logical responsibility.

* Group related data under nested objects only when the grouping improves clarity.

* Avoid unnecessary nesting that makes payloads difficult to read and validate.

* Use arrays for repeated items and keep the shape of each array item consistent.

* When the same concept appears in multiple places, use the same key names and the same structure

***

### Additional Best Practices

JSON should be reviewed not only for syntax, but also for naming, type consistency, structural clarity, and schema alignment.

#### JSON Review Checklist

| Area      | What to Verify                                                                                                                     |
| --------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| Validity  | JSON is syntactically valid: double quotes used, commas placed correctly, no trailing commas, and brackets are balanced.           |
| Naming    | Keys follow a consistent convention such as camelCase and use descriptive, stable names.                                           |
| Structure | Objects and arrays are organized logically, with nesting kept reasonable and repeated groups modeled consistently.                 |
| Typing    | Values use appropriate JSON types and similar fields do not switch between string, number, boolean, array, or object unexpectedly. |
| Ordering  | Property order is deliberate and aligned with how the data is read, configured, or displayed.                                      |
| Clarity   | Optional or internal-use fields are clearly named, and redundant properties are avoided.                                           |


# Automatic User Provisioning and User Roles assignment

This articles describes Automatic User Provisioning and User Roles Assignment

This feature automates the integration of users into Straatos, enhancing the onboarding process by streamlining user provisioning and group assignments. This system eliminates manual user setup, group linkage, and the need for acceptance of user invitations.

Once implemented, this feature allows users to access Straatos using their Azure Entra ID. It ensures users are automatically created or updated in Straatos, with group memberships managed according to their Azure Entra group assignments.

Supported Scenarios:

* Straatos supports two primary methods for handling group information:
  * Groups Provided by Azure Entra:

    * By default, Azure Entra transmits all groups a user is associated with.
    * For users in more than 150 groups, Azure Entra provides a link to fetch the complete group list via the Microsoft Graph API. This requires the application to have appropriate permissions.

  * Groups Provided via App Roles and Enterprise Applications:
    * In this method, groups are defined using App Roles configured under Enterprise Applications.
    * Only the app roles are included in the group claim, simplifying the permission model as CumulusPro does not need additional access to Azure Entra’s group data.

{% hint style="info" %}
This feature is available exclusively when using Azure Entra as the identity provider (formerly known as Azure Active Directory).
{% endhint %}

***

### **Setting up the application registration**

1. On the external Azure AD (Entra) go to 'Microsoft Entra ID'.
2. Select 'App registrations'.
3. Click on 'New registration.'

<figure><img src="/files/hVYHztQFzqe5VXzq6Wr4" alt=""><figcaption></figcaption></figure>

***

### **Setting up the Certificates & Secrets**

1. Click on 'Certificates & secrets'.
2. Click on 'New client secret'.
3. Enter a description of your choice, for example, 'Straatos SSO'.
4. Choose an option for 'Expires'.

{% hint style="info" %}
You will need to generate a new secret before the expiry and update Straatos with the secret for SSO to continue working.
{% endhint %}

5. Once the secret is created, make sure to copy the value and store it in a safe place.

***

### **Setting up the Token configuration**

1. Click on 'Token configuration.'

2. Ensure at least the following claims are there.

   1. email.
   2. family\_name.
   3. given\_name.
   4. preferred\_username.
   5. groups.

3. By default, the 'groups' claim is not defined. Here is how to set it up:
   1. Click on 'Add groups claim'.
   2. Select 'Security groups, Directory roles, All groups' (or select the options depending on how you manage the Straatos groups).
   3. In the customize token properties by type, ensure that for all of them 'Group ID' is selected.

***

### **Setting up the API permissions**

1. Select API permissions.
2. Add permissions.
3. Select 'Microsoft Graph'.
4. Select Delegated permission, and add the following rights under delegated permission:
   1. OpenId.
   2. Profile.
   3. Email.
   4. User.read.
   5. Directory.Read.All.
   6. GroupMember.Read.All.
   7. Group.Read.All.
5. Select Application permission, and add the following rights under application permission
   1. user.read.
   2. Directory.Read.All.
   3. GroupMember.Read.All.
   4. Group.Read.All.
6. Click on the 'Grant admin consent for' button and continue to grant the admin consent.

***

### **Setting up App Roles and Enterprise Applications**

If there is no access via Graph API to Directory.Read.All, GroupMember.Read.All, Group.Read.All is granted, app roles can be configured to provide only the app roles configured within the Enterprise Application.

1. Open App Registration.
2. Open App roles.
3. Create app role.
4. Give the app role a name. This name needs to be saved in Straatos. For easier identification, the app role can be the same as in Straatos.
5. Allowed member type (Users/Groups).
6. Value and Description can be set to any value that is internally recognized. Those values are not relevant in Straatos.
7. Ensure 'Do you want to enable this app role' is selected.

{% hint style="info" %}
Add as many app roles as required to match the groups in Straatos for the process by repeating step 3-7.
{% endhint %}

Once all App Roles are created:

1. Go to Enterprise Applications.
2. Select the same app name as in App registration.
3. Click on Users and groups.
4. Click on Add user/groups.
5. Select the users and groups that have access to this role.
6. Select the role to which the users have access to.

{% hint style="info" %}
Repeat steps 4-6 to add more users to the groups.
{% endhint %}

***

### **Contact CumulusPro Support**

Provide CumulusPro Support with the following details:

* Application (client) ID.
* Directory (tenant) ID.
* Client secret.

{% hint style="info" %}
The client secret should be passed securely as it will grant access to your Azure Entra information.
{% endhint %}


# Setting up ADFS with Straatos

This articles describes Setting up ADFS with Straatos.

This article describes how to configure a local Windows Active Directory to be used with Straatos to provide a Single-Sign On experience for the users. This requires the use of the Active Directory Federation Services.

### **Prerequisites**

* Active Directory Domain Services (ADDS) installed.
* SSL Certificate.

***

### **Installing Active Directory Federation Services (ADFS)**

1. Open the Server Manager on your local machine, click the “Dashboard” tab, click “Add Roles and Features”.

2. Under the “Add Roles and Features" wizard, on the installation type tab, select “Role-based or feature-based installation”.

3. On the “Server Selection” tab, select “Select a server from the server pool”. Choose “Microsoft Windows Server 2012 R2 Datacenter” server.

4. On the “Server Roles” tab, select “Active Directory Federation Services.

5. On the “Features” tab, click Next.

6. On the “ADFS” tab, click Next.

7. On the “Confirmation” tab, click Install.

***

### **Configuring Active Directory Federation Services (ADFS)**

After installing ADFS on your local machine, you will need to connect it to the ADDS instance and upload the SSL Certificate:

1. After installing ADFS, a notification icon will appear in the Server Manager window.

2. Click the icon to reveal a drop-down menu and click "Configure the federation service on this server”.

3. On the “Welcome” tab of the Wizard, select “Create the first federation server in a federation server farm”.

4. On the “Connect to ADDS” tab, the administrator account will be pre-selected. Click Next.

5. On the “Specify Service Properties” tab, click Import and select your SSL Certificate of your domain.

6. Enter a “Federation Service Display Name,” then click Next.

7. On the “Specify Service Account” tab, there will be an error message:
   1. Group Managed Service Accounts are not available because the KDS Root Key has not been set.

8. To resolve this error, open Windows PowerShell and run the following command:
   1. Add-KdsRootKey -EffectiveTime (Get-Date).AddHours(-10).

9. Back to the ADFS configuration wizard, the error will be gone. Select Create a Group Managed Service Account, provide an account name and click on the Next button.

10. On the “Specify Database” tab, select “Create a database on this server using Windows Internal Database.” Then click Next.

11. On the “Review Options” tab, click Next.

12. On the “Pre-requisites Checks” tab, click configure.

13. The server will now be installed. Once the installation is complete, you’ll be redirected to the “Results” tab. Click Close.

14. You have successfully configured and installed ADFS.

***

### **Configure ADFS as an IDP provider in Local Machine**

This will enable sign-in for users with an ADFS account in Azure AD B2C:

1. In Server Manager, select Tools, and then select ADFS Management.

2. In ADFS Management, right-click on Application Groups and select Add Application Group.

3. On the Application Group Wizard Welcome screen:
   1. Enter the Name of your application.
   2. Select the 'Web browser accessing a web application' template under Client-Server applications.
   3. Click Next.

4. On the Application Group Wizard Native Application screen:
   1. Copy and save the Client Identifier value. The client identifier will be used to add the ADFS instance as a new Open ID Connect IdP.
   2. In Redirect URI, enter: - `https://your-domain-name/your-tenant-name.onmicrosoft.com/oauth2/authresp.`
   3. Select Next, and then Next, and then Next again to complete the app registration wizard.
   4. Select Close.

***

### **Configuring the App Claims**

This will set up all claims the ADFS application returns to Azure AD B2C:

1. In the Application Groups, select the application you created.

2. In the application properties window, under the Applications, select the Web Application. Then select Edit.

3. Select the Issuance Transformation Rules tab. Then select Add Rule.

4. In Claim rule template, select Send LDAP attributes as claims, and then Next.

5. Provide a Claim rule name. For the Attribute store, select Active Directory, add the following claims.

| LDAP attribute      | Outgoing claim type |
| ------------------- | ------------------- |
| User-Principal-Name | upn                 |
| Surname             | family\_name        |
| Given-Name          | given\_name         |
| Display-Name        | name                |
| E-Mail-Addresses    | email               |

6. Select Finish.

7. Select Apply, and then OK.

8. Select OK again to finish.

***

### **Email Activation and Login**

Once you have received the activation email from CumulusPro, click the first blue link to activate your account and start logging in using your own on-prem login credentials.

<figure><img src="/files/8Zg8MacX16keSiIJOMK7" alt=""><figcaption></figcaption></figure>


# Configuring Straatos for SSO

This articles describes Configuring Straatos for SSO

Once CumulusPro Support has configured the IdP, the straatos organisation can be configured to work with the IdP. For the IdP to work correctly, you will need to have a custom domain for the TaskUI configured.

Custom Domain Setup for TaskUI:

* Domain Options:

  * You can use a custom domain (example: app..com) or a domain provided by CumulusPro (example: .cumuluspro.net).

* DNS Configuration:

  * If you use your own domain, configure CNAME entries with your DNS provider to point to the designated CumulusPro server.

* SSL Certificate:
  * Provide an SSL Certificate for your custom domain to ensure secure connections.

CumulusPro will set up the whitelabel configuration for your application, providing the following critical information:

* Custom Policy Name:
  * You will receive a specific policy name tailored to your organizational requirements.
* Domain Name:
  * A domain name will be provided, which will be integral to your application's access and identity configurations.

{% hint style="info" %}
These options are required to configure and link the IdP to your Straatos organisation.
{% endhint %}

***

### **Configuring the Straatos organisation to work with your IdP**

1. Go to '<https://straatosv2-api-qa-eu.cumuluspro.net/swagger/index.html>'.

2. Navigate to the organisations API and select the 'PUT /IAM/Organisations/{id}' API.

3. Enter your organisations id.

4. In the body, enter the following details:
   1. ssoIdentityProvider:
      1. The value for the adIssuer is the one that is provided in the token claim. It should look like this:
         1. `https://login.microsoftonline.com//v2.0 where the should be the Directory (tenant) ID from your app registration.`
   2. ssoClientId:
      1. The GUID from the client application created above.
   3. ssoClientSecret:
      1. The Client Secret created in the client application above.
   4. ssoIdentityExperiencePolicy:
      1. Provided by CumulusPro and will look similar to this: B2C\_1A\_SIGNUP\_SIGNIN\_TEST.

5. Execute the API call.

***

### **Configuring the Straatos Groups to match the AD/Entra Groups**

The groups from Active Directory/Entra need to be linked with the groups from Straatos to enable automatic user management.

1. Goto `https://straatosv2-api-qa-eu.cumuluspro.net/swagger/index.html`.
2. Navigate to the organisations API and select the 'PUT /IAM/Groups/{id}' API.
3. Enter your Group Id for which you want to link it to the AD/Entra Group.
4. In the body, enter the 'ssoGroupGuid'. The value is the Entra/AD Group ID you want to link. (example: 'df48830e-bda7-45b0-b135-03abd3a79c93').
5. Execute the API call.


# Getting Started

This tutorial is an introduction into configuring [Straatos](https://cumuluspro.com/straatos). In particular, we will configure a process with a start event, a manual data entry step using Web Validation as well as an automated processing step and a script.

At the end of this tutorial, you should be able:

* To create a new process.
* Use the CumulusPro Scan+Process*Lite*, Scan+Express and Mobile Capture as a starting point to a process.
* Use Web Validation in the process to validate documents by an operator.
* Use an automated module to process documents.
* Use the Process Designer to create a workflow.
* Use the Process Monitor to view documents in active processes.

### Prerequisites

As this tutorial focuses on the [Straatos Process](https://cumuluspro.com/straatos), we assume that you have already setup an Organisation and the Scan+Process*Lite*, Scan+Express or Mobile Capture clients.

{% hint style="danger" %}
**Ensure that you have created at least one (1) Document Type.**
{% endhint %}

### 1. Creating a new Workflow

In this step, we create a new workflow

1. Log in to the [CumulusPro Admin Panel](https://admin.cumuluspro.net/) with your credentials.
2. Open your organisation you want to create the workflow.
3. Click on 'Workflows'.
4. Click on the 'Create Workflow Configuration' tile.
5. Name the new 'Workflow Configuration' 'Tutorial Process' and then click on the tile.

Watch this video to see how a workflow is created:

{% embed url="<https://youtu.be/SiSoKVAN1bE>" %}

### 2. Adding Index Fields

In this step, we will add some index fields. The Index Fields created here are only available in the workflow and are separate to the index fields you may have created on your Document Types.

{% hint style="info" %}
If you want the Index Field values from your Document Type in the Scan or Mobile clients to be passed to your workflow, create an index field in the workflow with the same name as you created them in the Document Type.
{% endhint %}

1. Click on the + next to the 'Index Fields'.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_03_26_391.png?dc=201512290324-54)

2\. A new field 'NewField1' has been created.

3\. Add another two fields by repeating step 1 until your screen looks like this.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_03_30_042.png?dc=201512290328-12)

{% hint style="info" %}
If you have created too many fields or want to delete a field later, click on the blue x. This will remove the field from the workflow.
{% endhint %}

We are now going to rename the fields. For each field perform the following steps 1-3.

1. Click on the Index Field.
2. Change the field name to according to the table below.
3. Click 'Back' in the browser.

| Original Field | Display Name  | Field Name |
| -------------- | ------------- | ---------- |
| NewField1      | Email Address | email      |
| NewField2      | Name          | firstname  |
| NewField3      | Date          | date       |

### 3. Creating the Flow - Start Event

Watch this short video for an introduction:

{% embed url="<https://youtu.be/XabZW2OEI90>" %}

Click on the Design Process button.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_03_51_303.png?dc=201512290349-59)

This will open an empty Process Designer. On the left side, you find the steps that can be added to the process. We start by adding a Start Event.&#x20;

{% hint style="info" %}
A Start Event is the beginning of a workflow. This is where documents from Scan+ProcessLite, Scan+Express and Mobile Capture enter the workflow. Additionally, email import can as well be configured at a start event and third party integrations such as Zapier can use a start event to send documents to CumulusPro.
{% endhint %}

{% hint style="info" %}
A process flow can have multiple Start Event, one for each document type if necessary.
{% endhint %}

Click on the Start Event icon and drag it onto the design canvas: &#x20;

<div align="left"><img src="/files/-Mgddvrj0g_5uq-0beln" alt=""></div>

Your screen should now look like this:

<div align="left"><img src="https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_04_00_415.png?dc=201512290358-46" alt=""></div>

To edit the properties of the Start Event, click on the Settings icon.

<div align="left"><img src="/files/-MgdfAKwDHkWt0hyp-9M" alt=""></div>

This opens a pop up showing the settings for the Start Event.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_04_19_457.png?dc=201512290417-73)

Select the Document Type from the Dropdown. In the screenshot above, the document type 'Document' has been selected.

### 4. Adding a User Task

Now, having a Start Event where documents get into the workflow, let's add a User Task to the workflow. There are two ways this can be done, both described below. You will only need to perform one.

Video on how user tasks are created:

{% embed url="<https://youtu.be/F0wdm4-kpXw>" %}

Click on the Start Event. Select the 'Append User Task'.

<div align="left"><img src="https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_04_29_039.png?dc=201512290427-10" alt=""></div>

Place the User Task on the canvas like this:

<div align="left"><img src="https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_04_30_1510.png?dc=201512290428-12" alt=""></div>

Give the User Task a name 'Data Entry'.

Now that we have a user task, we need to assign a user to this task. For each User Task in the workflow, there is a role with the same name in the 'Authentication' section of the Organisation.

#### Add a New Account

1. Goto the Organisation Level in Admin Panel.
2. Click on 'Authentication'.
3. Click on 'Accounts'.
4. Click on 'Create Account'.
5. Enter a username (email address).
6. Enter a password.

#### Add an Account to the Workflow Step

1. Goto the Organisation Level in Admin Panel.
2. Click on 'Authentication'.
3. Click on 'Roles'.
4. Click on 'Data Entry' (the name of the step we created above).
5. Tick the account that should have access to the 'Data Entry' step.

The user has now access to the workflow step 'Data Entry'. However, if you haven't done yet so, you will need to give this user as well access to MyHome.

#### Access to My Home

MyHome is where a workflow user sees all the workflows and steps they have access to. If you do not have given those rights before. Follow the steps below:

1. Goto the Organisation Level in Admin Panel.
2. Click on 'Authentication'.
3. Click on 'Roles'.
4. Create a new Role and call it 'MyHome' and open the Role.
5. Tick the account that should have access to the 'MyHome' step.
6. Under Functions click on 'My Home'.
7. Under Document Types click on the document type the user should have access to.

#### Add an End Event

Click on the User Task 'Data Entry' and click on the 'End Event'.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_04_31_5411.png?dc=201512290430-15)

Drop the End Event onto the canvas.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_04_33_1012.png?dc=201512290431-7)

Now you have a complete workflow with a User Task. At this stage, the workflow does not do much, it just displays the document to a user, but afterwards, does not do anything with it. So, lets add a task to send the document via email.

On the left side, click on the Service Task and drag it over the line between the 'Data Entry' and 'End Event'.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_04_40_5913.png?dc=201512290439-40)

Drop the Service Task on top of the line and the step will be inserted there as shown in the screenshot below:

Name the Step 'Send Document'.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_04_42_2314.png?dc=201512290440-10)

Click on the step 'Send Document' and then onto the 'Settings' icon. From the actions dropdown, select the 'SendGrid Send Email'.

Your screen should look like this:

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_04_44_1115.png?dc=201512290442-66)

For the 'To Email Address', we want to use the email address of the Index Field 'email' we created earlier.

1. Click into the field 'To Email Address'.
2. Click onto the dropdown 'Insert Field at Cursor'.
3. Select 'email'.
4. For the 'From Email Address' enter the sender email address. For example '<noreply@cumuluspro.com>'.
5. For 'Subject' enter 'Your Document'.
6. For 'Text Body' Enter the below text:\
   `Hi {firstname},`\
   `Here is your document.`\
   `Regards,`\
   `The CumulusPro Team`
7. For 'Add Attachment' select 'Original Document'.
8. Close the pop-up box by clicking the x on the top right.

Now we are are ready to publish and test the process flow.

### Publish and Test the Process Flow

Click on 'Publish Workflow'.

<div align="left"><img src="https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_04_55_2916.png?dc=201512290453-45" alt=""></div>

One the workflow is successfully published, the date and time of the publishing appears next to the workflow.

{% hint style="info" %}
Any changes to the workflow will need to be published in order to be active in production. This includes adding, removing of index fields.
{% endhint %}

Now, submit a document from one of the Scan or Mobile Clients for the Document type specified.

### 5. Workflow Monitor & Processing Documents

After having submitted a document, you may want to see the document in the workflow. This section show you how to see the document in the workflow.

{% embed url="<https://youtu.be/-tMSYTbGyWI>" %}

Once the workflow is published, you can enter the monitor either in the Designer screen as shown below.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_05_30_4717.png?dc=201512290529-50)

Or on the workflow configuration, as shown below.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_05_31_5519.png?dc=201512290530-60)

The Process Monitor displays the same process flow as in the designer. Under each workflow step, the number of documents currently in the step are visible.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_05_47_5120.png?dc=201512290546-49)

To view the details of the documents in a particular step, click on the step and a pop up displays the details of the document.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_05_49_3921.png?dc=201512290547-99)

To see a preview of the document, click on a document and a viewer opens to see the documents.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_05_50_4822.png?dc=201512290549-136)

The document is currently ready in the User Task 'Data Entry'. In this section, we are going to process the document.

1. Log Out from Admin Panel.
2. Enter the username and password for the 'Data Entry' operator created earlier.
3. You will now be logged into 'My Home'.
4. At the bottom left, select the process ' Tutorial Process' and then click on 'Data Entry'.
5. The Web Validation client will be opened and you see the document with the index fields at the right.
6. Enter a valid email address where you want the document to be sent to.
7. Enter a first name that appears in the greetings line of the email.
8. Press the 'Complete' button on the top left.
9. The document is then processed by the workflow and the document is sent to the email address entered.
10. Check the email received as well as the document in the Monitor (which is now in the end event).


# Invoice Processing

### Objective

This tutorial shows how a sample invoice process can be configured.

At the end of this tutorial, you should be able to:

* Create a new invoice process
* Import Emails into the workflow
* Scan or use Mobile Capture to start a workflow
* Use Email to inform vendors about expectations in the invoice process
* Perform Optical Character Recognition (OCR)
* Extract Key Invoice Metadata, such as PO Number, Invoice Number
* Perform a Database Lookup & Other business rules
* Provide an email with a link to a document so vendors can update missing metadata directly in the process
* Use Timer functions to reject invoices if the vendor doesn't respond in a given timeframe
* Export Documents with Zapier to Google Drive
* Create Business Rules for Web Validation

### Process Overview

<div align="left"><img src="/files/-MgdhotAdlgky9jPXz8X" alt=""></div>

### Prerequisites

This section details the Admin Panel Organisation setup necessary prior to setting up the workflow. If the Organisation is already setup you can skip this section.

### Creating the Workflow

#### 1. Creating a New Workflow

In this step, we create a new workflow:

1. Log in to the [CumulusPro Admin Panel](https://admin.cumuluspro.net/) with your Credentials
2. Open the Organisation where you want to create the workflow
3. Click on 'Workflows'
4. Click on the 'Create Workflow Configuration' tile
5. Name the new 'Invoice Tutorial' and then click on the tile

Watch this video on how to create a workflow:

{% embed url="<https://youtu.be/SiSoKVAN1bE>" %}

#### 2. Adding Index Fields

In this step, we will add some index fields. The index fields created here are only available in the workflow and are separated from the index fields you may have created on your Document Types.

{% hint style="info" %}
If you want the index field values from your Document Types in the Scan or Mobile clients to be passed on to your Workflow, create an index field in the workflow with the same name as you created them in the Document Type.
{% endhint %}

1. Click on the + next to the 'Index Fields'.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_03_26_391.png?dc=201512290324-54)

2\. A new field 'NewField1' has been created. Click on it.

3\. Change the field display name, Field name and Datatype according to the table below.

4\. Repeat step 1 to 4 for the remaining fields.

| Name                | Display Name          | Datatype |
| ------------------- | --------------------- | -------- |
| InvoiceNumber       | Invoice Number        | string   |
| InvoiceDate         | Invoice Date          | date     |
| PONumber            | PO Number             | string   |
| TaxPoint            | Tax Point             | string   |
| NetTotal            | Net Total             | amount   |
| TaxTotal            | Tax Total             | amount   |
| GrossTotal          | Gross Total           | amount   |
| Currency            | Currency              | string   |
| DocumentType        | Document Type         | string   |
| SupplierCompanyName | Supplier Company Name | string   |
| SupplierTaxID       | Supplier Tax ID       | string   |
| RejectURL           | Reject URL            | string   |
| EmailFrom           | Email From            | string   |

### Start Event - Scan/Mobile/Email Import

In this section we create a start event that gets documents from one of our own apps, such as Scan+ProcessLite, Scan+Express, Mobile Capture or from any iConnector compatible application.

{% embed url="<https://youtu.be/XabZW2OEI90>" %}

#### Creating the Flow - Start Event

Click on the Design Process Button.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_03_51_303.png?dc=201512290349-59)

This will open an empty Process Designer. On the left side, you find the steps that can be added to the process. We start by adding a Start Event.

{% hint style="info" %}
A Start Event is the beginning of a workflow. This is where documents from Scan+Process*Lite*, Scan+Express and Mobile Capture enter the workflow. Additionally, email and FTP import can also be configured at a start event and third party integrations such as Zapier can use a start event to send documents to CumulusPro.
{% endhint %}

{% hint style="info" %}
A process flow can have multiple Start Event, one for each document type if necessary.
{% endhint %}

Click on the Start Event icon and drag it onto the design canvas.

<div align="left"><img src="https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_03_59_404.png?dc=201512290357-48" alt=""></div>

Your screen should now look like this.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_04_00_415.png?dc=201512290358-46)

To edit the properties of the Start Event, click on the Settings icon as shown below.

<div align="left"><img src="/files/-Mgdj-94cyclIRiQ-LNe" alt=""></div>

This opens a pop up showing the settings for the Start Event.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2015_12_29_04_19_457.png?dc=201512290417-73)

Select the Document Type from the dropdown. In the screenshot above, the document type 'Invoices' has been selected. However, the names available depend on the names given in the section '[Prerequisites](/tutorials-and-best-practices/straatos-tutorial-getting-started#prerequisites)'.

#### Start Event for Email Import

1. Create a second start event.
2. Click on the Settings.
3. Leave the document type empty.
4. Open the '+ Mail Polling'.
5. Complete the settings.
   1. The IMAP Server, Port and Username/Password depends on your server. If you do not have an email account, you can skip the email import part.
   2. Select 'Active' to ON, this will enable the email import.
   3. Map the email fields to the index fields, for example 'From' choose 'EmailFrom' from the dropdown list.
   4. In case of an error, the Mail Pooler Error Message will display what has gone wrong.

#### Create an OCR Task

In this section, we create a Task that performs Optical Character Recognition (OCR) from the two Start Events.

{% embed url="<https://youtu.be/coP5j4xg__A>" %}

1. Drag the 'Service Task' onto the canvas.\ <img src="/files/-MgdkBpneog5VnagE-b1" alt="" data-size="original">&#x20;
2. Name the Task 'OCR'.
3. Click on the OCR Task tile.
4. Select Settings.\
   ![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_01_27_05_13_293.png?dc=201601270510-20)
5. Select 'ABBYY OCR Searchable PDF' from the 'Action' dropdown.\
   ![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_01_27_05_28_444.png?dc=201601270526-28)
6. Close the OCR dialog by pressing the 'x' on the top right.
7. Now, connect the 'Start Event' to the OCR Task.
8. Click on the top start event, then click on the arrows.\
   ![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_01_27_05_30_565.png?dc=201601270528-26)
9. Drag the arrow on top of the OCR Task tile.
10. Repeat the above for the bottom start event. Your diagram should look like below.\
    &#x20;<img src="/files/-MgdkxZXiGDnZNbg3i4j" alt="" data-size="original"> \
    To make the diagram easier to read, we now adjust and label the arrows.
11. In the diagram above, we would like to adjust the arrow from the top start event to enter the OCR box from the top. In oder to do this, click on the arrow. The arrow is shown in a red-dashed line and the corners are marked in yellow.
12. Click on the connector and move it to until the arrows align.<img src="/files/-Mgdl7wLemjFtrZDvBky" alt="" data-size="original"> \
    The result should look like this.\
    &#x20;<img src="/files/-MgdlN6ee44IOvW7Iyoq" alt="" data-size="original"> \
    Now that the lines are drawn, we label them to indicate the input.
13. Double click on the line from the top start event.
14. Enter the name 'Email Import'.
15. Drag the Label near the start event.
16. Repeat the above steps for the second arrow and label it 'Scan/Mobile'. Your process should look like below.\ <img src="/files/-MgdleSOWzeJqpjnOubO" alt="" data-size="original">&#x20;

#### Metadata Extraction

The next step we add is to extract Metadata. While we could follow similar steps to adding the OCR Task, we explore an alternative here.

{% embed url="<https://youtu.be/YqaGlBgtzFk>" %}

1. Click on the OCR tile and select the Service Task.

   ![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_01_27_05_52_4111.png?dc=201601270550-23)
2. Place the service task onto the canvas next to the OCR.
3. Name the service task 'Metadata Extraction'.\
   *Note: The arrow to the service task was automatically added.*
4. Click on Settings of the 'Metadata Extraction'.
5. Select 'FocalPoint Invoice Extraction' from the 'Action' Dropdown List.
6. Now, the country settings are visible. Settings for the different 'Actions' appear after the action is selected.
7. From the 'Country' dropdown list select 'UK'.
8. Close the service task settings by pressing the x on the top right.

{% hint style="info" %}
The list contains supported and preconfigured Invoice Processing settings.
{% endhint %}

The process should look like this:

<div align="left"><img src="https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_01_27_05_57_4612.png?dc=201601270555-15" alt=""></div>

#### Scripting Business Rules with JavaScript

{% embed url="<https://youtu.be/nujlYdC_N_0>" %}

The Script Task allows you to define JavaScripts that are executed on the server side. In this tutorial step, we will use the Script Task to do a DB Lookup where we retrieve the SupplierCompanyName from the TaxID we found on the invoice.

1. Add a Script Task (either drag and drop the script task from the left menu or click on the Metadata Extraction step and add the script task.
2. Name the Script Task 'DB Lookup & Business Rules'.
3. Click on the Settings of the Script Task.
4. This opens a JavaScript editor.
5. Copy the following code into the script:

```
//DB Lookup
var query = {
    User: 'ukinvoice ',
    Password: '4149ad2c-7659-4215-abb5-a937e7cbc202',
    SqlQuery: 'select * from ukinvoice.Supplier where TaxID = @TaxID',
    Parameters: {
        '@TaxID': SupplierTaxID
    }    
};

effektif.ajax({
    url: 'https://iconnector-configuration.cumuluspro.net/v2.2/DataService.svc/json/Query',
    data: JSON.stringify(query),
    method: 'POST'
}).done(function (stringData) {
    var data = JSON.parse(stringData);
    
    if (data.ErrorMessage) {
        _errorMessage = data.ErrorMessage;
        onwards = false;
    } else if (data.Records.length == 1) {
        SupplierCompanyName = data.Records[0].Name;
    } 
}).fail(function (jqXHR, error) {
    _errorMessage = error;
    onwards = false;
});
```

This script queries the database with the TaxID and from the returned records, it selects the first and populates the value into the SupplierCompanyName index fields. In case of an error, the error message is assigned to the \_errorMessage variable and the document stays in this workflow step.

The process flow should now look like below.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_01_27_09_47_1913.png?dc=201601270944-19)

#### User Task - Validation

{% embed url="<https://youtu.be/IdpwjTLOEg8>" %}

Now that we have the metadata extracted and the business rules executed, we want a user to validate the invoice. The user should have the option to edit the Index Field and if the document is correct to complete the document. If the document has to be sent to the vendor, the user will reject the document for the vendor to update.

1. Add a User Task to the workflow.
2. Name the User Task 'Validation'.
3. Draw an arrow from the 'DB Lookup & Business Rules' to the Validation.
4. Click on the Settings of 'Validation'.
5. In Application Configuration select 'Web Validation (MyHome)' from the drop down list.
6. Under 'Validation' button enable the 'Complete' and the 'Reject' button.
7. Close 'Validation Settings' by clicking the top right 'x' of the dialog.

{% hint style="info" %}
As Validation requires users to access documents, we will create users and roles. However, we will do that later when we created a few more steps that require user interaction.
{% endhint %}

The workflow should look like this:

![](/files/-MgdmwtI4pNHxEcAQc0G)

#### Exclusive Gateway

{% embed url="<https://youtu.be/6XP3mrNDlqg>" %}

In Validation, we have given the user the chance to either Complete the invoice (and move to the next step) or to Reject the invoice. Hence in this next step, we want to route the document to different steps in the workflow.

1. If the document is completed, then it should move on to the Approval stage.
2. If the document is rejected, we want to inform the vendor and give the vendor a chance to correct the invoice.

An Exclusive gateway is added in the same way as a process step.

1. Drag and Drop the Exclusive gateway onto the canvas.
2. Draw an arrow from Validation to the exclusive gateway.

{% hint style="info" %}
The routing definition from the exclusive gateway is defined in the outgoing arrow. We will cover this in the next step.
{% endhint %}

#### Script Task - Web Validation URL for Supplier

If we reject the document to the vendor, we want to inform the vendor by email that the invoice has been rejected. As part of the email, we want to include a link to the web validation module (and document) where the vendor can update the document.

1. Drag and Drop a Script Task onto the canvas.
2. Name the Script Task to 'Create Web Validation URL for Supplier'.
3. Open the settings for the Script Task.
4. Copy/Paste the following code into the script task:

```
effektif.ajax({
    url: 'https://iconnector-configuration.cumuluspro.net/v2.0/AuthService.svc/json/TokenForFederatedAccount?' +
             'loginName=' + encodeURIComponent('supplier@invtutorial.com') + '&' + 
             'password=' + encodeURIComponent('password') + '&' +
             'customdata=' + encodeURIComponent('step=979,docid=' + _documentId),
    data: '',
    method: 'GET'
}).done(function (dataString) {
    var token = JSON.parse(dataString);
    
    RejectURL = 'https://webvalidation.cumuluspro.net?ConfigurationUniqueId=2b1c48b9-a3ea-4a13-8fa1-7772ec90d6d5&token=' + token;
}).fail(function (jqXHR, error) {
    _errorMessage = error;
    onwards = false;
});
```

The script creates a URL that points to the document with an access token. The URL is then assigned to the index field RejectURL.

{% hint style="warning" %}
**The step ID (in the sample code 979) needs to match the step ID of the web validation module. The step ID for web validation is the ID that is in the pop up of the User Task. This has not yet been created and needs to be updated in the script later.**
{% endhint %}

Now that the Script Task has been created, we can draw the conditional routing to that script task.

1. Click on the Exclusive gateway.
2. Click on the arrow.
3. Draw the line to the 'Create Web Validation URL for Supplier'.
4. Click on the arrow.
5. Click on the Settings icon.
6. For the Condition Field select '\_status' from the dropdown list.
7. For the 'Equals' enter 'reject'.\
   *`Note: The _status variable is assigned the value of the button clicked by the user in Web Validation. the button 'Reject' assigns the value 'reject'.`*
8. Close the Arrow Dialog.
9. Double Click the arrow.
10. Enter a Label description 'Reject to Supplier' and position this next to the arrow.

The workflow should now look like this:

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_01_27_10_15_0415.png?dc=201601271012-38)

#### Email to Supplier

In the next step, we want to send the vendor an email with a link to the invoice. The vendor can then click on the link in the email to update the details to the invoice.

1. Add a Service Task.
2. Name the task 'Email to Supplier'.
3. Draw an arrow from 'Create Web Validation URL for Supplier' to 'Email to Supplier'.
4. Click on the Settings of the 'Email to Supplier' service task.
5. From the Action, select 'SendGrid Send Email'.
6. Enter the details of the email.\
   *Note: To Email address can be taken from the Index field or can be a fixed email address.*
7. For the body, you can either use a Text Body or HTML Body. For HTML, copy this sample HTML email:

```
<body> 
    <p>Dear Sir/Madam,</p>
    
    <p>An invoice that we have received from you needs your attention. Please click on the link below to review the invoice and the respective comments/questions.</p>
    
    <p>{RejectURL}</p>
    
    <p>Regards,
    <br>The CumulusPro Team</br></p>
</body>
```

{% hint style="info" %}
The **{RejectURL}** is the index field value we enter here.
{% endhint %}

{% hint style="info" %}
If you have your own SendGrid account, you can enter the API Key in the settings. Then we will use your account. Otherwise the CumulusPro account will be used and the outgoing email will be from CumulusPro.
{% endhint %}

#### Supplier Validation and Timer

{% embed url="<https://youtu.be/F0wdm4-kpXw>" %}

Once the email has been sent to the supplier, the system will wait for the supplier to update the invoice. There are two potential outcomes:

1. The supplier updates the invoice and completes the assigned task.
2. Supplier does not take any action and hence after a certain waiting period, the invoice should be processed as an exception (Email to Supplier that the invoice has been rejected).
   1. Add a User Task and name it 'Supplier'.
   2. Draw an arrow from 'Email to Supplier' to 'Supplier'.
   3. Draw an arrow from 'Supplier' to 'Validation'.
   4. Click on the 'Supplier' User Task settings.
   5. For 'Application Configuration' select 'Web Validation (MyHome)'.
   6. For 'Validation Buttons' select 'Complete'.
   7. Close the 'Supplier Settings' by clicking on the top right 'x'.

Now, we add a Timer function (Boundary event).

1. Drag and Drop the Boundary event onto the Supplier User Task on the bottom right.\
   ![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_01_27_10_35_3416.png?dc=201601271032-20)
2. Click on the Boundary Event.
3. Click on Settings.
4. Enter '3' in the 'Days' section.

This means that a task will wait for 3 days until action is taken. If no action is taken, the task is routed to another step.

{% hint style="info" %}
Update the 'Create Web Validation URL for Supplier' with the correct ID of the 'Supplier' user task.
{% endhint %}

#### Email to Supplier - Invoice Reject

In the case where the Supplier does not take action on the invoice within 3 days, we want to send an email to the Supplier informing the supplier about the rejection of the invoice.

1. Add a Service Task onto the canvas next to the Boundary Event.
2. Name the Service Task 'Email to Supplier - Invoice Reject'.
3. Draw an arrow from the Boundary Event to the new Service Task.
4. Double Click on the Arrow and create a label 'No response within 3 days.
5. Click 'Settings' on the 'Email to Supplier - Invoice Reject' and complete the email settings similar to the previous 'Email to Supplier' task.
6. In 'Add Attachment' select 'Original Email (EML) as the first attachment.
7. In the second 'Add Attachment' select 'Original Document'.

The workflow should now look like this:

![](/files/-MgdoY0N5fzKvmM1QpT4)

#### End Event

To complete the workflow, we add an end event. This are where documents are completed and after a configured time are deleted from the Straatos Platform.

1. Add an End Event to the process next to 'Email to Supplier - Invoice Reject'.
2. Draw a line to the End Event.

The workflow should now look like below.

![](/files/-MgdonoPyVrXr2HMNXo3)

#### Approval

Having complete the exception handling where we need suppliers to update the invoice, we now need to complete the standard (default) process. For this tutorial, we would like to route the document to an Approver. The Approver will have the option to Complete the document.

1. Add a User Task 'Approver'.
2. Draw an arrow from the Exclusive Gateway to 'Approver'.
3. For 'Approver' settings, enable the button 'Complete'.
4. For 'Application Configuration' select 'Web Validation (My Home)'.

The workflow should now look like this:

![](/files/-Mgdp2n3Czhl5Wy_kMBi)

#### Commenting

Comment fields are an easy way to add notes to the workflow so it makes it easier to understand. For this tutorial, we add a note to the Supplier step to give an example of why a document is sent to the Supplier.

1. Click on Supplier.
2. Click on the notes icon.\
   ![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_01_27_12_08_5120.png?dc=201601271206-12)
3. Place the note box onto the canvas.
4. Enter a description, such as 'Missing PO Number'.

#### Export to Google Drive via Zapier

In the last step, we want to export the documents and metadata to a backend system. For this tutorial we use Zapier to export the documents to Google Drive. Zapier ([www.zapier.com](http://www.zapier.com)) provides integrations into more than 500 applications. Hence the Google Drive example is just one of many.

1. Add a Service Task next to the 'Approver'.
2. Name the Service Task 'Export to Google Drive.
3. Draw an arrow from 'Approver' to the 'Export to Google Drive'.
4. Draw an arrow from 'Export to Google Drive' to the End Event.
5. Click on settings on 'Export to Google Drive' and select 'Zapier Integration' from the  'Action' Dropdown.

The remaining configuration is done within Zapier. We first complete the user and role setup and route a document past the all the steps so Zapier can automatically pick up the values to link to Google Drive.

#### User and Roles Setup

We need to create a user for each Validation step as well as a user to work with Zapier.

1. Select 'Invoice Processing Tutorial' from the menu navigation.\
   ![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_01_27_12_24_0522.png?dc=201601271221-50)&#x20;
2. Select Authentication.
3. Select Roles.
4. Each User Task workflow step has already a role. However, we need to create a role for 'My Home' and 'Zapier'.
5. Click on 'Create Role'.
6. Name the role 'Zapier'.
7. Click on the tile 'Zapier'.
8. Under Functions, select 'Zapier'.\
   ![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_01_27_12_26_4823.png?dc=201601271224-36)
9. Click on 'Back' in the browser.
10. Click on 'Create Role'.
11. Name the Role 'My Home'.
12. Under Functions, select 'My Home'.
13. Lastly, set up a scan role.
14. Click on 'Back' in the browser.
15. Click on 'Create Role'.
16. Name the Role 'Scan'.

Now we have created the roles, lets create the users:

1. Go back up to 'Authentication'.
2. Click on 'Accounts'.
3. Click on 'Create Account'.
4. Name the user '<Supplier@InvTutorial.com>'.
5. Click on the tbile.
6. Enter an easy to remember password.
7. Select 'Supplier' from the 'Add Role'.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_01_27_12_31_4124.png?dc=201601271229-52)

Repeat steps 3-7 for the following users/roles:

* <Approver@InvTutorial.com>   - Approver
* <Validation@InvTutorial.com> - Validation
* Tutorial-Zapier - Zapier
* <Scan@InvTutorial.com> - Scan

Now the roles have been setup.

### Testing the Workflow

#### Publishing the Workflow

Before using the workflow, we need to publish it.

1. Go to Workflow Configuration - Invoice Process Tutorial - Design Process.
2. Click on 'Publish Workflow'.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_01_28_00_23_3927.png?dc=201601280021-49)

#### Upload a Document

Use either the Mobile app or Scan+Process*Lite* to scan and upload a document.

#### Monitor the Documents

1. Go to Workflow Configuration - Invoice Process Tutorial - Monitor Process.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_01_28_00_26_3729.png?dc=201601280023-71)

#### Processing Documents

Use one of the CumulusPro Clients to capture a number of invoices. In this example we use Scan+ProcessLite.

1. Goto the Link tile.\
   ![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_02_02_05_29_204.png?dc=201602020529-5)
2. Open the Scan+ProcessLite link.\
   ![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_02_02_05_30_175.png?dc=201602020530-95)
3. If it is the first time you are using scan client on the machine, you will need to install Scan+. Otherwise, you will be prompted to log in.
4. Login with the Scan Operator credentials (alternatively, if you have configured 'Anonymous login', you will skip this step.
5. Scan documents and upload documents.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_02_02_05_35_347.png?dc=201602020535-164)

{% hint style="info" %}
We need to include an index field 'FromEmail' where we can enter the email address. This makes it possible to test the email notification.
{% endhint %}

#### Monitoring the Process

{% embed url="<https://youtu.be/-tMSYTbGyWI>" %}

Now that the documents are uploaded, we want to monitor the progress in the Process Monitor.

1. Open admin.cumuluspro.net.
2. Log in.
3. Go to the workflow.
4. Next to the 'Design' Button there is a 'Monitor' button. Click on the button.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_02_02_05_39_419.png?dc=201602020539-111)

The Process Monitor opens and displays the same representation as the Design Process.

If the documents are successfully imported, they are displayed as a number below the workflow step they are currently in.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_02_02_05_42_0510.png?dc=201602020542-107)

In the above screenshot, 1 document is visible.

If the documents are not all visible, this might be that the counters have not been refreshed. The counters refresh every minute automatically. If you want to refresh the counters manually, you can do this by pressing the 'Update Counters' link.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_02_02_05_43_4211.png?dc=201602020543-40)

To see more details of the documents in a particular step, click on the step tile. A table opens showing the details of the documents as well as actions that can be taken for those documents.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_02_02_05_46_2612.png?dc=201602020546-162)

If you would like to see a preview of the documents, click the document line (not the checkbox in front) and a preview screen opens on the right.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_02_02_05_47_3913.png?dc=201602020547-144)

To hide the preview screen, click on the document line again.

Continue to process all the documents and check the outcome in each particular step until the 'Export to Google Drive' step. Next, we will setup Zapier.

#### Zapier Configuration for Google Drive Export

For this tutorial, we going to setup Zapier as an export for Google Drive.

1. Goto [www.zapier.com](http://www.zapier.com).
2. If you don't have already a login, create a new login.
3. One setup, go to 'My Zaps' and click on 'Make a New Zap'.
4. Your screen should look like this:

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_02_02_05_54_5114.png?dc=201602020554-128)

5\. In 'Choose a Trigger App' enter CumulusPro.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_02_02_05_56_2415.png?dc=201602020556-82)

6\. Select CumulusPro.

7\. Then for 'Choose Trigger' click on 'Save+Continue'.

8\. Select (or create) and account.

{% hint style="info" %}
`If you haven't used Zapier with this workflow yet, create a new account and log in with your organisation level account that has rights to zapier.`
{% endhint %}

9\. Click on Test Account and once 'Account is working' is displayed, click on 'Save+Continue'.

10\. On the Set Up Options, choose the workflow and the workflow step.

{% hint style="info" %}
&#x20;*Only workflow steps which are 'Service Tasks' and where the Action is 'Zapier Integration' are shown.*
{% endhint %}

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_02_02_06_03_2616.png?dc=201602020603-104)

11\. On 'Test this Step' click 'Fetch & Continue'. Important is that a document is currently in the 'Export to Google Drive' step.

12\. If the test is successful, click on continue.

Now we setup the Action (Google Drive)

1. Search and select 'Google Drive'.
2. Choose 'Create File from Trigger' and click 'Save+Continue'.
3. Select your Google account or add a new one, then click Save & Continue.
4. Select the Folder (optional).
5. In 'File', click on the list icon at the end and then select the document you want to export. In this case it is the 'ABBYY OCR searchable PDF'.\
   ![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_02_02_06_13_3417.png?dc=201602020613-45)
6. Click Continue.
7. Click 'Create & Continue' on the 'Test Google Drive'.
8. When the 'Test Successful' appears, click on 'Finish'.
9. Create a Name for your Zap and switch it on.
10. Now the Zapier setup is complete.

Follow the step below to process the document in Admin Panel Process Monitor.

1. Select the document.
2. Click on Retry selected.
3. The document now gets exported to Google Drive.
4. Check Google Drive if the documents are there.

### Business Rules in Web Validation

{% embed url="<https://youtu.be/L-ZMK1jZAjw>" %}

So far, we have setup business rules in Java Script as part of a process step. However, we may want to validate index information in the Validation screen. For this tutorial we add a check if the GrossTotal is equal to the NetTotal + Tax.

1. Go to the Workflow setup.
2. Click on the index field 'GrossTotal'.
3. Scroll down to the 'Validation Expression Message'.
4. Add the message 'Net Total + Tax Total is not equal to Gross Total'.
5. In 'Validation Expression (boolean)' enter the JavaScript below.

```
roundAmount(NetTotal + TaxTotal) == roundAmount(GrossTotal)
```

Now, to test, open the fly-out on the right hand side.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_01_27_12_43_2825.png?dc=201601271240-79)

This opens the Web Validation Simulator. The Web Validation Simulator displays all the fields and rules as the web validation module. Each change that is made in the rules will immediately reflect in the simulator. Also, the index field values can be entered and tested if they fit the rules.

![](https://dzf8vqv24eqhg.cloudfront.net/userfiles/3385/5046/ckfinder/images/2016_01_27_12_45_2626.png?dc=201601271242-102)


# Page 1

### **Optimized for the Cloud Infrastructure**

**Straatos BPM** is fully optimized for cloud infrastructure, enhancing its accessibility and performance across various locations.\
Users can access the platform from anywhere with an Internet connection.

***

#### **Security and Reliability**

The platform leverages **Microsoft Azure’s global network of data centers**, which are:

* **ISO/IEC 27001 certified** — ensuring high standards of information security management.
* **Compliant with Safe Harbor principles** — guaranteeing proper handling of European citizens’ personal data.

***

**Scalability**

By utilizing the **scalability of Azure**, Straatos can:

* Support **any number of accounts**.
* Manage **multiple concurrent processes** efficiently.
* Seamlessly accommodate **growing business demands** without performance compromise.


