Integrations vs. Actions

Integrations are standardized connections between Langdock and a third-party tool that manage authentication and enable communication via an API. Within an integration, actions can be built. These actions allow assistants to interact with specific API endpoints of the connected third-party application. Below we explain how to create an integration and configure ready-to-use actions for it.

Setting up an Integation

Within the integrations menu you can start building your integration by clicking on Build integration.

Next, you specify an integration name and upload an icon which will be shown within the chat when using an action, and in the integrations overview. You can also add a description which will be displayed in the integrations overview and help the assistant to know when to use that specific integration. Press Save to continue and create the integration.

Authentication

The first thing to set up for an integration is always the authentication. In the Build tab, you can select a general authentication type, and configure it according to the steps shown below. The following types exist:

API Key

After selecting API Key as the authentication method, you can add custom input fields (e.g. the API key or a client ID) in step 2. This input can be used in the following steps and will always be collected from a user setting up a connection for this integration. Each input field can be set to “required” depending on later usage.

Step 3 allows you to set up a simple API endpoint to test the authentication based on the input parameters entered by the user. Just replace the URL parameter in the code block, and add references to the input fields required for the request. The input fields can be accessed via data.auth.fieldId.

The existing code serves as a template. Please use the built-in ld.request and ld.log function to send requests and log responses.

Lastly, test your action and create a first valid connection.

OAuth 2.0

Custom integrations can also authenticate via OAuth 2.0.

In step 2 you can add custom input fields. This input can be used in the following steps and will always be collected from a user setting up a connection for this integration. Each input field can be set to “required” depending on later usage. As Client ID and Client Secret will be entered in step 4, this only includes additional parameters.

Create an OAuth client

Depending on the application you want to connect, you need to set up an OAuth client / App / Project in that application and enable the APIs that will be used. This is always application-dependent, which is why our integration interface allows us to accommodate individual requirements through custom code fields in step 5.

In our example, we need to create a Google Service Account. For that account we can create a new key and with that receive both the client ID of the service account, and the client secret. These can now be added to the Langdock integration in step 4. Within that service account, we now save the OAuth Redirect URL , and enable the Google Calendar API.

Change Authorization URL

Next, you have to check the respective OAuth documentation of the service you are trying to integrate and extract information about the Authorization URL .
Typically, it is enough to change the BASE_URL provided in our template.

In our example, we adapt the authorization URL to :

return `https://accounts.google.com/o/oauth2/v2/auth?client_id=${env.CLIENT_ID}&response_type=code&scope=${data.input.scope}&access_type=offline&redirect_uri=${encodeURIComponent(data.input.redirectUrl)}&state=${data.input.state}&prompt=consent`;

Define Scopes

Following this we have to define the OAuth scopes required by the actions we want to implement for that integration. The scopes can be pastesd in a comma or space separated list of values according to the API documentation of your API.

In our example, we aim to access calendar events and need some info about the user profile and mail to gain access to the user’s associate email address and preferences like the time zone. Therefore we need the following scopes, which in this case have to be listed separated by spaces:

https://www.googleapis.com/auth/calendar.events https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile

Provide Access Token & Refresh Token URL

Afterwards, check the API’s OAuth documentation again, to determine the Access Token Url and the Refresh Token Url. Typically, it is enough to change the tokenUrl provided in our template.

For Google Calendar we just have to insert

const tokenUrl ='https://oauth2.googleapis.com/token';

Test Authentication Setup

To complete the setup you can, similar to the Access Token authentication, provide a test API endpoint that returns e.g. some user information like /me .

The return value of that test request can be used inside the OAuth Client Label to influence the naming of the established connections. You can access the return value via: {{data.input}}

For Google Calendar, we use:
Google Sheets - {{data.input.useremail.value}}

With this setup, you can now add a connection and test if you are directed to the right Authorization Url, and a connection can be created.

For Google Calendar, we test the successful authentication via this endpoint:

url: 'https://people.googleapis.com/v1/people/me?personFields=names,emailAddresses'

None

For publicly available APIs without authentication choose this option.

Accessing input fields

To use input provided for the previously defined input field, you can use the accessor data.input.{inputFieldId}.

Via data.auth.{authenticationFieldId} you can reference the input values for additional authentication fields. This will return the values input for the users’ current connection.

Built-in functions for custom code sections

Within the custom code blocks that are used in step 5 (OAuth) and to test your connection, the implemented functions are being executed in a sandbox with limited available packages and pre-built functions. In the following, we explain which functions are available and how they can be used within the custom code blocks to successfully setup authentication with the application you want to integrate. Please make use of these native function

Basic functions

The custom client library ld contains the basic needed functionality for implementing an authentication flow.
ld.request() creates a web request in the format specified by the passed object and returns the response. The parameters passed to this function should be valid JSON objects, as the JSON.stringify() function is called within. Accordingly, for complex JSON objects, you may need to apply JSON.parse().

ld.log() logs the passed values into the Logs field. This field is visible below the Testaction button after testing an action.

Example usage from the Google Calendar integration:

const options = {
  method: 'GET',
  url: `https://www.googleapis.com/calendar/v3/calendars/${data.input.calendarId}/events/${data.input.eventId}`,
  headers: {
    'Authorization': 'Bearer ' + data.auth.access_token,
    'Accept': 'application/json',
  },
};

const response = await ld.request(options);

return response.json;

JSON

Both JSON.stringify(), converting a Java Script JSON object into a string, and JSON.parse(), converting a string into a Java Script JSON object, are usable in the custom code blocks.
The parameters passed to the ld.request() function must be valid JSON objects, as JSON.stringify() is called within it. Accordingly, for complex JSON structures, you may need to apply JSON.parse() beforehand.

Example usage from the HubSpot integration:

const properties = data.input.properties
  ? JSON.parse(data.input.properties)
  : {};

const options = {
  method: 'PATCH',
  url: `https://api.hubapi.com/crm/v3/objects/companies/${data.input.companyId}`,
  headers: {
    'Authorization': 'Bearer ' + data.auth.access_token,
    'Content-Type': 'application/json',
  },
  body: {
    properties: properties,
  },
};

Base 64

As some OAuth clients require you to encode you client id and secret in Base64 to use Basi authentication, we created a function that does exactly this.

btoa() Base64 encodes a string, atob() decodes a Base64 encoded string.

Example usage:

const auth = btoa(`${env.CLIENT_ID}:${env.CLIENT_SECRET}`);

Usability Recommendations

To make actions more usable within assistants we recommend thinking about the following aspects:

Id handling

For most API calls, specific internal ids are required. Passing them as parameters can be required for actions like getting a specific contact in HubSpot or adding an event to a specific calendar in Google Calendar.

Therefore, we recommend creating helper actions that get these pieces of information and return them to the assistant, so that the assistant then can use them for other API calls. An example of this is the Get deal context function for Hubspot, which uses GET endpoints to gather information about internal ids for available pipelines and stages, which enables an assistant to use other actions like Create deal or Update deal more effectively and usable.