Managing multiple domain name providers with Kendraio App

Donald Newholm
Kendraio
Published in
10 min readAug 31, 2023

Introduction

At Kendraio, we are experimenting with a way to help people manage all of their domains, across multiple domain providers, in one place.

Currently, users of domain providers can manage multiple domains within one account (for example, their GoDaddy account). However, what they can’t do is manage multiple domains from multiple different providers in one place. There are a few reasons why someone might want to do this:

  • Entrepreneurs with multiple businesses might want to have separate domain provider accounts for each business (for billing purposes). They could benefit from being able to manage multiple domain provider accounts in one place.
  • Domain providers have different deals and specialities, consequently certain domains can only be registered with certain providers. This could lead to having multiple accounts with different providers. In this case, people could benefit from being able to manage multiple domain provider accounts in one place.

In this article we’re going to focus on how to integrate a specific domain provider, Dynadot, with Kendraio App. Our intention is to demonstrate an interface that enables a user to view domains from two different Dynadot accounts within Kendraio App. A single Dynadot account already allows users to manage multiple domains, but does not allow users to manage multiple accounts.

If you use Dynadot, it’s simple enough to log into their platform and inspect your data there. But if you’ve registered multiple domains under different accounts, you can’t see all your domains at once. In this article we show that by using Kendraio App to interface with the Dynadot API, you can list all your domains from multiple accounts in one place. The idea is to have a simple and user-friendly interface that enables you to fetch, display and sort your domain data with flexibility.

Below is a complete guide to building your own Kendraio Flow that will take two Dynadot API keys and display the results in a neat grid. The completed Flow, which you can try out straight away, is available here:

https://app.kendra.io/domains/doubleDynadotDomains

Instructions

Open your browser and head to https://app.kendra.io. We’ll use Kendraio App to put together a Flow that lists your Dynadot domains. When you first land on the page, it should look like this:

On the top left hamburger menu, click Flow Builder. You can now hide the Flow menu by clicking the hamburger again — we don’t need that anymore. This should give you fresh blank page, thus:

If you can see anything other than the above blank page, click the top right cog to display the Flow Builder. You can clear the Flow by clicking the bin icon. Keep the Flow Builder open — we’ll need it throughout.

Flows are built using tasks. You can think of each task as a link in a chain, passing information from top to bottom, transforming the data as needed on the way.

First of all, we need an Initialisation. This will tell the Flow to get started as soon as the page is loaded, any time you need to use this Flow. In the Flow Builder, click on Add Task to open the Task Menu. Pick Initialisation and then click on Add Task.

The popup should close and you will now see that the Flow contains an Initialisation.

You can click on it for further information. Since there are no options for an Initialisation, all you can see here is space for a comment, along with buttons to Update and Delete the Initialisation task.

Now onto the job at hand. In order to display data, we must first fetch it from the Dynadot API. To get the data, you’ll first need to give the API your security key. To input your security key we’ll use a Form task. Click on Add Task again and select Form, then Add Task again to close the popup.

Expand the Form task to see its settings. Tasks are configured with JSON, which is a standard text-based format for representing structured data for storing and accessing information by name. Replace the current JSON with:

{
"type": "form",
"jsonSchema": {
"type": "object",
"properties": {
"authkey1": {
"type": "string",
"title": "Key 1"
}
}
},
"uiSchema": {}
}

This adds a Form field to pass our Dynadot key to the API. Once you click Update, your Flow should look like this:

Let’s try out our Form. Grab your key from Dynadot and paste it into the Key field. Click Submit and the Form will save the field’s contents under the name authkey1. It is worth noting that Kendraio App is a Progressive Web App, which means all the code runs locally on your browser and data is never sent anywhere, even to Kendraio’s own server.

Before we send the key to the Dynadot API, let’s make sure our Form is working. Click on Add Task and select Debug. This task displays the Kendraio App’s data at that point in the Flow. Click the dropdown arrow next to data: Object and you’ll see your API key.

Your key is only stored under the name authkey1 because that’s how we set up the Form. You can call it whatever you want, and it will show up here under that name.

Right! Now that we know our Form is working, let’s send the key to the Dynadot API. Click on Add Task and choose HTTP Request. Expand the task and replace the JSON with this:

{
"type": "http",
"method": "get",
"endpoint": {
"protocol": "https:",
"host": "api.dynadot.com",
"pathname": "/api3.json",
"query": {},
"valueGetters": {
"query":
"data.{command: 'list_domain', key: join('', [authkey1])}",
"dummy": ""
}
},
"useProxy": true
}

This tells the task to take your API key (stored in the browser as authkey1) and carry out an HTTP Request to the specified endpoint: in this case, the Dynadot API. Let’s see if it’s working — use the drawbars on the Debug task to move it down to the bottom of the chain. Expand data: Object and you should see something along these lines, where each Array entry represents one of your domains:

Great, it’s working. But why view our data this way when we can use a nice grid? Grab a Data grid from the Task Menu. Once you collapse the Debug Object, your Flow should look like this:

Our Data grid tells us we have No Rows To Show. In order to make our data available to the Data grid, we need one final task: Mapping. Add the Mapping task from the Task Menu and move it between the Debug and Data grid tasks. Your Flow display won’t look any different — the Mapping manages the previous task’s data and passes it along the chain, and as such has nothing to display.

In order for the Mapping to prepare the data for the Form, we need to give it some data it can use. We can see from the Debug task that the data we want to display is stored at:

data.ListDomainInfoResponse.MainDomains

Paste this into the Mapping task and click Update, and you should see some action in your Data grid. It should now look something like this:

Okay! Technically, we’ve succeeded in our aim. But it doesn’t look great. Let’s get rid of the columns we don’t want to see right now. Let’s keep it simple and stick to displaying the name, registration and expiration of each domain. In order to do this, we need to amend our Mapping JSON. Open up the Mapping and replace what’s there with:

data.ListDomainInfoResponse.MainDomains[*].[
Name,
formatDate(
parseUnixTimestamp(to_number(Registration), 'ms'),
'yyyy/MM/dd'
),
formatDate(
parseUnixTimestamp(to_number(Expiration), 'ms'),
'yyyy/MM/dd'
)
]

Now we should see a much more readable Data grid.

However, there’s a problem — the column names are taken straight from the data object, where the values are stored by number, not name. But don’t worry — we can set the Data grid to use whatever heading names we like.

Expand your Data grid and replace the JSON with:

{
"type": "grid",
"gridOptions": {
"pagination": true,
"paginationPageSize": 20,
"defaultColDef": {
"sortable": true,
"resizable": true
}
},
"columnDefs": [
{
"field": "0",
"headerName": "Domain"
},
{
"field": "1",
"headerName": "Created"
},
{
"field": "2",
"headerName": "Expires"
}
]
}

Once you click Update, you should see the Data grid columns are now headed by our chosen labels. It should look like this:

This is great — but so far, we haven’t done anything we can’t do on the Dynadot site. Let’s put our second key in the mix.

Another key needs another Form field. Expand the Form task and duplicate the authkey1 property, then change its name to “authkey2” and its title property to “Key 2”. Here’s the full JSON:

{
"type": "form",
"jsonSchema": {
"type": "object",
"properties": {
"authkey1": {
"type": "string",
"title": "Key 1"
},
"authkey2": {
"type": "string",
"title": "Key 2"
}
}
},
"uiSchema": {}
}

Let’s make sure our Form is processing both keys correctly — enter your two keys into the Form and click submit, then bring the Debug task up to directly follow the Form. Click the expand arrow next to data: Object and you should now be able to see both of your authkeys.

The HTTP Request that follows will only deal with our first key, so we need to save our second key to the Context for future use. The Context is a local store that keeps track of Kendraio App’s data on your browser. It is cleared on page refresh. To save to the Context, we need a new task, called Context and State Save. Put one of these after the Form and change its JSON to:

{
"type": "context-save",
"key": "authkeys"
}

We also need a Context and State Save after the HTTP Request. Change the JSON to:

{
"type": "context-save",
"key": "domains1"
}

Now that we’ve saved the first list of domains, we are ready to make our second HTTP Request. Add a new HTTP Request task after the second Context and State Save and replace its JSON with:

{
"type": "http",
"method": "get",
"endpoint": {
"protocol": "https:",
"host": "api.dynadot.com",
"pathname": "/api3.json",
"query": {},
"valueGetters": {"query":
"context.authkeys.{command: 'list_domain', key: join('', [authkey2])}",
"dummy": ""
}
},
"useProxy": true
}

This pulls the second authkey out of storage in the Context and uses it to retrieve the second list of domains from the Dynadot API. Click submit on the Form to run both HTTP Requests. Finally, let’s have our Mapping format both lists of domain names for display in the Data grid. Open the Mapping and change the JSON to:

[
context.domains1.ListDomainInfoResponse.MainDomains[*].[
Name,
formatDate(
parseUnixTimestamp(to_number(Registration), 'ms'),
'yyyy/MM/dd'
),
formatDate(
parseUnixTimestamp(to_number(Expiration), 'ms'),
'yyyy/MM/dd'
),
`1`
],
data.ListDomainInfoResponse. MainDomains[*].[
Name,
formatDate(
parseUnixTimestamp(to_number(Registration), 'ms'), 'yyyy/MM/dd'
),
formatDate(
parseUnixTimestamp(to_number(Expiration), 'ms'), 'yyyy/MM/dd'
),
`2`
]
][]

Not only does this supply both sets of domain names to the Data grid, but it adds a new column to distinguish the two sets. To show the new column in the Data grid, expand the Data grid task and add the following at the bottom of the columnDefs list:

{
"field": "3",
"headerName": "Key"
}

This should show up in your Data grid. Here’s the final display:

If you’d like to change the order of the columns, you can do this by renumbering the fields in the Data grid task and reordering the list in your Mapping. In fact, you can customise it any way you like — that’s the point!

Conclusion

We hope you have enjoyed this demonstration of Kendraio App as much as we enjoyed putting it together. A useful future step in the development of this Flow would be to integrate API keys from different domain providers. Say for example you were managing some website domains through Godaddy, some through Namecheap and some through Dynadot. The dream is that by integrating all of these APIs with Kendraio App, you could manage all of these accounts in one place. Awesome, eh?

Listing domains is just one job that Kendraio App can accomplish — please let us know what you would like to see it do next, and we’ll try to make it happen. We’re still experimenting with many aspects of Kendraio App and we’d love to know what you think about our Dynadot Flow and the interface in general.

To stay updated on Kendraio’s developments and initiatives, please subscribe to our newsletter and follow us on socials.

Subscribe to newsletter

Follow us on Instagram

Follow us on X (Twitter)

Follow us on LinkedIn

Follow us on Facebook

--

--