Write your REST Endpoints

A good REST makes every tech stack work efficiently.

Now assume you have a HRM application which does the book keeping of your employees' leaves. How does your bot update the leave information it understood from your employee during a conversation to your HRM ?

Here's where Dhee's adaptor APIs come to use.

The adaptor APIs are called by your Dhee.AI bot at the right phase of a conversation to communicate information back and forth with your existing back-end systems. These adaptor APIs have to be REST based endpoints exposed to the internet, secured, and authorised using Basic Authentication.

Also, they are called "adaptor" APIs, because they consume and produce data in the format prescribed by Dhee.AI, and encapsulates all the enterprise API calls, data accumulation from different sources, and any post processing if required, within them.

In this part of the walk-through, we will develop sample REST-based endpoints which would be later consumed by our clients/bots application. As discussed earlier, the walk-through has been designed based on an imaginary leave management system.

In the beginning, we will keep the endpoints as simple as possible. We will expose two end-points, one each for

  • RetrieveCasualLeaveStatus - Retrieves the total and remaining Casual leaves.

  • RetrieveSickLeaveStatus - Retrieves the total and remaining Sick leaves.

  • RaiseLeaveRequest - Raise a leave request for the specified category during the mentioned period.

API Endpoint

In this example, we will use Azure Functions to create end-points. Azure Functions serverless compute service which can be scaled on-demand. It frees the developer from maintaining the server infrastructure, configurations, or even web server. We would be using C#.Net as our primary language for developing the example endpoints. But note that choice of programming language is not important here.

API Response Format

The Dhee.AI requires the API endpoints to follow a fixed schema so that it can decipher the responses efficiently. The schema of the response object is defined as follows

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "success": {
      "type": "boolean"
    },
    "result": {
      "type": "object"
    },
    "resetList": {
      "type": "array",
      "items": {}
    },
    "errorMessageKey": {
      "type": "string"
    }
  },
  "required": [
    "success",
    "result",
    "resetList",
    "errorMessageKey"
  ]
}

For example,

{
    success : true,
    result : {
                slotName01 : "value01",
                slotName02 : "value02",
                slotNameN  : "valueN"
            },
    resetList : ["slotToBeEmptied01", "slotToBeEmptied02", "slotToBeEmptiedN"],
    errorMessageKey : "errorMessageMLTIfAny"
}

Considering the format, let us go ahead and define our DheeResponse Dto.

public class DheeResponseDto
{
    public bool Success { get; set; }
    public Dictionary<string,object> Result { get; set; }
    public IEnumerable<string> ResetList { get; set; }
    public string ErrorMessageKey { get; set; }
}

As mentioned earlier, we will keep the implementation as simple as possible in this state of development. The example Azure functions would not persist data and would use mock data for responding to User requests.

RetrieveCasualLeaveStatusStatus

The first endpoint we would be developing is the RetrieveCasualLeaveStatus. The method returns the original number of casual leaves available for the person and the remaining ones. With C#, you can define the Azure Function as the following.

[FunctionName(nameof(RetrieveCasualLeaveStatus))]
public static IActionResult RetrieveCasualLeaveStatus([HttpTrigger(AuthorizationLevel.Anonymous,
"POST",Route = null)] HttpRequest request,
ILogger logger)
{
    logger.LogInformation("Requesting for leave status");
    var random = new Random();

    // Mock the leave status
    var leaves = new CasualLeaveStatus
    {
        TotalLeaves = 20,
        Remaining = random.Next(0, 20),
    };

    return new OkObjectResult(new DheeResponseDto<CasualLeaveStatus>
    {
        Success = true,
        Result = leaves,
        ErrorMessageKey = String.Empty,
        ResetList = Enumerable.Empty<string>()
    }) ;
}

The CasualLeaveStatus Status is defined as

public interface ILeaveStatus
{
    int TotalLeaves { get; set; }
    int Remaining { get; set; }
}

public class CasualLeaveStatus : ILeaveStatus
{
    [JsonProperty("casual_leave_total")]
    public int TotalLeaves { get; set; }

    [JsonProperty("casual_leave_remaining")]
    public int Remaining { get; set; }
}

public class SickLeaveStatus : ILeaveStatus
{
    [JsonProperty("sick_leave_total")]
    public int TotalLeaves { get; set; }

    [JsonProperty("sick_leave_remaining")]
    public int Remaining { get; set; }
}

RetrieveSickLeaveStatusStatus

The RetrieveSickLeaveStatusStatus API is quite similar to RetrieveCasualLeaveStatusStatus in terms of sample implementation.

[FunctionName(nameof(RetrieveSickLeaveStatus))]
public static IActionResult RetrieveSickLeaveStatus([HttpTrigger(AuthorizationLevel.Anonymous,
"POST",Route = null)] HttpRequest request,
ILogger logger)
{
    logger.LogInformation("Requesting for leave status");
    var random = new Random();

    // Mock the leave status
    var leaves = new SickLeaveStatus
    {
        TotalLeaves = 20,
        Remaining = random.Next(0, 20),
    };

    return new OkObjectResult(new DheeResponseDto<SickLeaveStatus>
    {
        Success = true,
        Result = leaves,
        ErrorMessageKey = String.Empty,
        ResetList = Enumerable.Empty<string>()
    });
}

RaiseLeaveRequest

The third endpoint we would develop is the RaiseLeaveRequest endpoint. The purpose of the endpoint would be to create a leave request for the User for the specified Date Period.

Definition of the endpoint using C# is shown below.

[FunctionName(nameof(RequestLeave))]
public static async Task<IActionResult> RequestLeave(
    [HttpTrigger(AuthorizationLevel.Function, "POST", Route = null)] HttpRequest request,
    ILogger logger)
{
    logger.LogInformation("Parsing Leave Request Information");

    var data = new
    {
        StartDate = DateTime.Parse(request.Query["startDate"]),
        EndDate = DateTime.Parse(request.Query["endDate"]),
        Reason = request.Query["leaveReason"]
    };

    logger.LogInformation($"Marking {data.Reason} Leave from {data.StartDate} to {data.EndDate}");

    return new OkObjectResult(new DheeResponseDto<LeaveRequestResponse>
    {
        Success = true,
        Result = new LeaveRequestResponse { IsRequested = true},
        ErrorMessageKey = String.Empty,
        ResetList = Enumerable.Empty<string>()
    });
}

internal class LeaveRequestResponse
{
    [JsonProperty("is_requested")]
    public bool IsRequested { get; set; }
}

Note that the input slots are query string parameters on a POST request. This is how dhee.ai would be sending the slot information to the endpoints.

As mentioned earlier, our API endpoints have been the simplified definition for the sake of this example. We have intentionally skipped any layer of persistence or exception handling. We will address these in the following walkthroughs.

This brings us to the conclusion of the first step. We will now use the Dhee.AI portal to configure our Bot.

You can now download the complete source code for the demo API described in this example.

Last updated