Leveraging Hasura to GraphQL’ify a (Trello) API

Maxwell Struever
9 min readAug 5, 2023

--

Overview

Trello is one of my favorite day-to-day productivity apps. I use it for everything; projects at work, personal and business to-do lists, a recent apartment hunt with my wife, and our shared grocery list.

Trello has a great and easy-to-work-with API. I’ve used it a bunch to automate certain parts of interacting with Trello. For example, we set up a small app to track errors from our data platform pipelines in a Trello board, so a data engineer can come in and easily view a Trello board and see what needs attention.

Hasura is also one of my favs, but for building apps (both on a personal side project scale and at an enterprise scale for the clients I work with!) Hasura started as a tool to GraphQL’ify an existing (Postgres) database, instantly making CRUD APIs available for it. It has grown a ton and can now GraphQL’ify and combine multiple data sources, including REST APIs. Note: I also love GraphQL; here’s why.

I want to demonstrate how Hasura can take an existing API and incorporate it into your Hasura GraphQL.

Sign up for Hasura

Sign up by email. It’s an easy, free sign-up process! The free tier will be sufficient for our needs.

Set up your Trello API key and token

https://developer.atlassian.com/cloud/trello/guides/rest-api/api-introduction/

I use a separate Trello account to act as my ‘code’ user. I add this Trello user to the boards I want it to have access to, then the API key we generate with it will have access only to those boards. For speed in setting up, you can authorize an API key in your own Trello account.

You use the API key first to request access to the boards. Then you get back an API token which you will use for all the actual API calls.

Add Trello key and token to Hasura

For safety, best to set these up as Hasura Project Environment Variables. Again, for quickness, you can just manually type these in the URLs that you’re setting up. https://developer.atlassian.com/cloud/trello/guides/rest-api/authorization/#authorization-header

Add Trello APIs to Hasura using Actions

You can add any REST API to Hasura with their Actions component. They have a new handy feature that lets you do some minor transformations of the REST API results to fit into the format Hasura would need.

You can of course add any API, and we could add each API call from Trello as a separate action in Hasura. Becuase there are so many pieces to the Trello API, I began looking around for a shortcut (as computer scientists do) to input all of them. Fortunately, Hasura has a few options. You can:

  1. Import the .json results of an existing API query (you could try out a Trello API call in Postman, and copy and paste the results)

2. Or, even better! Import the whole Trello API as an Open API spec. I found a page on the Trello API docs where you can export it all as an OpenAPI: https://developer.atlassian.com/cloud/trello/rest/api-group-actions/#api-group-actions

Note: you need to click ‘Create’ on each API call you want to import; it seems there is no ‘Create all’ button at this time. To start, I selected:
- getBoardsIdCards
- getBoardsIdLists
- getCardsId
- getListsIdCards
- getMembersIdBoards

For each action, we will need to add the authentication details from our key and token in order to authenticate our API queries to Trello, as our user. The format is described here in the Trello docs: https://developer.atlassian.com/cloud/trello/guides/rest-api/authorization/#authorization-header

Note: adding these auth pieces to each Trello action we have to set up is easier to repeat/copy and paste in the code of the Hasura Metadata. So, for now, let’s just get it working in a few different places.

Let’s try it out!

The first Trello Action query should now be functional!

Let’s query what boards I’m a member of. (in the Trello API, you can just put “me” instead of your user’s actual ID)

It works! the boards are listed out, and in GraphQL fashion, we are able to pick what fields we get back in the call!

Let’s check the others (don’t forget to add the Authorization header to each action!)

Creating relationships

Querying each endpoint on its own and selecting what fields are available is cool and all, but one of GraphQL’s greatest features is how it easily handles relationships. Hasura handles this automatically for foreign key relationships when connecting to a database like Postgres, but we’ll need to do some manual setup here for Trello’s API since we’re bringing it in as an Action.

Unfortunately, in the current version of Hasura (as of July 2023), we actually have to set up a new Hasura instance to allow relationships within our Actions: https://hasura.io/docs/latest/actions/action-relationships/#action-to-action-relationships

But, we’ve already come this far, let’s try it out!

We need to create a new Hasura instance. This is possible with the same account we just created.

Go to https://cloud.hasura.io/projects and click ‘New Project’ and select Free Project.

It will set itself up quickly and launch the console.

Go to the Remote Schemas page of the new instance, we will call this our Gateway instance. Create a new remote schema and point it to the GraphQL URL of our original Hasura instance; we’ll call this our Source instance.

Note: we could get a lot more fancy with the authentication and passing JWTs or other Auth methods on from our Gateway instance to our Source. For brevity's sake, we are just going to give full admin access from the Gateway to the Source. To do this, add a new header, and have it be sourced from a new environment variable called SOURCE_HASURA_ADMIN_SECRET.

We then need to go create a new env var in our Gateway instance and make the value be the admin secret of the Source instance.

To figure out what this is, go back to the API page of our Source instance, and click ‘Show admin secret’

Source instance API view
Gateway instance environment variables list, which has the secret of the source instance.

The Gateway instance should automatically grab all of the GraphQL queries and types from the Source instance.

Now we can start creating relationships:

Let’s start with the board to lists relationship.

We want to use the ID of a Board to help us fetch the Lists that belong to that board.

The setup for our ListsBelongingToBoards relationship

After saving this new relationship, we can try out the new query. Note that the name of the relationship we created is how the sub-object will show up in the query.

Our new relationship in action (ha)

It works! We are able to get boards that belong to us, then we are able to fetch what lists belong to those boards.

We can take it another step further and create a relationship from lists to cards.

It works! and matches my actual Trello board as expected.

Performance

You may notice the relationship query takes a long time, and you even get a popup warning like this from Hasura:

This makes sense because we’re doing a lot of inefficient steps. We wanted to show off the capabilities of relationships in Hasura, so this isn’t a performant production-ready example.

Let’s look at what all is happening behind the scenes when we’re setting up these relationships and why it performs slowly when the API itself is quite fast.

In the following query:

query MyQuery {
getMembersIdBoards(id: "me") {
id
name
ListsBelongingToBoards {
name
id
CardsBelongingToLists{
name
}
}
}
}

We are asking:

  1. Gateway Hasura to first reach out to Source Hasura instance.
  2. Source Hasura then is making the first REST API call to Trello, ‘getMembersIdBoards’. That returns all of the Trello boards I belong to, which for this account is 12.
  3. We are then asking it, via the ‘ListsBelongingToBoards’ relationship, to go get ALL of the lists that belongs to each board. Because we don’t have any efficiencies baked into the process, Hasura has to make 12 separate calls to the Trello API ‘getBoardsIdLists’.
  4. After we are returned all of the lists that belong to each board, which is sometimes more than 10 per board, we are asking it with ‘CardsBelongingToLists’ relationship to fetch all of the cards that belong to those lists. That is making the getListsIdCards Trello API call once for each list in each board; this is more than 100 calls.

So, behind the scenes, with no efficiencies created, Hasura has to take inefficient steps to call each of the source APIs to return the nested relationship details that we want. This is not great, but again, we are just demonstrating the capabilities of Hasura, including another API into its Graph.

Potential areas for increasing performance

  1. If we were connecting to a source database with relationships instead of manually connecting REST APIs, Hasura would get to leverage joins and other query efficiencies on the source based on the request.
  2. If we wanted to build a source API from the ground up, we could make it in GraphQL itself (such as Apollo Server) and include that into Hasura as a remote schema, with all of the relationships built-in.
  3. Hasura lets you limit how deeply nested a query can be so that users can’t accidentally make very inefficient requests. Depth Limits
  4. For the Trello API specifically, we could add options to the API requests and only return what we want; they mention this in their own GraphQL article as “Field Narrowing” and “Nested Resource Expansion.”

Comments and next steps

Having to create a separate Hasura instance to create relationships within our ‘Actions’ was annoying, but it sounds like this is going to be improved in future versions of Hasura (note, Hasura v3 is about to be released, as of July ’23)

In Googling around, I found that Trello’s engineering team was actually looking into switching to GraphQL, but they were approaching it from the client side only. (I didn’t even know this was an option; it was cool to read about!) It sounds like the Trello team is not currently converting their API server to GraphQL, but they certainly seem interested.

I also found that someone set up a GraphQL’ified version of the Trello API, https://github.com/lukehorvat/graphql-trello. However, this works on the client side as well, so you couldn’t use other existing GraphQL client tools to query the Trello API as a GraphQL server. Still cool!

I created a repo with the metadata JSON files from each of the two Hasura instances here: https://github.com/madmaxlax/hasura-trello-graphql-conversion

--

--

Maxwell Struever
Maxwell Struever

No responses yet