Skip to main content
Version: 10.2.8

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

For WorkFusion public REST API, refer to Swagger.

Business Processes and Manual Tasks have a specific lifecycle within WorkFusion. There are a number of states: draft, processing, paused, completed, and so on. The API lets you manage the operations by providing unique actions applicable to various states—create, start, pause, stop, and so on.

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 employs form-based (login and password) authentication to ensure that APIs are only accessible to users with proper credentials.

Note that CSRF protection is added to REST endpoints. To make a REST call, add a CSRF token to the request header.

  1. Before executing REST API requests, log in using the form URL:

    POST method

    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.
  2. A successful request body from the server looks like this:

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

  4. When creating REST API requests:

    1. Set this 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.

Here is a Postman login request example:

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 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 to each Master server:

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

    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, on the Master server, run the following command:

    ./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.

The example output is as follows:

[wfuser@ip-10-100-9-111 ~]$ curl https://core-35330-wfan-10024-workfusion-lb1.wflab.io/echo
{"X-Forwarded-For": "10.100.9.111"}

UUID

Each operation, such as a task, Business Process, or workforce, have a unique identifier called UUID. It is used as a unique reference to invoke the WorkFusion API and identify those entities. The UUID looks similar to this: db1cf0a8-1be4-4842-aec9-4ab0196bc9f1.

Once you receive the required UUID, you can use it to manage BPs or workforces via API. For example:

For more information on each endpoint and its parameters, see the Swagger UI.

Obtain Business Process UUID

To obtain Business Process UUID, follow the instruction below:

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

  2. Click the button to open the BP definition in a new tab.

    The Business Process definition opens in a new tab. The UUID is displayed as shown in the image below.

Obtain Workforce UUID

To get a Workforce UUID, follow the steps below:

  1. In Control Tower, go to Workers > Workforces.

  2. Copy the UUID of the required Workforce from the table.

Document processing

This section provides details on Intelligent Document Processing designed to:

  1. Accept files from a customer’s system.
  2. Use these files for an Intelligent Document Processing Business Process.
  3. Classify and extract information in the context of the BP.
  4. Route documents that require human-in-the-loop for exception handling.
  5. Send the results of the process to the customer's system.

Get data files for screening

The input data is an Excel file with the buyer or seller data used in your use cases. This data can be delivered from a file storage:

  • MinIO S3 within Work.AI
  • Any outside Work.AI

Work.AI MinIO S3

The MinIO client for interacting with WorkFusion MinIO S3 can be written in Java, Go, Python, JS, .NET, and other languages.

WorkFusion MinIO is available at https://HOSTNAME-minio-lb1.workfusion.com/minio/. Remember to insert your URI instead of the placeholder.

The WorkFusion MinIO URL is outside the Work.AI platform. Therefore, use the access key and secret key authentication:

Access key: HHVDVFJFT3GHHJKJ43FG
Secret Key: KNJkljJHGJHgjhJGHKjgy666RryfrftFk6589890

For more information on how to upload and download files, refer to the MinIO documentation.

You have to create a bucket in the following format in advance: https://HOSTNAME-minio-lb1.workfusion.com/minio/media_check/input_data/.

Verify that the file transfer is working by checking the following MinIO SDK methods (JavaScript Client API Reference):

  • bucketExists checks if a bucket exists: https://docs.min.io/docs/javascript-client-api-reference.html#bucketExists.

  • putObject uploads an object from a Stream or Buffer: https://docs.min.io/docs/javascript-client-api-reference.html#putObject.

    In case of a successful file transfer, the response contains the etag and versionId strings of the uploaded object.

File storage outside of Work.AI

A client's server can also 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 a 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

At the end of execution, the BP saves the updated files to the MinIO S3 storage at https://HOSTNAME-minio-lb1.workfusion.com/minio/media_check/output_data/.

The BP generates a final report with temporary links to these files. You can retrieve the report via API. For details, read Check BP for results.

Start Business Process

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

The command to start a Business Process takes the following form:

  • Method: POST

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

  • Headers required:

  • Body:

    • JSON object

      {
      "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: UUID of the started Business Process

    Below is a Postman example:

The return of a UUID indicates a successful start of the Business Process with the provided CSV file.

Check BP status

Once the Business Process is underway, it is necessary to continually check its status to determine when it is completed.

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

  • Headers required:

  • 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",
    "workforceUuid": null
    },
    ...,
    {
    "title": "Step 5",
    "stepIndex": 5,
    "runUuid": "uuid",
    "runStatus": "COMPLETED",
    "campaignUuid": "uuid",
    "type": "MACHINE",
    "finalStep": true,
    "stepPosition": "END",
    "componentUuid": "uuid",
    "versionUuid": "uuid",
    "workforceUuid": null
    }
    ]

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.

If the BP fails, log in to Control Tower and investigate the problem, including analyzing logs.

Check BP for results

To pull the results of a Business Process or look at its snapshot with a specific UUID in the CSV or XLSX format, use the following structure:

  • Method: GET

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

  • Headers required:

  • Response: returns 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 from the WorkFusion Media Check BP processing.

Process results

The updated files have to be uploaded to your system based on the business and process requirements so that relevant Analysts can process alerts.

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

}

}