SharePoint Framework web part and K2 Workflow REST API

In this article I will describe the necessary steps to create and configure SharePoint Framework web part to access K2 workflow REST API on K2 Five or K2 Cloud. The example will be simple “Worklist” web part that shows K2 workflow tasks that are available for current user. The K2 API is configured with OAuth authentication and AAD accounts. Complete sample is published in a repo on my GitHub: and you can follow along the source code of that web part, as I will emphasize important parts of the solution.

As a starting point, I used steps explained in the article Connect to Azure AD-secured APIs in SharePoint Framework solutions. However, there are some challenges related to the configuration of AadHttpClient that imposed obstacles, that are not described in detail in the article text and that presented an obstacle that I resolved using “brute force – common sense” approach.

K2 Workflow API

As described in K2 documentation (configuration and developer reference), K2 Cloud and K2 Five expose REST API endpoint for Workflows. It is possible to use those APIs to start workflows, retrieve active tasks for user, and perform workflow actions on existing tasks. K2 exposes preview and v1 versions of the API.

Necessary configuration steps:

  1. As described in configuration guidance on K2 documentation, it is necessary to configure CORS before we can try to access the service from SharePoint - I need to white-list my SharePoint Online before I can call the API from web part.
  2. I also need to setup AAD consent before the API endpoint can be accessed from any AAD account (described in K2 help article).

For this example I’m using tasks endpoint that provides access to active tasks for user. :

{ "itemCount": 1, "tasks": [ { "serialNumber": "670_7", "status": "Open", "taskStartDate": "2018-12-30T21:27:51.39", "priority": 1, "formURL": "https:///Runtime/Runtime/Form/com.K2.System.Workflow.Form.BasicTask/?SN=670_7&_title=&_url=&_embed=", "viewFlowURL": "https:///ViewFlow/ViewFlow.aspx?ProcessID=670", "workflowID": 888, "workflowName": "Flow to K2\Flow2K2.ApproveRequest", "workflowDisplayName": "Flow2K2.ApproveRequest", "workflowCategory": "Flow to K2", "workflowInstanceID": 670, "workflowInstanceFolio": "12/30/2018 10:27 PM", "activityInstanceID": 5, "activityInstanceDestinationID": 7, "activityName": "Approve Request", "eventName": "Approve Request", "eventDescription": "", "originator": { "username": "", "fqn": "", "email": "", "manager": "", "displayName": "" }, "actions": { "nonBatchableActions": [], "batchableActions": [ "Approve", "Reject" ], "systemActions": [ "Redirect", "Release", "Share", "Sleep", "Unshare" ] }, "instruction": "" } ] }


K2 has published enterprise application for K2 API that can be used for connection to K2 API endpoints. You can find it in Azure Portal > Azure Active Directory > Enterprise Applications. I will use this application to configure webApiPermissionRequest and AadHttpClient to connect to the tasks endpoint. Details for the Enterprise Application are shown on the screenshot below:


I use Name to configure webApiPermissionRequest, which makes my manifest portable between different environments.  I use Homepage URL (which is at the same time our Resource) for initialization of AadHttpClient . That is a bit of discrepancy to official guidance, which states that AadHttpClient should be initialized using Application ID of AAD application which we use to secure the resource.

K2 API Permission Request

I configure the web part with permission request by adding entry in webApiPermissionRequest to config/package-solution.json (per guidance) as in the code snippet below:

"webApiPermissionRequests": [
    "resource": "K2 API",
    "scope": "user_impersonation"

As I mentioned, I am using Name of my Enterprise App as a resource for my permission request. That will make my webpart usable in different environments, without the need to change anything in manifest. In theory, that would enable me to publish the web part in SharePoint Store.

Initialization of AadHttpClient

In my web part, I am initializing AadHttpClient with resource URL of our AAD App (help article on That is the only possible way which worked for me without errors – I could not make it work using Application ID. Here is relevant code snippet in code of my web part:

protected onInit(): Promise { return new Promise((resolve: () => void, reject: (error:any) => void): void => { this.context.aadHttpClientFactory .getClient('') .then((client: AadHttpClient): void => { this.aadClient = client; resolve(); }, err => reject(err)); });


Calling REST API and rendering response

Once I have initialized the AadHttpClient, I am calling REST API:

this.aadClient.get( + '/api/workflow/preview/tasks', AadHttpClient.configurations.v1)

and rendering table row for each retrived worklist item:

\({ => `<tr><td><a href="\)" target="_blank" class="\({ styles.button }">Open Form</a></td><td>\)\({t.workflowInstanceFolio}</td><td>\)View`).join('')}

Here I am accessing different parts of returned JSON in accordance with the schema of REST response (see above)

Granting permissions

After I add the web part to App Catalog, I need to approve request for API permission (guidance) which looks like this in my case:


Web part configuration

After web part is added to the page, it has to be configured with correct URL to K2 Server on which we are connecting. The configuration is performed by editing K2 Server URL property in Web Part Property pane:


After that, we can finally see the end result – which is to show available tasks from K2 worklist on a Modern Page in SharePoint Online


Final thoughts

The intention of this article is to describe one approach for integration of data that originates from K2 REST API into Modern UI in SharePoint Online using SharePoint Framework web part, and to provide workaround for some challenges related to initialization of AadHttpClient against Enterprise Application in Azure Active Directory. Web part itself is not intended to be used in production, because it is not coded that way and lacks error handling – so consider it as demo code. Code is available in repository on my GitHub: and might or might not get updated/improved over time. Feel free to fork the repo and use it as starting point for your solutions. Reach out to me on Twitter: if you have any questions or comments. If you liked this post or find it useful, please share it on LinkedIn or Twitter and tag me Smile .