# HTTP Client

Make calls to any third-party API

## Overview

The HTTP client connector allows you **to make calls to any third-party API endpoints**.
Two general scenarios which would necessitate the use of the Tray.io HTTP client connector are:

1. The endpoint you seek to use is not currently available within the service connector's operations list.
2. There is no Tray.io connector available for the service you need to reference. This means that the HTTP client connector can be used to effectively **build your own connector** by creating a new authentication and passing in a token as a parameter.

> **Info:** **USER TIP**: With scenario 2 it is likely that the HTTP client connector will be used in conjunction with the [Webhook Trigger](https://tray.ai/documentation/connectors/trigger/webhook-trigger/). This enables users to create workflows which are also triggered by an event in the service, for which there is no official Tray pre-built trigger yet either.

## Authentication

### Using existing auths

If Tray.io does have a connector but it doesn't have the operation you require, the HTTP client can use an auth you may have already created for that connector:
![http-client-airtable-use-existing-auth](https://tray.ai/documentation/images/connectors/core/http-client/2nmhhcrBA9EeIp3t1bPiao_http-client-airtable-use-existing-auth.png)
This can be done by selecting the auth in the Http client step. In which case you will notice that the HTTP client will adopt the icon for that service.
You can then make use of `$.auth` variables to meet any auth requirements the third party service may have.
This example shows passing `$.auth.api_key `as a bearer in the 'Authorization' header (exactly what the name of the token or key is will depend on the service - it could be e.g. `$.auth.api_token `or` $.auth.access_key`):
![httpclient-use-auth-value-as-header](https://tray.ai/documentation/images/connectors/core/http-client/5umjZBEZIhZTr9IfamXxO3_httpclient-use-auth-value-as-header.png)

### Custom / generic services

If no Tray.io connector is available, to use the HTTP client you will either need to create a [Generic Service Authentication](https://tray.ai/documentation/platform/connectivity/authentications#generic-service-authentication) or [Create a new service](https://tray.ai/documentation/platform/connectivity/custom-services/introduction) for the service you wish to use

### Secure use of authentications

> **Warning:** Do not hard code any authentication values directly into the properties panel!
> Always use the above `$.auth` method to programatically pick up your tokens from a proper authentication.
> This will ensure your token is properly obscured in the logs.

## Using the HTTP client

> **Info:** You may find that using our [cURL import](#import-curl-methods) feature is the easiest way to use the HTTP client!

### Making a GET request

Assuming you have already set up an Airtable authentication as per the [Custom services page](https://tray.ai/documentation/platform/connectors/custom-services/), the following example shows how you can make a basic Airtable GET request using the HTTP Client:
![http-step-1](https://tray.ai/documentation/images/connectors/core/http-client/29680238-571a5390_http-step-1.png)
In this case we have had to use the Airtable API documentation to find the **URL** of the endpoint we wish to access.
We have also had to set an **Authorization** Header using the `$.auth.api_key` jsonpath.
This will then return the data we are looking for:
![http-airtable-example-log-output](https://tray.ai/documentation/images/connectors/core/http-client/29680238-8b078bc7_http-airtable-example-log-output.png)

## Quickstart - import a request

It is possible to automatically create all the necessary inputs and query parameters for your request by importing what is called a 'curl command':

```json
// HubSpot API
curl --request GET \
  --url 'https://api.hubapi.com/crm/v3/objects/contacts?limit=10&archived=false' \
  --header 'authorization: Bearer YOUR_ACCESS_TOKEN'
```

Curl is a tool which allows you to specify http requests in plain text.
Developers would normally use this a command in a 'terminal', but in this case we can just import the request directly into the Tray Http client.
In its most basic format all you need is the curl command for your chosen API and an access key.
Handily, a lot of third-party services have ready-made curl commands in their docs that you can copy.

### Import cURL methods

The video demonstrates how to use three different cURL examples using the Import cURL feature:

1. A simple cURL address.
2. A cURL address including queries.
3. A cURL address including headers.

### Quick import example

When using curl import you will need to have an authentication for the service you are using.
The exact authentication method will depend on your service. Please reference the [Authentication](https://tray.ai/documentation/connectors/core/http-client/#authentication) section above for more guidance.
Below is an example (using HubSpot) of how we would use the cURL feature to auto-populate all the required fields.

### 1 - Find cURL command in third party docs

Here is an example cURL command from [HubSpot API docs](https://developers.hubspot.com/docs/api/overview) using [List contacts](https://developers.hubspot.com/docs/api/crm/contacts#endpoint?spec=GET-/crm/v3/objects/contacts):
![curl example hubspot](https://tray.ai/documentation/images/connectors/core/http-client/6VsWhCdlHVc3siMUtYUW8W_asdf.png)

### 2 - Paste your cURL command

> **Warning:** **IMPORTANT!**: Remember to not include values for your authorization headers as any auths you pass in this way will be visible in the workflow logs.

When you paste your cURL command **do not hard code the API key/access token directly** into the header.
**Leave the place holder for now**. If you set up your Token authentication correctly at the first stage the secure display option will be available to you once the properties panel updates with your cURL details.
![http-import-where](https://tray.ai/documentation/images/connectors/core/http-client/4rFXLWRstUOi6jqwt8DCHk_Group%2018%20%281%29.png)
![http-client-paste-the curl-code](https://tray.ai/documentation/images/connectors/core/http-client/3SB4DiBPczRDng6xWxAY6m_a;lsdkfj.png)

### 3 - Confirm to continue

A warning modal will appear. Make sure you are happy with your setup before continuing.
![http-client-curl-click-confirm](https://tray.ai/documentation/images/connectors/core/http-client/7KZeojil6wEvWNmbAtHNyy_alskdjfh.png)

### 4 - Update auth header

The **Import** feature auto populates the property field values for you.
Use interpolation to retrieve the auth **Access Token** and replace the service place holder.
Your own jsonpath will begin with the usual `$.auth...`. Depending on your service the end result could include `\{$.auth.access_token\}`, `\{$.auth.api_key\}` etc.
![http-import-panel-show](https://tray.ai/documentation/images/connectors/core/http-client/6d6Nyj1H80bqJKIyz0xgwt_Group%2017.png)
![hs-interpolation-token](https://tray.ai/documentation/images/connectors/core/http-client/4H1XjPXhhnRK4cGt1U5MUE_asdf.png)

### 5 - Test the workflow

The **Output** tab should update with new schema and your **Bearer token** will have been securely removed.
![http-client-curl-run-the-wf](https://tray.ai/documentation/images/connectors/core/http-client/1bBXPflYgpMlMy3l2hLg6G_asdkfygj%20%281%29.png)

### Error: 'The pasted curl command could not be parsed'

> **Warning:** Note that if the url in your curl command contains curly braces you will receive a 'the pasted curl command could not be parsed' error message.

In the following example `&#123;groupId&#125;` will cause such an error:

```json
curl --request POST \  
  --url 'https://your-domain.atlassian.net/rest/api/3/group/user?&#123;groupId&#125;=' \  
  --user 'email@example.com:<api_token>' \  
  --data '{  
  "accountId": "dummy_account"  
}'
```

The fix here would be to change the url to `https://your-domain.atlassian.net/rest/api/3/group/user?groupId=`
Note also, that you can pass curly brackets elsewhere in the curl command - as in the above `--data` parameter

## Testing your setup

The best way to check that everything is running properly is to use a manual trigger to call your API and inspect the logs to see what messages are being passed back and forth.

## HTTP client features

The HTTP client connector intelligently handles data to make things as clear, reliable and consistent as possible. Below are some of the measures we take to ensure this.

### OAuth2 advanced features

There are several advanced features available within the OAuth2 Advanced properties section:

* **Authorization type** - Set the authorization type and HTTP headers behind the scenes. May be used in conjunction with setting up your own custom refresh logic as well.

### Setting Authorization type (OAuth2)

When using OAuth2, you have two options for setting Authorization type:

* Add an 'Access token' to the **Headers** section
  Or
* Click on 'Show advanced properties', select 'OAuth2' and set the Access token under 'Authorization type'
  The Bearer section of the token path is already set for you here you need only add the latter half of the token path: `$.auth.access_token`.

![http-advanced-headers](https://tray.ai/documentation/images/connectors/core/http-client/7hc6pQFdLr2i514WmgTCr3_http-advanced-headers.png)

* **Follow redirect** - For if you want to move a webpage to a new location (redirects are not followed by default).
* **Reject unauthorised** - Default is 'true', everything is HTTPS. Users are able to disable the secure functionality if need be here.
* **TLS** - Users can make their own HTTPS settings. By default the connector states it is coming from Tray.io but this enables users to change the security information if need be and set the TLS setting in the HTTPS request.
* **Parse response** - Automatically generated as a string, this can be changed to make the response JSON or XML etc.
* **Force file response** - Instead of returning the response as a json object, this feature returns it as a file which can be downloaded.
* **Force file resonse name** - The name of the file if the response is forced as a file object.
* **Status codes** - Depending on the version number of the workflow in question, the connector will terminate depending on the status code. This feature allows users to specify the status codes that the HTTP client should expect as per their requirements. See [Dealing with statuses returned by your calls](#dealing-with-statuses-returned-by-your-calls) for more details below.

### Dealing with statuses returned by your calls

### Version 5.0+

As of version 5.0 (and above) by default the HTTP client connector fails if the status code returned isn’t in the `2xx` range.
If the status code returned by the API is one of the expected codes, the step is considered successful and the workflow will proceed as normal.
If the status code returned by the API is NOT one of the expected codes, the step will fail, and it is here that you can use Tray.io's error handling capabilities to mitigate things.
Note that users can change this with the Status code advanced property feature, in that users can specify the status codes that the HTTP client should expect.

### Version 5.0<

Each time an operation makes a call, as long as a connection is made and a status is returned, **Tray.io will not consider that an error has occurred**.
For example, a status of `403 - Forbidden` or `504 - Gateway Timeout` will not result in a Tray.io error that would be managed using our [Error Handling](https://tray.ai/documentation/platform/troubleshooting/error-handling/) methods.
If `4xx` and `5xx` statuses are likely to be encountered, the Tray.io [Boolean condition](https://tray.ai/documentation/connectors/core/boolean-condition) and [Branch](https://tray.ai/documentation/connectors/core/branch/) connectors can be used to set up a path for dealing with these use cases.

### Variables

All variables passed as query parameters are HTML-escaped automatically.

### Pagination

Tray has a page limit of 1 MB. So calls to APIs may return errors if the body of the returned content is too large.
To prevent this happening, you should implement a pagination method which is appropriate to the type of API calls you are making.

### Headers

Any header required by the API Service can be added, as per the 'Authorization' header in the above [Making a GET request example](#making-a-get-request) for a token-based auth.

#### Content

The **Content-Type header is automatically set depending on the body provided**, with `application/ x-www-form-urlencoded` being set if none is selected.
Additionally, the Content-Type of the request can be set/ overwritten by explicitly specifying it in the header itself.

#### Accept

The **Accept header is fixed to application/json, with a few exceptions**.
If the `body` is set to `none`, or the automatically detected Content-Type (dependent on the body) is either `text/ plain` or `application / x-www-form-urlencoded`, then Accept is not set.
Additionally, the Accept value of the request can be set/ overwritten by explicitly specifying it in the header.

### Binary files

It is possible to use the HTTP client connector to send files across in a binary format using the 'Body type' -> 'Binary' option.
When a user sends a file using the 'Body type': 'binary' property, Tray.io will stream the data of that object to your endpoint.
The end result will be a string output, found within your output panel under the JSON key name: `"body"`.
For the sake of clarity, this example will use two small Tray.io workflows to show the transportation of the data more clearly.

### 1 - Set up a form to send a file

Using the Form trigger, set the operation to 'Form request'. Using the following properties panel field information, the first workflow will trigger once a file is uploaded online.
![http-binary-step-1](https://tray.ai/documentation/images/connectors/core/http-client/29680238-e253040b_http-binary-step-1.png)
Note that you can get the URL of your form trigger via the settings icon within your workflow builder.
![http-binary-step-1-url](https://tray.ai/documentation/images/connectors/core/http-client/29680238-4a11a0ce_http-binary-step-1-url.png)

### 2 - Upload file

Now go to the form trigger URL and upload the file you wish to send in binary format.
**The file itself can be in any format**, as the point of this exercise is to prove that during the "send" process between workflows, the file will be sent in binary format (not that it was as such to begin with).
![http-binary-step-1-upload](https://tray.ai/documentation/images/connectors/core/http-client/29680238-d82a3063_http-binary-step-1-upload.png)

### 3 - Add HTTP client POST step

Add a HTTP client connector as your next step. Set the operation to 'POST'.

### 4 - Create second webhook-triggered workflow

Create a secondary workflow, this time using a Webhook as your trigger. Copy the public URL reference for this secondary workflow, and go back to the original workflow.
![http-binary-step-2](https://tray.ai/documentation/images/connectors/core/http-client/29680238-b745b5fe_http-binary-step-2.png)

### 5 - Add webhook URL to HTTP client in 1st workflow

In the first workflow's HTTP step, place the new URL within the 'URL' field. Set your 'Body type' to 'binary' and create a jsonpath from your trigger within the binary field itself: `$.steps.trigger.result.Test[0]`:
![http-binary-step-3](https://tray.ai/documentation/images/connectors/core/http-client/29680238-f2fe28dd_http-binary-step-3.png)

### 6 - Check logs in webhook-triggered workflow

Within the second workflow, once the form is uploaded again, the second webhook trigger will be notified. This is proven by the green log and output of the debug panel.
The file itself, having travelled in binary format, can be found under the `"body"` key in the output panel.
Regardless of the original format, the data type will now be string. All the data from the original file will now be available to view in a single line of output, as displayed below:
![http-binary-step-3-output](https://tray.ai/documentation/images/connectors/core/http-client/29680238-630fd4c8_http-binary-step-3-output.png)

### Multipart file uploads

Note that files can also be uploaded in multiple parts when using the `form-data` option.
This is found within the 'Body' type field.
![http-form-data](https://tray.ai/documentation/images/connectors/core/http-client/29680238-9521900d_http-form-data.png)
