Workflows

Workflows (also called Onify Flow) are BPMN processes that be initiated either via a form, schedule or via API. A workflow can also be a presentation of a specific workflow or process from an process, external system or a script. This gives the user a clear view of where the process is. The process state and status can then be updated via API or the BPMN process.

Introduction

Workflows one of the ways to do automation in Onify. Workflows are a declaration of a workflow and when you start a workflow, this will create a process. It is then the process you interact with for managing state and status. A workflow can also be scheduled in the BPMN diagram.

A workflow can also be a declaration of a external workflow and can in this case be used to inform the user about the current process.

Creating new workflow

You can either create a workflow via the admin interface, via Camunda Modeler or via the API. If you deploy or run a BPMN diagram via the Camunda modeler, some of the below parameters are automatically set.

  • key - Unique key (id) for the workflow
  • name - Name of the workflow
  • description - Description (external) for workflow
  • bpmnresource - The BPMN resource to be used (see Onify Flow)
  • icon - Icon for workflow
  • tag - Tag(s) for workflow
  • owner - Who is the owner of this workflow/process. This is only used for information purpose
  • role - Role(s) that have access to start workflow. If not set, every logged in user can start this workflow.
  • domain - Domains that have access to workflow (if multi-tenant is enabled). If not set, all users in all domains have access.
  • state - States are a declaration of the different states (milestones) of a workflow/process. These can either be manually created when you create the workflow or set in the BPMN process.
  • state.order - Order of the state
  • state.id - The unique id of the state
  • state.name - The name of the state
  • state.description - The description of the state
  • state.required -
  • meta - Metadata for the workflow. This could be used for eg. cost savings or other data related to the workflow/process.

Running a workflow

If the workflow is associated to a BPMN resource (Onify Flow) the process can either be started via admin interface, via Camunda Modeler or via the API.

A workflow can also be scheduled and this must be defined within the BPMN diagram.

When you start a workflow, a process is created and this holds all information about the current running process.

Process state

When you have a process running you have the ability to both add new states or update a state. The purpose of state is to show and visualize the user where in the process it is.

However, if the process is running a flow (BPMN), updating the state can also have a impact of signaling a activity, eg. a user task.

You can update process state via flow or via API.

Note: For more information about state and how to manipulate it, see Process state under Building flows.

Process status

The status is something that is set for the entire process, not for a specific state.
Here are the different statuses that can be set:

  • continue - To continue the process
  • complete - The process should be considered completed with success
  • pause - The processes should be considered to be paused
  • stop - The processes should be considered to be stopped

To mark something to be wrong, set error to true.

Note: For more information about state and how to manipulate it, see Process status under Building flows.

Forms

Forms are a great way to interact with a workflow and/or flow (BPMN).

Starting workflow using form

In the form configuration (process.*) we can start a process based on the selected workflow:

  • workflow - The workflow to be started
  • title - Title to set to the process. Supports Handlebars
  • description - Description to set to the process. Supports Handlebars
  • action - Actions to be made visible for the user in "Your processes" view (not implemented yet)
  • action.id - Unique id for the action
  • action.name - Name for the action
  • action.url - Url for the action
  • action.status - In what process status will this action be visible?

Here are some examples on how to set title and description using handlebars.

{
  "workflow": "onboarding",
  "title": "Employee Onboarding",
  "description": "Onboarding for {{submit.firstname}} {{submit.lastname}}"
}
{
  "workflow": "request-services",
  "title": "Request services by {{user.name}}",
  "description": "Requested {{#csv form.items}}{{name}}{{/csv}}"
}

Signaling process using form

If you are using flow, you can signal a process activity by sending processid and stateid in the queryparams when opening the flow, eg. ./form/<SLUG>?processid=<PROCESSID>&stateid=<ACTIVITYID>.

This will signal flow to continue the process if stateid is set on any of these element types:

  • Receive Task
  • User Task
  • Manual Task
  • Message Intermediate Catch Event
  • Signal Intermediate Catch Event

When signaling the activity, data from the form will be added to the output of that activity, eg. content.output.*. The data that will be available are example:

  • user.* - The user object like, name, mail, etc
  • form.* - Information about the form that is sending the data
  • form.queryparam.* - Query parameters from the form
  • form.submit.item.* - Submitted items (eg. {{form.submit.item.manager.[0].key}})
  • form.submit.option.* - Submitted options (eg. {{form.submit.option.memory.[0].key}})
  • submit.* - Submitted data from the form, eg. field values

For more information about

Onify Flow

Onify flow is based on the open source workflow engine bpmn-engine.

Requirements

  • Camunda Modeler version 5.0 or later
  • Onify Hub API version 2.2.0 or later

BPMN modeler

You can draw BPMN diagrams in many different products but Onify best supports the Camunda Modeler. We both support drawing the diagrams and also deploying and running diagram directly in the modeler.

Learn more about BPMN

Here is a great post how to get started with BPMN. Good luck ;-)

Building flows

Timers

Onify flow supports timers, i.e. TimerEventDefinition's with one addition. Onify also supports time cycle using cron.

timeDuration

Suitable for activity timeouts. Duration is defined using ISO8601 duration

timeCycle

Suitable for scheduled flows. Cycle is defined using cron.

timeDate

Suitable for scheduled flows. Date should be set using new Date() or in ISO format.

Input/Output

When modelling a flow for Onify it is possible to define activity Input/Output parameters. Onify has some special handling of the content of that.

  1. If a parameter with the same name appears the parameter will be overwritten with the new value
  2. If a Map is used the Map will be converted into an object
  3. If a Map contains fields with the same name the field will be converted into an Array and the values will be pushed
Expressions

Input/output parameters can be set using expressions. The bpmn-engine has built in expression handling that is documented here.

Tip! Since all parameter values are treated as strings, typed booleans and numbers can defined using: ${true}, ${false}, or ${1234}.

Input parameters

Input parameters will be available under content.input.

Process state

If a state input parameter is defined it will be mapped as process state. States can be one or many. The input parameter can be either a Map or a script returning an object.

Example Map:

field nametypedescription
idstringexample: state-1
name(optional) stringexample: My first state
order(optional) integerdisplay order
description(optional) stringdescription
user (optional) arrayallowed user
role (optional) arrayallowed roles
Output parameters

Input parameters will be available under content.output.

Process state

If a state output parameter is defined it will be mapped as process state. States can be one or many. The output parameter can be either a Map or a script returning an object.

A script can be preferred since a complex object can be set:

next(null, {
  id: 'state-1',
  result: {
    done: true,
    error: false,
    skipped: false, 
    timestamp: new Date(), // defaults to current date/time if not set
    statuscode: 200, // defaults to 200 if not an error
    statusmessage: 'OK',
    link: '/', 
    link_text: 'Back to root',
    user: 'username' // defaults to current user if not set,
    meta: {} // se example below
  }
});

Not all properties of result has to be used

The meta field can be used to set custom fields, here is example code:

next(null, {
  id: content.id,
  result: {
    done: true,
    meta: {
      elapsed_time_for_this_step: elapsedTimeForThisStep
    },
  }
});

NB! It is not recommended to update state for the current running process via API. This can cause conflicts. If you want to set state for the current process, always do it in flow via state input/output.

Process status

Input/Output can also be used to manipulate process status using a parameter named status. The status can contain the following properties:

Example Map:

field nametypedescription
statuskey(optional) stringcan be one of start, continue, complete, pause, or stop
statuscode(optional) integerHTTP status code
statusmessage(optional) stringStatus message
error(optional) booleanhas the process errored
data(optional) objectobject with additional data

NB! The status should only be set at the end of a process, typically in an end event. Setting the status at any other stage in the process flow may lead to unexpected behavior, especially concerning the statuskey.

ServiceTasks

The name is also the same name you use as Connector Id in the Camunda modeler. First, select Connector as Implementation in the service task. Arguments can then be used as input parameters.

onifyApiRequest(options[, callback])

Make an Onify API request with the user currently running the flow.

Arguments:

  • options: a string with the requested URI, or an object with:
    • url: (required) the request URL, accepts relative api URL e.g. /my/settings without api version
    • query: (optional) optional object containing search parameters. Will be stringified using node.js built in function querystring.stringify
    • method: (optional) the request HTTP method (e.g. POST). Defaults to GET
    • headers: (optional) an object with optional request headers where each key is the header name and the value is the header content
      • authorization: (optional) override authorization
    • throwHttpErrors: (optional) boolean indicating that non 200 responses will throw an error, defaults to true
    • payload: (optional) a string, buffer or object containing the request payload

Returns:

  • statusCode: the HTTP status code
  • statusMessage: the HTTP status message
  • headers: an object containing the headers set
  • payload: the response raw payload
  • body: response body, parsed as JSON
onifyElevatedApiRequest(options[, callback])

Same as onifyApiRequest but with admin privilegies.

httpRequest(options[, callback])

Make an external HTTP request. The request library used is npm module got.

Arguments:

  • options: required object passed to got:
    • url: (required) the request URL
    • query: (optional) optional object containing search parameters. Will be stringified using node.js built in function querystring.stringify
    • method: (optional) the request HTTP method (e.g. POST). Defaults to GET
    • headers: (optional) an object with optional request headers where each key is the header name and the value is the header content
      • authorization: (optional) override authorization
    • throwHttpErrors: (optional) boolean indicating that non 200 responses will throw an error, defaults to true
    • payload: (optional) a string, buffer or object containing the request payload

Returns:

  • statusCode: the HTTP status code
  • statusMessage: the HTTP status message
  • headers: an object containing the headers set
  • body: response body

Signal Process Activity via API

This feature (requires API version 2.30+) enables signaling a process to continue from a paused or waiting activity by sending a custom payload.

The process can be signaled when it is waiting for any of the following activities:

  • Receive Task
  • User Task
  • Manual Task
  • Message Intermediate Catch Event
  • Signal Intermediate Catch Event
Signal Activity (User)

Endpoint: PUT /api/v2/my/processes/{id}/signal/{activity}

Description: Signal a specific activity within a user's process to proceed.

Path Parameters:

  • id (string, required): The unique identifier of the process.
  • activity (string, required): The activity identifier to signal.

Request Body: (object, optional)

  • An arbitrary JSON payload relevant to the process or the activity.

Headers:

  • Authorization (required): Bearer token.

Example cURL Request:

curl -X PUT "http://0.0.0.0:8181/api/v2/my/processes/1234/signal/userTask1" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "inputData": "value",
    "userAction": "approve"
  }'
Signal Activity (Admin)

Endpoint: PUT /api/v2/admin/processes/{id}/signal/{activity}

Description: Signal a specific activity within an administrative process to proceed.

Path Parameters:

  • id (string, required): The unique identifier of the process.
  • activity (string, required): The activity identifier to signal.

Request Body: (object, optional)

  • An arbitrary JSON payload relevant to the process or the activity.

Headers:

  • Authorization (required): Bearer token.

Example cURL Request:

curl -X PUT "http://0.0.0.0:8181/api/v2/admin/processes/5678/signal/messageCatchEvent1" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "messageContent": "data",
    "triggerReason": "externalSignal"
  }'

JavaScript

Onify flow supports javascript in a ScriptTask, as SequenceFlow condition, or in Input/Output parameters.

NB! The flow execution stalls until next has to be called for the flow to continue.

NB! All scripts timeout after 60 seconds (unless you use async functionality). So keep them short and simple. You can also override the script timeout by setting extension property scriptTimeout (in milliseconds), eg. ${120000}.

Global context

Since script will be sandboxed they have some specific global properties and functions that can be addressed directly or under this.

When in doubt on where to find your information insert this script:

console.log(this);
next();
fields

Object with information regarding the message that executed activity.

content

Object with information of the current running activity.

Here you can find input and/or output that was defined for the activity execution.

properties

Object with properties of the message that executed activity.

environment

Flow execution environment.

contextName

Name of running flow.

next(err, result)

Must be called when script is completed.

Buffer.from(...args)

Node.js function Buffer.from.

Useful for encoding and decoding Base64.

Encode as base64

Example:

Buffer.from('Hello world').toString('base64');

Decode base64

Example:

Buffer.from('SGVsbG8gd29ybGQ=', 'base64').toString();
console.log(...args)

Basic javascript console.log('Hello world'). Write something on stdout. Will end up in console or in a container log.

decrypt(encryptedText, encoding = 'hex')

Decrypt an encrypted text with defined Onify client secret.

encrypt(text, encoding = 'hex')

Encrypt text with defined Onify client secret.

jwt.sign(...)

Create a signed JWT using npm module jsonwebtoken sign function.

jwt.verify(...)

Verify a signed JWT using npm module jsonwebtoken verify function.

Cleaning Up Process Instances Using History TTL

Starting from API version 2.30, it is possible to configure when process instances should be removed, streamlining workflow maintenance and keeping your process history manageable. The History Time-to-Live (TTL) setting allows you to define the retention period for completed process instances on a per-workflow basis.

The History TTL specifies how long completed process instances should remain in the database. You can configure this as either a specific date or a duration using the ISO 8601 format. Additionally, the TTL can be dynamically set using variables and logic to adapt to different workflows and business rules. The cleanup operation is executed once per day, and instances exceeding the TTL value are automatically removed during this routine task.

If no TTL is specified for a workflow, the process instances will remain indefinitely, ensuring that historical data is not deleted unless explicitly configured.

Configuration

The History TTL can be configured directly in the BPMN modeler. You can set this value per workflow to customize the retention period for each workflow. The TTL can be defined as either:

  • A specific date (e.g., 2024-12-31T23:59:59Z).
  • A duration in ISO 8601 format (e.g., P30D for 30 days).
  • A dynamic value using workflow variables and logic to calculate the TTL based on the process context (e.g. ${calculatedTTL}).

By setting an appropriate TTL, you can ensure that your process history is efficiently managed, reducing database clutter and improving performance. If indefinite retention is desired, simply leave the TTL unset.

Screenshots

Your processes

1732

A view of all your processes including state and status.

BPMN 2.0 diagram

3484

A BPMN 2.0 diagram example of a approval process.

Blueprints

To more easily get started. Have a look at our Blueprints for Flow on GitHub.

API endpoints

Workflow API endpoints

Here you can find out more information about the different API endpoints for workflows.

Process API endpoints

Here you can find out more information about the different API endpoints for running processes.