WorkflowGen features the API, which is a modern solution to create process-driven solutions such as mobile apps, web apps, and microservices that require a powerful workflow and BPM engine.
The WorkflowGen GraphQL API is a Node.js application that runs in IIS using . It enables a high level of customization such as extending the GraphQL schema with custom types, queries or operations, or implementing new authentication methods.
About GraphQL
From the website presentation:
GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.
GraphQL is a and an open source technology created by Facebook. In September 2016, GitHub its GraphQL API.
We’ve often heard that our REST API was an inspiration for other companies; countless tutorials refer to our endpoints. Today, we’re excited to announce our biggest change to the API since we snubbed XML in favor of JSON: we’re making the GitHub API available through GraphQL.
GraphQL is a modern API solution for React, React Native, Angular 2, and Vue based applications.
Many GraphQL tutorials are available, it's available in many languages, and it has a large .
Technical requirements
In addition to the standard WorkflowGen installation, the following components are required:
✏️ Note: This library is required if you encounter the error The specified module could not be found regarding the edge and edge-js libraries when accessing the /wfgen/graphql, /wfgen/hooks, or /wfgen/scim web apps.
The HTTP GET method is supported on queries only. The HTTP POST method is supported on queries and operations.
HTTP usage
GraphQL will first look for each parameter in the URL's query-string: /graphql?query=query+getUser($id:ID){user(id:$id){name}}&variables={"id":"4"} If not found in the query-string, it will look in the POST request body. If the POST body has not yet been parsed, express-graphql will interpret it depending on the provided Content-Type header:
application/json: the POST body will be parsed as a JSON object of parameters.
application/x-www-form-urlencoded: this POST body will be parsed as a url-encoded string of key-value pairs.
application/graphql: the POST body will be parsed as GraphQL query string, which provides the query parameter.
Using GraphiQL IDE in a web browser
As of WorkflowGen version 7.15.0, the GraphiQL tool is disabled by default. You can enable it in the GraphQL section on the Configuration Panel Integration tab. You can also enable GraphiQL in the WorkflowGen web.config file by setting the GraphqlGraphiqlEnabled parameter to Y.
Configuration
Maximum query content length
The maximum GraphQL query content length can be set by configuring the maxAllowedContentLength property in the WorkflowGen web.config file. The following example shows how to configure this property as 1 MB (note that the value should always be specified in bytes, so the value in the example is 1,024,000 bytes). The default value is 30000000 bytes.
You can configure the local or remote folder paths where files used by FILE type parameters are located using the Input file allowed folders setting in the GraphQL section on the Configuration Panel Integration tab. (Alternately, you can add the folder names separated by commas to the GraphqlInputFileAllowedFolders parameter in the WorkflowGen web.config file.)
When using file uploads, you don't need to include the original file folder.
To disallow input file allowed folders, leave this field empty. To allow certain folders only, enter comma-separated values according to the table below:
Value
Description
Empty
No folders allowed
*
All folders allowed
c:\*
All folders on drive c:
c:\Inetpub\*
All subfolders in a specific folder
c:\Inetpub\folder*
All c:\Inetpub folders whose names start with folder
📌 Examples:
c:\Inetpub\folder1
c:\Inetpub\folder1\abc
c:\Inetpub\folder2
c:\Inetpub\folder2\abc\def
Specific folder only
Input file allowed HTTP URLs
You can configure allowed HTTP URLs for input files using the Input file allowed HTTP URLs setting in the GraphQL section on the Configuration Panel Integration tab.
To disallow file uploads using HTTP and/or HTTPS URLs, leave the field empty. To allow certain URLs only, enter comma-separated values according to the table below:
Value
Description
Empty
No HTTP or HTTPS URLs allowed
*
All HTTP and HTTPS URLs allowed
https://*
HTTPS URLs only
http://*
HTTP URLs only
http://mydomain/*
HTTP from a specific domain only
http://mydomain/folder/*
HTTP from a specific folder only
http://mydomain/folder*
All files and folders whose names start with folder
📌 Examples:
http://mydomain/folderfile.jpg
http://mydomain/folder/file.jpg
http://mydomain/folder2/file.jpg
http://mydomain/folder/file.jpg
Specific file only
Maximum input file size
In the GraphQL section on the Configuration Panel Integration tab, enter the maximum input file size in kilobytes in the Maximum input file size (kB) field.
Alternately, you can set the maximum input file content size in kilobytes as the value of the GraphqlMaxInputFileSize parameter in the WorkflowGen web.config file.
Maximum input file content size
When working with FILE type parameters content encoded in base64, you must enter the maximum input file content size in kilobytes in the Maximum input file content size (kB) field in the GraphQL section on the Integration tab in the Administration Module Configuration Panel.
Alternately, you can set the maximum input file content size in kilobytes as the value of the GraphqlMaxInputFileContentSize parameter in the WorkflowGen web.config file.
FILE type data content is only recommended for small files under 1 MB.
GraphQL API key
Add or define the following configuration parameters to the main \wfgen\web.config:
<add key="GraphqlApiKeyEnabled" value="N" />: Set to Y in order to enable the GraphQL API key feature.
<add key="GraphqlApiKey" value="[YOUR_API_KEY]" />: The value sent in the x-wfgen-graphql-api-key header must match this key. We recommend using a long and unique key string such as a GUID for example.
Performance tuning
WorkflowGen is installed with the following default GraphQL settings (located under iisnode in \wfgen\graphql\web.config):
The value of the nodeProcessCountPerApplication setting is set to 0 by default for the best performance in Node.js applications. This creates one node process based on the number of virtual processors that are configured. You can change this value at any time to a custom number of node processes; for example, nodeProcessCountPerApplication=2 will create two node processes independently of the number of virtual processors.
You can also optimize performance if needed by adjusting the maxConcurrentRequestsPerProcess value based on the number of potential concurrent users and requests.
Cross-origin resource sharing (CORS)
Add the cors node with the list of external domains and their methods and headers (where HTTP requests will be allowed) to the WorkflowGen web configuration settings (located in \wfgen\web.config). See some common examples below.
The following authentication methods are supported:
IIS Basic
WorkflowGen authentication
Custom .NET authentication modules
OpenID Connect
If your WorkflowGen site is configured with Integrated Windows or Basic authentication, you must configure GraphQL with Basic authentication.
HTTPS is required to secure credentials.
For OpenID Connect providers, you need to pass the access token as a bearer token in the Authorization header; for example, Authorization: Bearer <ACCESS TOKEN>(replace<ACCESS TOKEN> with your access token).
System access users
Some operations (such as UpdateRequestDataset) require users to have system access to perform the operations. This can be configured in the System operations allowed users field, under Security on the Configuration Panel Integration tab.
User impersonation
User impersonation is supported but not recommended, and should be used only when no other technical solutions are possible. (For example, OpenID Connect-based authentication methods allow you to use access tokens to perform API operations on the client and server sides without impersonation.)
System operations allowed users can impersonate another WorkflowGen user account by setting this account's username as the value of the x-wfgen-impersonate-username HTTP request header.
This request header can be renamed according to your naming convention. You can specify a new header name in the GraphqlImpersonateUserNameHttpHeader setting in the \wfgen\web.config file (e.g. <add key="GraphqlImpersonateUserNameHttpHeader" value="my-custom-impersonate-username" />).
Delegation mode
Some GraphQL queries and operations can be executed on behalf of another user. This is possible when a user has created a delegation in WorkflowGen. The delegatee has to specify the user ID of his delegator in the onBehalfOf argument.
List of actions to do on by the delegatee on behalf of the delegator with the user ID VXNlcjoy:
{
viewer {
actions(filter: {as: ASSIGNEE, status: OPEN}, onBehalfOf:"VXNlcjoy"}) {
totalCount
hasNextPage
hasPreviousPage
items {
request {
number
description
}
number
name
description
limit
launchUrl
}
}
}
}
When the onBehalfOf argument is set, it is propagated implicitly to the all the sub-queries and fields until a User type is used.
Global identifiers
Each GraphQL type has an id: ID! field. This ID is global and is unique for all WorkflowGen objects.
You can use the node(id:ID!) query to retrieve a WorkflowGen object by its ID.
{
node(id: "UHJvY2VzczoxNQ==") {
id
... on Request {
number
requester {
lastName
}
}
... on Action {
limit
assignee {
id
company
}
}
... on User {
userName
email
}
}
}
A parameter's array can be included in the createRequest operation payload. Be aware that a data with the same name and data type must previously exist in the process for each parameter in the array to store the parameter's value. The following example shows how to send parameters corresponding to the four supported data types (TEXT, NUMERIC, DATETIME, and FILE).
Request payload:
mutation {
createRequest(input: {processName: "SR", processVersion: 1, parameters: [{name: "TEXT", textValue: "My text parameter"}, {name: "NUMERIC", numericValue: 5}, {name: "DATE", dateTimeValue: "2017-02-23T20:46:00Z"}, {name: "FILE", fileValue: {name: "TestFile.txt", contentType: "text/plain", size: 616, url: "file:///c:/TestFile.txt", updatedAt: "2017-02-21T15:06:38Z"}}]}) {
request {
id
name
number
}
}
}
All of the actions with the same name in a request can be cancelled at the same time by using their name in this operation payload. The following conditions are met:
The viewer and the user (if they do not share the same identity, as in delegation mode) must have access to the request.
The action must be open.
The action must have a cancel or default exception defined in the transition.
The viewer is:
an administrator or a process folder manager
OR
a supervisor with cancellation rights
OR
the action assignee.
Request payload:
mutation {
cancelRequestActionsByName(input: {
requestNumber: 21,
activityName: "INITIATES"
}) {
action {
id
status
}
}
}
An interactive action (including data locks) can be started by using the StartInteractiveAction mutation. To perform this mutation, provide the either request number and the action number, the request number and the activity name, or the action ID.
The following conditions must be met:
The viewer and the user (if they don't share the same identity, as in delegation mode) must have access to the request.
The action must be open.
The action type must be human.
The user must have the rights to to complete the action.
Request payload:
mutation {
startInteractiveAction(input: {requestNumber: 73, number: 2}) {
action {
status
subStatus
interactiveParameters {
totalCount
items {
name
direction
hasValue
type
textValue
numericValue
dateTimeValue
fileValue {
url
blobUrl
name
}
}
}
}
}
}
An array of interactive parameters is required to complete the action; it can be returned by using the action.interactiveParameters query.
This code will create a favorite using the process or view description, but adding a custom description is also possible, as shown in the following example:
Request payload:
mutation {
createFavorite(input: {
itemId: "UHJvY2Vzczoy",
description: "My custom description"
}) {
favorite {
id
type
description
}
}
}
Users can update comments if they are administrators, process manager of the process or process supervisor, or standard users who are members of the process participants, have write permissions, and are the comment author.
Request payload:
mutation {
updateComment(input: {
id: "Q29tbWVudDoyMi0tLTE=",
message: "This is my updated message"
}) {
comment {
message
}
}
}
Response payload:
{
"data": {
"updateComment": {
"comment": {
"message": "This is my updated message"
}
}
}
}
This mutation requires that the portal delegation feature be enabled. Standard users can only create delegations for themselves; only administrators can create a delegation for another user.
This mutation requires that the portal delegation feature be enabled. Standard users can only update delegations for themselves; only administrators can update a delegation for another user.
This mutation requires that the portal delegation feature be enabled. Standard users can only delete their own delegations; only administrators can delete another user's delegations.
Process mutations are available as of WorkflowGen version 7.16.0. They can only be performed by administrators or process folder managers of the folder where the process is located.
Create a process
The createProcess mutation creates a process from the process properties. The process name, description, state, and folder identifier or name are required.
Request payload:
mutation {
createProcess(input: {
name: "My new process",
description: "my new process",
folderName: "DEFAULT"
}) {
process {
id
name
version
description
state
folder {
name
}
isSubProcess
isBuiltInForm
isActionDataArchived
isDatabaseStorageForFiles
accessLevel
updatedAt
updatedBy {
userName
}
}
}
}
mutation {
createGlobalParticipant(input: {
name: "My global participant",
description: "My global participant description",
type: COORDINATOR,
userIds: ["VXNlcjox", "VXNlcjoy"],
groupIds: ["R3JvdXA6MQ=="],
directoryIds: ["RGlyZWN0b3J5OjE="],
coordinatorIds: ["VXNlcjoy"]
}) {
globalParticipant {
id
name
description
type
}
}
}
mutation {
createLocalProcessParticipant(input: {
name: "My local process participant",
description: "My local process participant description",
type: COORDINATOR,
userIds: ["VXNlcjox", "VXNlcjoy"],
groupIds: ["R3JvdXA6MQ=="],
directoryIds: ["RGlyZWN0b3J5OjE="],
coordinatorIds: ["VXNlcjoy"],
processId: "UHJvY2Vzczoy"
}) {
localProcessParticipant {
id
name
description
type
}
}
}
Response payload:
{
"data": {
"createLocalProcessParticipant": {
"localProcessParticipant": {
"id": "TG9jYWxQcm9jZXNzUGFydGljaXBhbnQ6MTI=",
"name": "MY_LOCAL_PROCESS_PARTICIPANT",
"description": "My local process participant description",
"type": "COORDINATOR"
}
}
}
}
Update a local process participant
Request payload:
mutation {
updateLocalProcessParticipant(input: {
id: "TG9jYWxQcm9jZXNzUGFydGljaXBhbnQ6MTI=",
name: "My local process participant",
description: "My local process participant description",
type: COORDINATOR,
userIds: ["VXNlcjox", "VXNlcjoy"],
groupIds: ["R3JvdXA6MQ=="],
directoryIds: ["RGlyZWN0b3J5OjE="],
coordinatorIds: ["VXNlcjoy"]
}) {
localProcessParticipant {
id
name
description
type
}
}
}
Response payload:
{
"data": {
"updateLocalProcessParticipant": {
"localProcessParticipant": {
"id": "TG9jYWxQcm9jZXNzUGFydGljaXBhbnQ6MTI=",
"name": "MY_LOCAL_PROCESS_PARTICIPANT",
"description": "My local process participant description",
"type": "COORDINATOR"
}
}
}
}
Global list mutations are available as of WorkflowGen version 7.17.0. They all can only be performed by administrators. A global list manager can only update a global list from an XML definition.
Create a global list
The createGlobalList mutation creates a global list from the global list's properties. If no input argument is provided, the global list is created with the default values.
Request payload:
mutation {
createGlobalList(input: {}) {
globalList {
id
name
manager {
id
}
connectionName
connectionString
providerName
selectCommand
}
}
}
Response payload:
{
"data": {
"createGlobalList": {
"globalList": {
"id": "R2xvYmFsTGlzdDoxMw==",
"name": "My new list 13",
"manager": null,
"connectionName": null,
"connectionString": null,
"providerName": null,
"selectCommand": null
}
}
}
}
The CreateGlobalList mutation can also be used to duplicate a global list by passing the fromGlobalListId property in the arguments:
Request payload:
mutation {
createGlobalList(input: {
fromGlobalListId:"R2xvYmFsTGlzdDoxMw=="
}) {
globalList {
id
name
manager {
id
}
connectionName
connectionString
providerName
selectCommand
}
}
}
Global list creation and update operations support databinding connections to get the list items. Two databinding modes are available: connection name and connection string.
Request payload (connection name mode):
mutation {
createGlobalList(input: {
connectionName: "MainDbSource",
selectCommand: "Select ID_USER,FIRSTNAME from USERS"
}) {
globalList {
id
name
manager {
id
}
connectionName
connectionString
providerName
selectCommand
}
}
}
Response payload (connection name mode):
{
"data": {
"createGlobalList": {
"globalList": {
"id": "R2xvYmFsTGlzdDoxNg==",
"name": "My new list 14",
"manager": null,
"connectionName": "MainDbSource",
"connectionString": null,
"providerName": null,
"selectCommand": "Select ID_USER,FIRSTNAME from USERS"
}
}
}
}
Request payload (connection string mode):
mutation {
createGlobalList(input: {
connectionString: "Data Source=localhost;Initial Catalog=MY_DB;User ID=MY_USER;Password=MyPass$;",
selectCommand: "Select * from USERS",
providerName: SYSTEM_DATA_SQLCLIENT
}) {
globalList {
id
name
manager {
id
}
connectionName
connectionString
providerName
selectCommand
}
}
}
Response payload (connection string mode):
{
"data": {
"createGlobalList": {
"globalList": {
"id": "R2xvYmFsTGlzdDoxNw==",
"name": "My new list 15",
"manager": null,
"connectionName": null,
"connectionString": "Data Source=localhost;Initial Catalog=MY_DB;User ID=MY_USER;Password=MyPass$;",
"providerName": "SYSTEM_DATA_SQLCLIENT",
"selectCommand": "Select * from USERS"
}
}
}
}
Update a global list
The updateGlobalList mutation updates a global list's properties from the global list identifier.
Request payload:
mutation {
updateGlobalList(input: {
id:"R2xvYmFsTGlzdDoxMw==",
name: "updated name"
}) {
globalList {
id
name
manager {
id
}
connectionName
connectionString
providerName
selectCommand
}
}
}
As of WorkflowGen version 7.12.0, file data can be downloaded using a blob URL that is returned in the process, request or action datasets, respectively.
As of version 7.2.0, GraphQL supports the fileValue.updatedAt, fileValue.content, and fileValue.url fields when sending FILE parameters (as shown in the previous example).
The fileValue.updatedAt field should use the ISO 8601 date format.
The maximum number of uploads in the same request is 30.
The maximum file upload size is set in the GraphqlMaxInputFileSize configuration parameter.
The multipart/form-data content type is only supported for HTTP requests with file uploads. If the fileValue.name, fileValue.description, and fileValue.contentType properties are not defined, they will be set from the uploaded file information; otherwise, they will take the values defined the payload.
viewerAsMember field usage
The viewerAsMember field is a Boolean parameter that determines if the viewer has standard user access scope, even if they have an administrator or a process folder manager profile. It can be used by the user(userName:"XXX").requests, user(userName:"XXX").comments, and user(userName:"XXX").actions queries when an administrator or a process folder manager tries to access another user's requests, comments, or actions with a standard user scope.
In the following payload example, an administrator would be able to access Jane Doe's requests, comments, and actions with a standard user access scope:
{
user(userName: "jane_doe") {
requests(viewerAsMember: true) {
totalCount
hasPreviousPage
hasNextPage
items {
id
number
}
}
actions(viewerAsMember: true) {
totalCount
hasPreviousPage
hasNextPage
items {
id
number
request {
number
}
}
}
comments(viewerAsMember: true) {
totalCount
hasPreviousPage
hasNextPage
items {
id
subject {
id
}
message
author {
id
}
}
}
}
}
Logs
All HTTP queries are logged by IIS as other ASP.NET web apps. Node.js application logs are available in the \wfgen\graphql\iisnode\ folder. You can adjust the iisnode log file management in the \wfgen\graphql\web.config file.
Debug mode
A debug mode can be enabled by setting the GraphqlDebugEnabled key to Y in the \wfgen\web.config file.
In debug mode, some extensions are added to the GraphQL response, and additional error messages are logged in the \wfgen\graphql\iisnode\ folder.
GraphQL desktop client
If you're using Windows authentication for GraphQL, you can install Altair as a browser extension. No header is required.
For information on the installation procedure, see the .
is used to serve GraphQL HTTP queries:
You can use , a graphical interactive in-browser GraphQL IDE, to test queries and operations, and to browse the schema documentation.
As of version 8.1.3, if your WorkflowGen and GraphQL API are secured using the WorkflowGen applicative or OpenID Connect authentications, you can alternatively access the GraphQL schema (i.e. /wfgen/graphql/schema) and the queries using a GraphQL API key header (x-wfgen-graphql-api-key) defined in the HTTP request, without an authentication header.
For more information, see the Microsoft article.
In order to allow a client application (such as front-end JavaScript code from an outside domain) to access and request data from the API, you must enable and configure the settings in the WorkflowGen GraphQL API module. To do this:
Install the on the WorkflowGen web server.
For more information about the CORS configuration, see the .
The GraphQL Node.js app code inside the \wfgen\graphql folder can also be customized to accommodate many other authentication methods (such as OAuth2, JWT, etc.) thanks to node libraries such as .
To give or withdraw system operations rights to or from specific users, refer to the setting in the Security section on the Configuration Panel General tab; alternately, you can edit the ProcessesRuntimeWebServiceAllowedUsers setting in the \wfgen\web.config file.
You can copy/paste these queries directly in the GraphiQL IDE. See the section above for more information.
To create a new request from the GraphQL API, make sure that sub-process mode is enabled with public access on the target process. (See the section in the for more information.)
For more information on FILE parameter manipulations when sent within GraphQL payloads, see the section.
A process can be created from its XPDL definition. The XPDL file (in .xml format) is uploaded by using the GraphQL feature as shown below.
A process can be updated from its XPDL definition. The XPDL file (in .xml format) is uploaded by using the GraphQL feature as shown below.
A global list can be created from its XML definition. The .xml file is uploaded by using the GraphQL feature as shown below.
A global list can be updated from its XML definition. The .xml file is uploaded by using the GraphQL feature as shown below.
The fileValue.content field should contain the file content encoded in base64. In this case, the fileValue.url field is not required. You must set the maximum input file content size (see the section above for instructions on how to set these).
The fileValue.url field contains the file URL. When working with FILE parameters, you must set the input file allowed folders and the maximum input file size (see the section above for instructions on how to set these).
You can also prevent file uploads using HTTP and/or HTTPS URLs setting the Input file allowed HTTP URLs in the GraphQL section on the Integration tab in the Administration Module Configuration Panel (see in the WorkflowGen Administration Guide).
If you need to work in GraphQL without an internet connection, you can use the for offline access.
If you're using Basic authentication for GraphQL, download the application from , then set the Authorization header.