Skip to main content
Version: 10.3

WorkFusion REST API

The WorkFusion API lets you launch, post data to, and receive results from the WorkFusion platform automatically. Using it, you can manage simple tasks and more complex Business Processes (BPs) representing a workflow of various manual and automated tasks.

info

The complete collection of WorkFusion REST API endpoints is available in WorkFusion's Swagger specification. For instructions on accessing the specification, see the Swagger configuration guide.

API security​

All API postings are made over a Secure Sockets Layer (SSL) connection encrypting communications between the user and web server to ensure data privacy.

note

All requests must be preceded by https://.

Form-based authentication​

WorkFusion REST API uses form-based (login and password) authentication to ensure that APIs are only accessible to users with proper credentials.

Note that to make a REST call, you need to add a CSRF token to the request header for protection.

  1. Before executing REST API requests, log in using the form URL and the POST method as shown below:

    POST /workfusion/api/dologin
    Content-Type: application/x-www-form-urlencoded
    j_username=usernamej_password=password

    where:

    • j_username is your username in Control Tower.
    • j_password is your password in Control Tower.

    A successful response from the server looks like this:

    {
    "success": true,
    "csrfToken": <csrftoken>,
    "csrfHeaderName": <csrftokenname>
    }
  2. Get JSESSIONID from the Set-Cookie response header.

  3. Create a REST API request:

    1. Set the acquired JSESSIONID to the Cookie header.
    2. Set application/x-www-form-urlencoded as the Content-Type header.
    3. Set the received <csrftoken> as the <csrftokenname> header.

Below is a sample login request in Postman:

Sample login with HttpClient
package org.example;

import com.google.gson.Gson;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.AbstractHttpEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

//Not a production-grade implementation use as an example only
public class ApiLogin {

public static final String USERNAME = "ct_user_name";
public static final String PASSWORD = "ct_user_password";
public static final String LOGIN_URL = "https://instance.workfusion.com/workfusion/api/dologin";

public static void main(String... args) throws IOException {
String token = new ApiLogin().login();
System.out.println("Auth token: " + token);
}

public String post(String addressURL, AbstractHttpEntity body, String csrfToken) throws IOException {

HttpPost httpPost = new HttpPost(addressURL);
System.out.println("POST -> " + addressURL);
httpPost.setEntity(body);
// add token if necessary
if (!StringUtils.isEmpty(csrfToken)) {
httpPost.addHeader("X-CSRF-TOKEN",csrfToken);
httpPost.getParams().setParameter("_csrf",csrfToken);
}
HttpClient httpClient = HttpClients.createDefault();
HttpResponse response = httpClient.execute(httpPost);

//Read the Set-Cookie header from the response
String cookies = response.getHeaders("Set-Cookie")[0].getValue();
System.out.println("Set-Cookie header: " + cookies);

String stringResponse = convertStreamToString(response.getEntity().getContent());
System.out.println(stringResponse);

return stringResponse;
}


public String login() throws IOException {

List<NameValuePair> nvp = new ArrayList<>();
nvp.add(new BasicNameValuePair("j_username", USERNAME));
nvp.add(new BasicNameValuePair("j_password", PASSWORD));

//post the username and password to the server to log in
//re-use the httpClient instance to make sure the same JSESSIONID cookie is used

//UrlEncodedFormEntity sets Content-Type=application/x-www-form-urlencoded
// no token is required for login
String loginResponse = post(LOGIN_URL, new UrlEncodedFormEntity(nvp),"");

Map jsonResponse = new Gson().fromJson(loginResponse, Map.class);

String csrfToken = (String) jsonResponse.get("csrfToken");

String csrfHeader = (String) jsonResponse.get("csrfHeaderName");
return csrfToken;
// then use csrfHeader and csrfToken for REST API calls, return it.

}

private String convertStreamToString(InputStream is) {
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
}

Use REST API with SSO​

You can authenticate REST requests with Keycloak credentials without making Control Tower changes. For more information on Single Sign-On (SSO), read the following topics:

info

To authenticate REST requests with API credentials, you must have a password assigned for your user. This condition is mandatory because, when using SSO, a user appears in Keycloak only after their first login via the interface, while Keycloak won't have the user's password.

Use REST API with LDAP​

LDAP access is configured via Keycloak. So, you can authenticate REST requests with your Keycloak credentials. For more information, read the Configure LDAP topic.

URLs​

All URLs begin with the following pattern:

https://%HOSTNAME%/workfusion/api/

Obtain end-user IP address​

To obtain a real end-user IP address, do as follows:

  1. Add the following snippet to nginx/sites/workfusion.com on each Master server:

    location /echo {
    default_type text/plain;
    return 200 '{"X-Forwarded-For": "$http_x_forwarded_for"}';
    }
  2. Restart Nginx:

    wfmanager restart nginx
  3. Enable the Proxy Protocol on HAProxy by changing group_vars/all/vars.yml. Set the use_proxy_protocol variable to true:

    # use proxy protocol for forwarding user ip
    use_proxy_protocol: true
  4. To reconfigure HAProxy, run the following command on the Master server:

    ./install.sh configure haproxy

The Proxy Protocol should be enabled on Load Balancer and used to carry connection information from the source requesting a connection. For more details, refer to Enable Proxy Protocol on F5.

Sample output is as follows:

[wfuser@ip-10-100-9-111 ~]$ curl https://<hostname>/echo
{"X-Forwarded-For": "10.100.9.111"}

UUID​

Each operation, such as a task or a Business Process, has a unique identifier (UUID). It is used as a unique reference to invoke the WorkFusion API and identify those entities. Sample UUID: db1cf0a8-1be4-4842-aec9-4ab0196bc9f1.

Once you receive the required UUID, you can use it to manage BPs via API, for example:

  • To get JSON with detailed information on a specific BP, such as status, executor, and so on, send a POST request to the following endpoint: https://HOSTNAME/workfusion/api/v2/bp-instances/BP_UUID?scope=STRUCTURE&scope=BP_DETAILS&scope=CHILDREN_DETAILS.
  • To receive snapshots for a specific BP, send a POST request to the following endpoint: https://HOSTNAME/workfusion/api/v2/bp-instances/BP_UUID/snapshots/final?lastSnapshotCount=50.
  • To receive a CSV file with BP results, send a POST request to the following endpoint: https://HOSTNAME/workfusion/api/v2/snapshots/BP_UUID.

Obtain Business Process UUID​

To obtain a Business Process UUID, follow the steps below:

  1. In Control Tower, go to the Business Process list.

  2. Click the button to open the BP definition in a new tab and locate the UUID as shown in the image below.

Document processing use case​

The section below describes how you can leverage WorkFusion API REST endpoints to implement a document processing automation covering the following operations:

The diagram below is a graphical representation of a document processing flow implemented with REST API endpoints:

Get data files for screening​

Input data is a file with the customer data used in your automation. You can deliver input data from a file storage, such as:

  • S3 Manager within Work.AI

  • Any file storage outside Work.AI

File storage outside of Work.AI​

A customer's server can host data files. However, WorkFusion Work.AI needs to access the files via traditionally accepted methods—S3 Object Storage, HTTP, FTP.

S3 Object Storage​

When using S3 Object Storage, WorkFusion Work.AI can access stored files with the credentials provided by the user in the following format:

Access key: HHVDVFJFT3GHHJKJ43FG
Secret Key: KNJkljJHGJHgjhJGHKjgy666RryfrftFk6589890
HTTP​

In case of HTTP links, WorkFusion Work.AI can access stored files with the credentials provided by the user in the following format:

  • Username and password authentication:

    headers: {
    username: USERNAME,
    password: PASSWORD
    }
  • Secret key in the HTTP headers:

    headers: {
    secret-key: secretKey
    }
  • Secret key specified as get-parameter in the link to the file:

    https://client_domain.com/media_check_input_data/file1.xlsx?key=JKJH778sdfusdf678f678dfs78s^yjhhjwdkl754
  • HMAC-based one-time password:

    API_KEY = c3b290df-d560-493c-86ca-0ab552f24490a
    SECRET = 06d9BLvnPwpj/DFKJ6iGb5oiFO7wZK+dl+C9aflIu/9DIXMXqEyR0Qi1y5BjFi8NcSJl4b62vpK9v3JB1223339g==

    headers: {
    authorisation: Signature keyId="${API_KEY}",algorithm="hmac-sha256",headers="(request-target) host date",signature="${HMAC_GENERATED_SIGNATURE_VIA_SECRET}"
    }
FTP​

When you use an FTP server for storing input files, WorkFusion Work.AI downloads these files with the following credentials provided by the user:

Protocol: FTP / SFTP
Port: 21
host: ftp://client_domain.com
remote root: /www/media_check_input_data/
username: USERNAME
password: PASSWORD

Start Business Process​

Once logged in, call the WorkFusion REST API to start the Business Process by passing a link to the input file with associated entities for screening.

  • Method: POST

  • URL: https://HOSTNAME/workfusion/api/v2/workfusion/task/file

  • Required headers:

  • Body

    {
    "campaignUuid" : "UUID of the Combined UC Campaign",
    "mainData" : ".csv file in the text representation."
    }

    // An example of building mainData string
    var main_data_example = "wf_screening_input\n" + // name of the column
    "file_s3_path_1\n" +
    "file_s3_path_2";

    var mainData = JSON.stringify(main_data_example ));
  • Response

    When the API call returns a UUID, it indicates a successful start of the Business Process with the provided input file.

Below is a Postman configuration example for the API endpoint to start a BP:

Check BP status​

Once the Business Process is started, it is necessary to continually check its status. It is recommended to ping the endpoint using the following structure every 3-5 minutes based on the expected execution duration:

  • Method: GET

  • URL: https://HOSTNAME/workfusion/api/v2/workfusion/task/{uuid}/steps

  • Requiered headers:

  • Response: an array of JSON objects that represents each step of the started BP

    [
    {
    "title": "Step 1",
    "stepIndex": 1,
    "runUuid": "uuid",
    "runStatus": "COMPLETED",
    "campaignUuid": "uuid",
    "type": "MACHINE",
    "finalStep": false,
    "stepPosition": "START",
    "componentUuid": "uuid",
    "versionUuid": "uuid"
    },
    ...,
    {
    "title": "Step 5",
    "stepIndex": 5,
    "runUuid": "uuid",
    "runStatus": "COMPLETED",
    "campaignUuid": "uuid",
    "type": "MACHINE",
    "finalStep": true,
    "stepPosition": "END",
    "componentUuid": "uuid",
    "versionUuid": "uuid"
    }
    ]

The Business Process indicates the completion when the final step has been reached with the completed status.

"finalStep": true
"runStatus": "COMPLETED"

If you receive runStatus: null in a response, this means the Business Process failed with an error, and additional investigation is needed. To investigate, log in to Control Tower and check the logs.

For investigation tips, see the support guides:

Check BP results​

At the end of execution, the BP saves the updated files to the S3 Manager application at https://HOSTNAME-s3-ui.cloud.workfusion.com and generates a final report with temporary links to these files. You can retrieve the report via API as described below.

  • Method: GET

  • URL: https://HOSTNAME/workfusion/api/v2/workfusion/task/{uuid}/snapshot/CSV

  • Headers required:

  • Response: a binary object that can be converted into an Excel table or a CSV file

    {
    "content": "...",
    "contentType": "text/csv"
    }

    // An example how you can do it in JS
    function retrieveSnapshot(processUuid) {
    retriveSnapshotUrl= instanceBaseUrl + "/api/v2/workfusion/task/{uuid}/snapshot/CSV";
    var startProcessPromise = $.ajax({
    type: "GET",
    url: retriveSnapshotUrl.replace("{uuid}", processUuid),
    contentType: 'text',
    headers: {...},
    dataType: 'text',
    cache:false,
    async: true
    });
    startProcessPromise.then(snapshotRetrieveSuccess, snapshotRetrieveError);
    };

    function snapshotRetrieveSuccess (response){
    var decodedResponseString = atob(JSON.parse(response).content);
    };

The resulting file contains links to the initial files updated with the resolutions and justifications for acceptance or rejection.

Sample implementation​

Refer to the API sample below to see how you can implement the login, launching, and getting a BP status with Apache HttpClient.

API sample
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.AbstractHttpEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.*;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//Not a production-grade implementation, use as an example only
public class APISample {

public static String BASE_URL = "https://instance.workfusion.com/workfusion";
public static String START_BP_URL = BASE_URL + "/api/v2/workfusion/task/file";
public static String STATUS_BP_URL = BASE_URL + "/api/v2/workfusion/task/";
public static String LOGIN_URL = BASE_URL + "/api/dologin";


public static String UUID = "4632e14b-86af-4fa8-8bc3-21ed709a0cb1";
public static String USERNAME = "ct_user_name";
public static String PASSWORD = "ct_user_password";

private HttpClient httpClient;
private List<Header> defaultHeaders;

public APISample() {
this.httpClient = HttpClients.createDefault();
this.defaultHeaders = new ArrayList<>(2);
}

public static void main(String... args) throws IOException {
APISample apiSample = new APISample();
apiSample.login();

//get version details and alike
//apiSample.get(BASE_URL + "/api/v2/workfusion/service/info");

//launch new Business Process
String uuid = apiSample.startBusinessProcess(UUID);

System.out.println(apiSample.getBusinessProcessStatus(uuid));
}

public void login() throws IOException {

List<NameValuePair> nvp = new ArrayList<>();
nvp.add(new BasicNameValuePair("j_username", USERNAME));
nvp.add(new BasicNameValuePair("j_password", PASSWORD));

//UrlEncodedFormEntity sets Content-Type=application/x-www-form-urlencoded
loginPost(LOGIN_URL, new UrlEncodedFormEntity(nvp));
}


public String get(String addressURL) throws IOException {

HttpGet httpGet = new HttpGet(addressURL);
System.out.println("GET -> " + addressURL);

HttpResponse response = httpClient.execute(httpGet);
return convertStreamToString(response.getEntity().getContent());
}

public List<Header> loginPost(String addressURL, AbstractHttpEntity body) throws IOException {

HttpPost httpPost = new HttpPost(addressURL);
System.out.println("POST -> " + addressURL);
httpPost.setEntity(body);

HttpResponse response = httpClient.execute(httpPost);
//
String cookieHeader = response.getHeaders("Set-Cookie")[0].getValue();
this.defaultHeaders.add(new BasicHeader("Cookie", cookieHeader));
//
String stringResponse = convertStreamToString(response.getEntity().getContent());
//
Map jsonResponse = new Gson().fromJson(stringResponse, Map.class);
String csrfToken = (String) jsonResponse.get("csrfToken");
String csrfHeader = (String) jsonResponse.get("csrfHeaderName");
this.defaultHeaders.add(new BasicHeader(csrfHeader, csrfToken));
return this.defaultHeaders;
}

public String post(String addressURL, AbstractHttpEntity body) throws IOException {

HttpPost httpPost = new HttpPost(addressURL);
System.out.println("POST -> " + addressURL);
httpPost.setEntity(body);
this.defaultHeaders.stream().forEach(httpPost::addHeader);

HttpResponse response = httpClient.execute(httpPost);
String stringResponse = convertStreamToString(response.getEntity().getContent());
System.out.println(stringResponse);

return stringResponse;
}


public String startBusinessProcess(String uuid) throws IOException {
TaskStart taskStart = new TaskStart();
taskStart.setCampaignUuid(uuid);

//pass the CSV file content here to provide input for the Business Process
taskStart.setMainData("loan_amt\n100000");

StringEntity body = new StringEntity(new Gson().toJson(taskStart));

//the server can return an error if it is not Content-Type=application/json
body.setContentType("application/json");

return post(START_BP_URL, body);
}

public String getBusinessProcessStatus(String uuid) throws IOException {
return get(STATUS_BP_URL + uuid);
}

static String convertStreamToString(java.io.InputStream is) {
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}

private static class TaskStart implements Serializable {

@SerializedName("campaignUuid")
private String campaignUuid;

@SerializedName("mainData")
private String mainData;

@SerializedName("sandbox")
private Boolean isSandbox;

@SerializedName("tags")
private String tags;

public TaskStart() {

}

public String getCampaignUuid() {
return campaignUuid;
}

public void setCampaignUuid(String campaignUuid) {
this.campaignUuid = campaignUuid;
}

public String getMainData() {
return mainData;
}

public void setMainData(String mainData) {
this.mainData = mainData;
}

public Boolean isSandbox() {
return isSandbox;
}

public void setSandbox(Boolean sandbox) {
isSandbox = sandbox;
}

public String getTags() {
return tags;
}

public Boolean getSandbox() {
return isSandbox;
}

public void setTags(String tags) {
this.tags = tags;
}

}

}