1. Home
  2. Developer Support
  3. Getting Started
  4. Make Http Request and Web API Action Endpoints

Make Http Request and Web API Action Endpoints

By making use of the following Workflow Actions, it is possible to integrate external systems with Workflows and Triggers via custom endpoints:

This document will help get you started setting up your own endpoints. Since these Actions are context sensitive (where and how they’re being used) and potentially configurable (via custom request bodies), the endpoints you create will be highly dependent and varied. Therefore, the examples below are just skeleton implementations. At the bottom of this article is a link to a working sample project written in C# containing the code used throughout this document.

Both Actions can be used to get data out of Workflow and into external systems. For example, if a Workflow Definition is modified in CostGuard, you may want to update an external system with the Workflow’s new information. To do this, a Trigger could be configured to fire on Workflow Definition Modified with the Make Http Request Action. You may also have a Workflow defined for changing a Workflow Definition, in which case a Task may exist that uses the Web API Action. The following sections describe using these Actions.

Make Http Request Action

The Make Http Request Action is great for integrating to an existing endpoint or for when you don’t have much control over the endpoint’s definition since it is possible to configure things such as the method (GET, POST, …), the content type (application/json, application/xml, …), and the request body:

When the trigger fires, smart data placeholders (text in the format “@[property name]”) are replaced with actual values. Assuming the above configuration for a Trigger named “Workflow Definition Updated”, the JSON request body sent to https://myapi.com/api/workflowdefinitions/makehttprequest would be:

{
   "name":"Workflow Definition Updated",
   "description":"Update external system when a Workflow Definition is modified.”,
   "workflowTypeID":"178"
}

The model defined should match the request body specified in the Action’s configuration. It can contain additional properties, but to fully receive the request body, it should at least have a property for each element in the request body.

public class WorkflowDefinitionModel
{
    public string   Name                { get; set; }
    public string   Description         { get; set; }
    public int      WorkflowTypeID      { get; set; }
}

Querystring parameters can also be specified in the URL address using smart data replacement to match an endpoint’s definition. The URL address above contains a querystring parameter named workflowID to match the following example skeleton endpoint implementation:

[CustomApiAuthorization]
[RoutePrefix("api/workflowdefinitions")]
public class WorkflowDefinitionsController : ApiController
{
    [HttpPost]
    [Route("makehttprequest")]
    public IHttpActionResult PostMakeHttpRequest(int workflowID,
        [FromBody] WorkflowDefinitionModel vm)
    {
        // Do work here

        // Return a 200 status code
        return Ok();
    }
}

The skeleton implementation above isn’t doing anything with the data passed to (parameter(s), request body), but they could be used to update a 3rd party system.

The Make Http Request Action will not complete until an Http status code is returned. Therefore, it is important to only do work inside your endpoint that will complete in a timely fashion as the Make Http Request Action task has a 2-minute timeout. If you must perform work that could take some time to complete, it is recommended to use the Web API Action since it can be configured to run in an asynchronous manner.

Web API Action

The Web API Action makes an HTTP(S) request to a specified address. It can be used by a Trigger or within the definition of a Workflow Task. When used by a Task, the Action can be configured to run in an asynchronous manner, meaning the Task will not complete automatically, but rather the Task must be completed manually or via an API call. Note that the “Is Async” parameter is also available when configuring a Trigger. However, since there is no Task to complete, the Trigger will be completed as soon as the call has been completed (when an HTTP status code has been returned from the method).

The following screenshot shows how to configure a Workflow Task to call an external API in an asynchronous manner. To start, set the “Is Async” property to “Yes”:

The body that is automatically sent to the endpoint includes the Environment the Workflow is running in and the IDs of the Workflow (WorkflowInstanceID) and Task (WorkItemInstanceID). In addition, an object named “Metadata” is included that contains key/value pairs for all configuration parameters plus key/value pairs for the extended data defined for the Workflow. For example, assuming a Workflow has an extended data field named EmployeeBadgeID, the following JSON would be sent to the endpoint by the Task:

{  
   "Environment":"MY_ENVIRONMENT",
   "Metadata":{  
      "URL":"http://myapi.com/api/workflowdefinitions/webapiasync",
      "Is Async":"True",
      "Headers.Authorization":"Basic mysupersecretauthkey",
      "EmployeeBadgeID":"9876"
   },
   "WorkflowInstanceID":2345,
   "WorkItemInstanceID":6789
}

Below is an example skeleton implementation of an endpoint to handle the configuration above:

[CustomApiAuthorization]
[RoutePrefix("api/workflowdefinitions")]
public class WorkflowDefinitionsController : ApiController
{
    [Route("webapiasync")]
    public IHttpActionResult PostWebApiAsync([FromBody] WebApiModel vm)
    {
        var environment = ConfigurationManager.AppSettings["Environment"];
        if (environment.Equals(vm.Environment))
        {
            // Do asynchronous work here and when done, set the task to Completed
            DoWork(vm);

            // Return a 200 status code (since DoWork() runs on a separate thread,
            // Ok will get returned immediately)
            return Ok();
        }

        return BadRequest();
    }
}

To fully receive the request body above, a model could be defined as follows:

public class WebApiModel
{
    public string                       Environment         { get; set; }
    public int                          WorkflowInstanceID  { get; set; }
    public int                          WorkItemInstanceID  { get; set; }
    public Dictionary    Metadata            { get; set; }
}

In the sample project, the endpoint above calls a method named DoWork() that performs a long running task on a separate thread:

private void DoWork(WebApiModel vm)
{
    Task.Run(() => PerformWork(vm));
}

private async Task PerformWork(WebApiModel vm)
{
    // Simulate a 30 second task
    await Task.Delay(30000);

    // Set the task to complete
    await SetTaskCompleteAsync(vm);
}

Since “Is Async” was set to Yes for the Task, it will not complete when execution returns from http://myapi.com/api/workflowdefinitions/webapiasync. Rather, the Task must be completed manually or via an API call. Below is an example of completing the Task via a Workflow API call after a 30 second delay. The method also shows updating extended data on the Workflow before completing the Task:

private async Task SetTaskCompleteAsync(WebApiModel vm)
{
    const int COMPLETED_WORK_ITEM_STATUS_ID = 3;

    var channel = Utilities.CreateWorkflowManagementChannel(vm.Environment);
    var requestor = new Requestor();
    requestor.AuthorizationToken = "AuthorizationToken";

    #region Update Extended Information on the Workflow

    var workflowReq = new ModifyWorkflowInstanceReq
    {
        WorkflowInstanceID = vm.WorkflowInstanceID,
        ExtendedInformation = new ExtendedInformation
        {
            new ExtendedInformationItem { Key = "EmployeeBadgeID", Value = "NS0414419" }
        }
    };

    #endregion

    #region Set the Task to Completed

    var workItemReq = new ModifyWorkItemInstanceReq
    {
        WorkItemInstanceID = vm.WorkItemInstanceID,
        RequestedWorkItemStatusID = COMPLETED_WORK_ITEM_STATUS_ID,
        Note = "Employee Badge ID assigned successfully (via asynchronous Web API call)"
    };
    
    var workItemRequest = new ModifyWorkItemInstanceRequest(requestor, workItemReq);
    var workItemResponse = await channel.ModifyWorkItemInstanceAsync(workItemRequest);
    if (workItemResponse.Messages != null)
    {
        throw new Exception("An error occurred setting the Task to Complete.");
    }

    #endregion
}

To learn more about these Actions, please refer to the following Knowledge Center articles:

Code Sample Project

Sample Workflow Integration

Updated on January 11, 2018
Was this article helpful?