No connectors? No problem!
Tags: programming, integration, softwaredevelopment, lowcode
Published: 2021-10-26 12:13:47

---
title: No connectors? No problem!
published: true
date: 2021-09-22 14:18:10 UTC
tags: Programming,Integration,SoftwareDevelopment,Lowcode
canonical_url: https://linx.software/no-connectors-no-problem/
---

**_TL,DR Wouldn’t it be cool if all these new PAAS/SAAS platforms had a “connector” for building custom “connectors”?_**

In the low-code/no-code space, development teams implement standard integrations as “plugins” or “connectors” which allows non-technical users to port data from one system to another with limited technical know-how. Some examples of these plugins are the Linx GoogleDrive and Xero plugins or Outsystems DropBox connector.

The terms “connectors” or “plugins” are used interchangeably, and there’s some debate on what exactly defines them. In practice, these refer to pieces of functionality that allow you to send and receive data from your custom system or platform to another. The advantage of these is that different companies specialise in what they’re good at; for example, Xero handles the accounting, Shopify manages the sales and Hubspot can manage the marketing. 

However, the issue is that these systems do not natively talk to one another, which leads to your different pieces of data being stored in different formats and scattered across platforms. Typically, this leads to manually retrieving the various parts and reconciling them in spreadsheets of some kind, which defeats the purpose of having these specialist systems.

With the emergence of APIs, these platforms can now programmatically expose your data, allowing you to pull and push the required details as you wish by using “connectors”. These are standard integration functions wrapped in a pretty interface and are typically achieved via an HTTP request to a REST API. However, the end-user only has to configure some inputs and doesn’t view the nitty-gritty details.

Most of the integrations that users are looking to use deal with connecting to major 3rd party platforms such as Microsoft, Google, Xero etc. These connectors allow users to extend those systems functionality and add them into their business logic. The advantage of this is that the developers have taken care of the difficulties in connecting to these systems and handling the various nuances such as authentication, data validation and error handling. 

However, a disadvantage is that connectors need to be built by the platform’s in-house development team, and this means that connectors that are high on your priority list might not be a priority for them. Additionally, you have no idea of timelines, and developers often need to design and build these connectors to handle every situation that can take time and is usually overkill.

Finally, these low-code platforms contain other functionality not related to HTTP connectors that are also being developed by the in-house teams, such as API hosting or Database integrations, meaning connectors to your particular platform might fall low on the list of priorities.

Once you’ve decided to go with a particular platform, you may run into the issues mentioned above, and your project may become stalled as you wait for the specific connector to be designed and implemented on the chosen platform. 

But Wouldn’t it be cool if these platforms had a “connector” for building custom “connectors”?


## Can you customise customisation?
With Linx, you can build custom connectors that suit your needs and aren’t overly complicated. As mentioned earlier, these connectors are just HTTP requests wrapped in a pretty interface that handles the nuances of the different APIs, making life much easier for non-technical users. However, as you build on low-code platforms, you gain technical expertise in the various systems.

If you delve into REST APIs, they’re not as complex and scary as they seem once you get the basics which are pretty much:
* [Authentication](https://linx.software/designing-and-building-a-server-side-application-for-the-secure-generation-and-storage-of-access-tokens/)
* Sending data correctly
* Handling the response data

And that’s pretty much it!

Each system will have its subtle differences, but the approach is the same. Once you’ve figured out how to implement a single request to a chosen API, all the other requests that you want to implement will follow pretty much the same structure in terms of authentication, URLs and data objects.

To give you an example, we recently started developing a sample [Linx Solution](https://github.com/linx-software/github-api-connectors) that integrates with the [GitHub REST API](https://docs.github.com/en/rest). I did this to make my own life a bit easier, managing and automating all our GitHub DevOps for the Linx Sample Library and providing users with a quick way of integrating with their instance of GitHub. And in the spirit of development, why rebuild something that someone else has already built? 

So with this in mind, I chose to implement much of the GitHub API as custom Linx functions, which can act as “connectors” that anyone can download and install in their Linx Solution. The advantage of this is that our development team can focus on other technologies.

At the same time, I build out the various “connectors” – and external users can then even extend these connectors to their custom needs without having to go through code reviews, feature requests and testing of every single piece of functionality.

When building a “connector” function, I structure them all the same:

![REST endpoint](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tsxitn79bockntg9mkb1.png)

REST endpoint
1. The ‘Endpoint’ contains the particular suffix of the URL to call.

2. The ‘CallRESTEndpoint’ function makes a request to the endpoint.

3. And the ‘ReturnResult’ function returns the result of the HTTP request as an output of the custom Linx function.

To further illustrate, I followed the below flow (I’ve used [this API request](https://docs.github.com/en/rest/reference/repos#list-repositories-for-the-authenticated-user) to the GitHub API as an example):


## Check out the API reference documentation 
First, you need to know the details of the endpoint you are calling, such as:
* The URL (endpoint) of the operation
* Request authentication
* Request parameters (such as query values, body etc.).
* Response data object.

So, I would go to the particular page of the request, like [this one](https://docs.github.com/en/rest/reference/repos#list-repositories-for-the-authenticated-user). 

Now depending on the level of documentation (some platforms Like GitHub are excellent in this regard), you’re able to set up an HTTP request easily without actually having to make test calls. From the documentation, we can find the method (GET) and the URL to call (/user/repos):

![repositories](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hf2sxdqa9mgulxkkd8t8.png)


## Configure the minimal request structure
With my structure, I can make the value of ‘Endpoint’. This just makes changing the endpoint in future functions much more effortless.

![properties](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y8w9ks4iuy7extt0iuma.png)

This endpoint ‘/users/repos’  is appended to the main GitHub API URL, ‘https://api.github.com’. Because all endpoints would use this base URL, I can just make it Setting in my Linx Solution:

![settings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l39kob0znh4fqu8j5h61.png)

I can then just reference this Setting value across all my functions. If this URL changes in the future, I can just change it in a single place and have solution-wide effects.

To make an actual call to the API, which requires the method and URL at a minimum:

![REST properties](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vmvvvhm3mexyd0rheopb.png)

So at runtime, the above URL property would translate into “‘https://api.github.com/users/repos”.

## Add authentication to the request
I now need to configure the authentication achieved by passing an ‘Access Token’ in the request’s header. Of course, now all the requests need the header; however, the value of the ‘access token’ might change or be retrieved as runtime, so I can create an input parameter that will receive this value.

![access token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xchxhb0z1i9dyjx2d41b.png)

In the CallRESTEndpoint configuration, you can reference this value.

![authorisation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ik9cw30tdcu67sv84lpv.png)

## Add any request parameters
Configure any parameters like they are specified in the documentation.

![request parameters](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ynkpf1xe95k4wvg9m6p0.png)

For any needed parameters, I just make them input parameters to my custom Linx function, just like I did with the access token.

![parameters](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hi1pr1b7kvvlurq7bck0.png)

I then add these as the actual query parameters of the request, which is simple enough….

![query string](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sxfr7opiwf4o8sy7nqdj.png)

## Make a test request
We’ve now configured the URL to call, the authentication details and then any query parameters. As it stands, my function will execute the request and return the response as one big string

![one big string](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d0oxu7afrhtmk4txhofk.png)
Not very nice.

To fix this, I’ll create an object that can be used to structure this string.


## Import the needed response data structure
With Linx, this is much easier than you would think. Simply copy the whole response

![copy the response](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8zzcy9ez69lqqggnwl93.png)

and import it as a custom Linx type
![custom type](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p2eqxk1lyomvr4np6n86.png)

And Linx will then create the needed structure

![required structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pk4mpd9d1ohop5arpdou.png)

Now that you have a structure to work with, you can use it to deserialise the response. You can use this structure as an output result of my custom function

![result fields](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/asso6a3uof51dxp2vdh8.png)

And assign the value of the HTTP response to the output of the function

![properties](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y2rmy0y6v2iy8zpnwnmn.png)

And voila! You now have the response structured as the result of your function

![structured response](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yuuyz784d53166v3uiud.png)

![detailed response](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1pd06nc8vz2kfrm8xziq.png)

So in practice, you can just drag the reusable function into other pieces of functionality, and it will act like a “connector”. And you can re-use this function as much as you like, wherever you like.

![connector](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e9bo8s7z6cone638potl.png)


## Rinse and repeat
With Linx, once you’ve created a piece of functionality, you’re able to copy that functionality and tweak it to your needs while not having to re-do much of the shared configuration.

Copying this functionality is as easy as ‘Right click -> Copy -> Paste’.  And an exact copy of the function will be created, which you can then just tweak accordingly.

![Repeated endpoint connector](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oq6hb8sv7wfedrx8vl79.png)


For instance, the above example returns all the repositories for the authenticated user. But what if I wanted to retrieve a single repository like it’s specified in this operation of the documentation?

I can just copy the whole ListReposForAuthenticated user and just tweak the process as needed. You will need to change some input parameters (the access token remains as remember you need it for each request)

![Input parameters](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iwvsyk1mi9beztq0ydra.png)

And alter the endpoint like below

![Endpoint properties](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7h97mof9gsbr8zlaacmj.png)

For the actual request, you can remove all the query parameters. The URL and authentication don’t need any changing as this was designed to be generic. Finally, you can change the result of the function to be a single item and not a list.

![not a list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/26hwwksy01guhyh6fnpe.png)

And you’re done! Don’t forget to change the name of the function to be more descriptive.

![GetRepisotory REST call](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3mefoq5savrsacppwis6.png)

You can then follow the same method across all the other endpoints. Because of the generic design in terms of the URL and authorization, adding operations is relatively simple, ending up with a whole range of “connector” functions that anyone can re-use:

![Connector functions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z90qbwfsmhzz32gus2ng.png)

These “connector” functions are reusable Linx functions that handle the inputs for the particular requests, makes an HTTP request to the GitHub API using the generic [CallRESTEndpoint pre-built function](https://linx.software/docs/reference/plugins/rest/content/callrestendpoint/) and then parses the response data and returns it as an output of the function.

Thus, each of these functions acts as a “wrapper” for the particular request, and you can just drag and drop the specific function as you wish into your logic:

![Function wrappers](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3i849bmet6xhojdqz6mz.png)

Take a look at the final [GitHub API connectors](https://github.com/linx-software/github-api-connectors) project or my other [Microsoft Graph API connectors](https://github.com/linx-software/microsoft-graph-api-connectors) project for a similar example.



The post [No connectors? No problem!](https://linx.software/no-connectors-no-problem/) appeared first on [Linx](https://linx.software).