Skip to main content

Introduction to Consuming REST APIs

Representational State Transfer

R
Written by Riku Virtanen
Updated over a year ago

Consuming REST APIs

Quick recap of REST APIs

REST API stands for RESTful (Representational State Transfer) Application Programming Interface and enables a variety of integration use cases over HTTP(S).

Remember that REST in the context of REST APIs is a set of architectural guidelines for representing the state of the resource for the API consumer. Therefore, REST APIs can be implemented in various ways and Frends supports all of them as any HTTP request possible.

How to consume REST APIs

When your integration use cases require consuming a REST API, you must recognize the type of payloads that are posted by the client and returned by the server as it dictates which the Frends Tasks should be used in the Process.

There are two Frends Tasks eligible for the most common REST API use cases: Web RestRequest and Web HttpRequest.

The Web RestRequest Task covers all HTTP(S) use cases where the response body from the server is JSON deserializable, therefore enabling the developers to use dot notation for referencing the JSON payload's properties without any additional deserialization or parsing of the response. On the other hand, this means that the request payload can be in any string format with RestRequest Task. Also, bear in mind that the Web RestRequest Task will throw an exception when deserialization does not succeed so make sure the REST API that you are consuming always returns JSON.

The Web HttpRequest Task on the other hand does not try to deserialize the response from the server and is therefore suitable for any kind of response but the developer must handle the format accordingly for the integration use case.

We can also see this difference between RestRequest and HttpRequest in their Task documentation as RestRequest returns an object with the Body property as JToken whereas HttpRequest returns an object with the Body property as string.

RestRequest:

For more detailed documentation, see: https://github.com/FrendsPlatform/Frends.Web#RestRequest  Returns: Object with the following properties: JToken Body. Dictionary(string,string) Headers. int StatusCode

HttpRequest:

For more detailed documentation, see: https://github.com/FrendsPlatform/Frends.Web#HttpRequest Returns: Object with the following properties: string Body, Dictionary(string,string) Headers. int StatusCode

Sometimes REST APIs may publish an endpoint which requires a file as request or response payload. In this case the payload must be handled as byte array representation of the file and this practice is covered in a following module of Other techniques for HTTP requests. For now, we cover REST APIs that transmit data as strings like JSON or XML.

Once you know what Task to use for consuming the REST API in your use case, you need to configure the parameters in the Task:

  • URL

  • Query parameters

  • HTTP Method

  • HTTP Headers

  • Message (request payload)

  • Authentication

  • Connection timeout (in seconds)

  • Follow redirects

  • Allow invalid certificate

  • Allow invalid response content type char set

  • Throw exception on error response

  • Automatic cookie handling

URL

Every HTTP request needs the server address with the needed URI parameters. In Frends, these are configured in the Uri field.

In the example above, we are referencing the Environment Variable companyAPI.baseURL with a value of https://company.com/api and specifying the resources. When the HTTP request would be executed, the Url value will be https://company.com/api/resource/v1/resouce. Using Environment Variables is essential when dealing with REST APIs that are published from different Environments.

Query parameters

Some REST APIs would need query parameters or query strings as part of the Url. These query parameters usually have a standardized format after the URL with key value pairs in the following format: ?key1=value1&key2=value2&key3=value3. These values are also URL encoded which is a specific practice to encode strings for URLs. The URL encoding is covered later in this course.

These parameters can of course be referenced as Process Variables with #var. notation if they change dynamically during Process execution and instances. Also pagination of some REST APIs are handled with query parameters.

HTTP Method

Depending on the REST API, you can use different HTTP methods. With Frends HTTP related Tasks you can use the following methods that are selected in the Task input parameters.

GET, HEAD, OPTIONS and CONNECT methods do not have a configured payload as part of the HTTP request. The complement group of these methods (POST, PUT, PATCH, DELETE) do have the option to include a configurable payload to the HTTP request which will appear on the input parameters once the method is selected. When using POST method in REST API practices, the message/payload is commonly utilized but the practices do vary so it is important to check out the documentation how the methods should be used with different use cases.

HTTP Headers

It is very common to utilize a variety of HTTP Headers in a HTTP request and their usage with Frends is very intuitive. With HTTP related Tasks, the HTTP Headers are configured in the Input parameters. HTTP Headers from the client usually describe the payload, telling the server what type of data to return, authorizing the request with secrets and so on. Also the server will return a set of HTTP Headers which can be used later in the Process after the HTTP request Task has executed.

In the example above, we are setting two HTTP Headers as an Array: an API Key with a value that is referenced from Environment Variables and a standard Content-Type header with value application/json which tells the server that we are sending a payload in JSON format with that HTTP request. The values of the HTTP Headers in an Array can be, for instance, text and expression, so remember to use handlebars with references or C# expressions when necessary.

The other method of inserting HTTP Headers is with Expression which requires a C# array of Frends.Web.Header types. Below is an example how this kind of array could be formed with the same values as in the example above. If you would be dynamically handling the headers, using List collection would be suggested as you can easily add the required headers and eventually call ToArray() method when referencing it to the Headers field as Expression.

There is no finite limit for how many HTTP Headers can be used with these Frends Tasks and usually the REST API that is to be consumed defines the mandatory headers.

Message / Payload

The message or payload in REST APIs is used when making requests that transmit data from a client to the server. The Message field in the HTTP Tasks can be of type text, JSON or expression. The text and JSON types differ only by the visual formatting in the input field to help the developer manage complex JSON objects.

In the example above, we have hardcoded the payload, but if the integration use case requires the payload to be formed according to previous Element results or Variable values, we could use handlebars and inject references. The example below shows how the references would work if there was a previous Task named Generate Resource according calculation and its result would have properties resourceName, resourceId and resourceDescription that could be mapped to the message of the REST API request.

Authentication

RestRequest and HttpRequest Tasks support the following Authentication method as standard Options parameters.

If the Authentication type requires some additional parameters, they will be visible after selection.

Usually REST APIs utilize OAuth or API Keys. In the case of OAuth, the token will be referenced to in the Token field once OAuth has been selected from the Authentication selector. OAuth authorization can also be used with None as the Options parameter Authentication value and HTTP Header with Name Authorization and value Bearer "OAuth Token value" which has been retrieved with a previous HTTP request or Subprocess.

When using API Keys, they need to be added into the HTTP Headers with a correct Header name and value preferably referenced from an Environment Variable.

Connection timeout (in seconds)

The Connection timeout seconds parameter is used for terminating the connection after the said time in seconds. The integer value for timeout is heavily dependent on the used REST API and the default value of 30 seconds is a good starting point which can be tweaked later if needed.

Follow redirects

Some endpoints may offer a redirect but usually REST APIs do not.

Allow invalid certificate

Most of the time REST APIs use a valid certificate but sometimes they may evaluate to invalid and therefore HTTPS may not work as intended. In these cases where the seemingly invalid certificate should be used, you can toggle Allow invalid certificate for these kinds of REST API requests.

Allow invalid response content type char set

REST APIs may sometimes return invalid response content for the request that was sent and therefore Allow invalid response content type char set could be used to handle these deficits in REST API functionality. Be sure to handle these types of use cases properly with exception handling.

Throw exception on error response

RestRequest and HttpRequest Tasks can throw exceptions according to the StatusCode of the response with the Throw exception on error response boolean toggle. When the toggle is set to true, an exception is thrown if the StatusCode of the response is something other than 200-299.

Automatic cookie handling

The Automatic cookie handling toggle enables to handle the cookies automatically.

Examples

The following examples show how to make REST API requests in typical use cases.

Consuming REST API requests with JSON format

Use case: GET customers as JSON from REST API and authenticate with API Key.

In this use case we just simply need a RestRequest Task with the following parameters. Remember to name the Task according to the commonly agreed practices with possible additional documentation Elements. The documentation of the consumed API should indicate what type of JSON response is to be expected, hence dictating the following actions in the use case.

In this use case, the base URL for the API is saved to an Environment Variable and referenced in the Url field with additional resources /api/crm/v1/customer to produce a complete Url https://companyurl.com/api/crm/v1/customer when this Task would be executed.

The API Key in the HTTP Header is also referenced from an Environment Variable with this value #env.companyAPI.APIKEY in handlebars and the name X-API-KEY in this hypothetical use case. The API documentation should explain how an API Key is used.

The last HTTP Header Accept: application/json is for indicating to the server that this client expects data in JSON format.

Eventually, the result of this Task would be referenced with #result[REST API: Get Customers] notation and would return the data received from the API.

​

Use case: POST customer as JSON to REST API and authenticate with OAuth.

In this use case we are using the same RestRequest Task as in the example above. However, we could also use the HttpRequest Task but referencing the results later in the Process is much easier with a RestRequest Task as JSON responses are deserialized to objects that can be referenced with dot notation.

This use case also has a different HTTP method selected compared to the one above as we are pushing data to the REST API with the POST method which in return means that the HTTP request contains a JSON payload. This payload is hardcoded in the Message field. Commonly these payloads are dynamically generated or mapped from different Tasks or Variables earlier in the Process. The referencing and forming of JSON property values were briefly described earlier in this module in chapter Message / Payload.

In addition to the HTTP method and payload, this use case has a common authentication method, an OAuth flow. This flow requires requesting an access token with a separate HTTP request from an endpoint with some secrets and parameters. That endpoint will eventually return an access token which will then be used to authenticate within the REST API and give access to the resources that are being consumed. The specifics of an OAuth flow will be described later in the module describing authentications but for now, we just take it for granted that the Get OAuth2 Token Task response will contain an auth_token property which will be referenced in the HTTP Header respectively.

In the example below, you can see how the POST request would work with an OAuth flow utilizing a prior HTTP request to get the access token. Eventually the REST API: POST Customer Task would be responded with the actual resource itself, according to the REST API best practices. In the end, the REST API documentation usually describes how the payload should be formed as well as the HTTP headers with different types of authentication.

Consuming REST API requests with XML or other formats

As REST API practices do not dictate the resource representation format to be JSON only, XML for instance could be used and only the payload and HTTP Header Content-Type or Accept would differ compared to the example above. With Frends there are multiple different ways to manipulate XML messages into different formats and the most common is to manipulate the data in deserialized JSON format and eventually use a Task to transform JSON back to XML. Also, XSLT mappings are possible for manipulating XML to a desired format. In the end, the mechanism of managing different message types boils down to the developer preference.

Exception handling with REST APIs

There are four angle of approaches to REST API exception handling and they always depend on the integration use case which consumes a REST API:

  1. Check HTTP status code

  2. Throw exception on error response with Catch

  3. Throw exception on error response with Call subprocess on unhandled error

  4. A combination of solutions above

Check HTTP status code

HTTP status code is widely used and standardized practice in HTTP responses for informing the client whether the HTTP request has been successfully completed. The HTTP responses are grouped in five classes with following status codes:

  1. Informational responses 100-199

  2. Successful responses 200-299

  3. Redirection messages 300-399

  4. Client error responses 400-499

  5. Server error responses 500-599

By using RestRequest or HttpRequest Task, successful execution results always have StatusCode property which can be used to determine how did the HTTP request itself work.

We could implement our exception handling like in the example below where after the RestRequest or HttpRequest Task we would give an expression #result[Consume API A].StatusCode <= 299 in the Exclusive Decision to determine do we need to execute some error handling or continue the Process execution.

This solution would catch exceptions relying on the HTTP status code, assuming the HTTP request works, hence not being able to continue the Process execution if the HTTP request fails, for example if it times out for some reason. Also, for more granular status code interpretation, an Inclusive Decision could be used if the error handling depends on what type of error response is received from the server.

Throw exception or error response with Catch

The second option is to implement more resilient approach where we would toggle the Throw exception on error response which allows us to catch all possible exceptions from the specific Task. This approach will catch HTTP status codes of error and if the request itself fails. For instance, a request can timeout or the server may not be online.

With this solution, remember that the joining element of Consume API A Task and do some error handling Subprocess, in this case the Return element, expects the same type of Result. The Catch element could also be attached to a Scope element that contains the specific HTTP Tasks.

Throw exception on error response with Subprocess to call on unhandled error

The third option to handle exceptions is without Catch element and instead specify Subprocess to call on unhandled error on the Process level. This allows a more simple solution but relies on the Subprocess to be called with unhandled error and does not allow the Process to continue.

A combination of solutions above

With Frends, you can build any kind of logic for your error handling and therefore depending on the use case and Process in question, sometimes more granular exception handling with different status codes and error handling elements may be required.

Recap on how to consume REST APIs with Frends

  1. Common REST API calls are implemented with RestRequest or HttpRequest Tasks

  2. The API documentation should tell you explicitly how to consume it

  3. Prefer RestRequest Task if the API returns JSON

  4. Handle errors according to your need

Did this answer your question?