R API for Trello

Jakub Chromec

2016-09-22

This document explains how to retrieve data from public and private Trello boards using trelloR.

NOTE. Right now, only GET requests are implemented. Support for POST and PUT may be added in later versions. Accessing the data in private boards requires authorization which you can read about in the Getting private data section.

Getting public data

The basic building block of the Trello workflow is a Board. It encapsulates a hierarchy of “models”, i.e. Members, Teams, Lists, Cards, Labels, Checklists and Actions. Each model has a parent model (e.g. a board is a parent model for cards on it) and child models (a card can include comments as child models). The models can be accessed recursively. This means that you can obtain the actions from all cards by addressing the whole board without going through specific cards one by one.

To access a particular model, you need to know its unique ID, or the ID of its parent model. In some cases (e.g. with boards or cards), you can use the model URL instead. This is useful because a URL can be found in your browser address bar (unlike ID). You can also obtain model ID by “searching”, which you can read more about later.

Here is an example how to get the data from Trello Development Roadmap. Since it’s a public board, no authentication is required:

library(trelloR)
#> R API for Trello
#> Disclaimer: trelloR is not affiliated, associated, authorized, endorsed by or in any way officially connected to Trello, Inc. (www.trello.com).
url = "https://trello.com/b/nC8QJJoZ/trello-development-roadmap"
idb = get_id_board(url = url)
#> Sending request...
#> Request URL:
#> https://api.trello.com/1/board/nC8QJJoZ?fields=name&limit=1000
#> Received 1 results
#> Returning tbl_df tbl data.frame
#> Converted into character vector of length 1 with name "Trello Development Roadmap"
cards = get_board_cards(idb, limit = 5)
#> Sending request...
#> Request URL:
#> https://api.trello.com/1/board/4d5ea62fd76aa1136000000c/cards?limit=5
#> Received 5 results
#> Returning tbl_df tbl data.frame

The above example uses get_id_board() to get the board ID based on its URL. Board ID is then supplied to get_board_cards() which fetches card-related data. The limit = 5 parameter just means that only the 5 newest cards will be returned.

If there are no complaints from the server, a JSON response is received and converted into a data.frame. It will look something like this:

cards
#> Source: local data frame [5 x 32]
#> 
#>                         id checkItemStates closed         dateLastActivity
#>                      <chr>           <lgl>  <lgl>                    <chr>
#> 1 57bc9cdff5ceb056e765b915              NA  FALSE 2016-09-09T03:47:55.480Z
#> 2 57bc991ee084b9a0d3dc1be6              NA  FALSE 2016-08-23T18:50:58.882Z
#> 3 57bc99a9f265c7c5f76ca4dc              NA  FALSE 2016-08-23T18:51:10.636Z
#> 4 57bc9a601c9a74dc1d63cdf4              NA  FALSE 2016-08-23T18:51:04.104Z
#> 5 576afe49c8854e12d1279e32              NA  FALSE 2016-08-23T18:51:25.042Z
#> Variables not shown: desc <chr>, idBoard <chr>, idList <chr>,
#>   idMembersVoted <list>, idShort <int>, idAttachmentCover <chr>,
#>   manualCoverAttachment <lgl>, idLabels <list>, name <chr>, pos <dbl>,
#>   shortLink <chr>, due <lgl>, idChecklists <list>, idMembers <list>,
#>   labels <list>, shortUrl <chr>, subscribed <lgl>, url <chr>, badges.votes
#>   <int>, badges.viewingMemberVoted <lgl>, badges.subscribed <lgl>,
#>   badges.fogbugz <chr>, badges.checkItems <int>, badges.checkItemsChecked
#>   <int>, badges.comments <int>, badges.attachments <int>,
#>   badges.description <lgl>, badges.due <lgl>.

Typically, the response will contain multiple columns including model ID, name and other data, such as attachments or preferences. Because the ID of child elements is included in the response, you can use it to work your way down the hierarchy until you reach the desired model.

Fetching specific models

trelloR includes a number of data-fetching functions each of which targets one single model. This puts certain limits on what you can ask for; on the other hand, it eliminates most of the effort (and makes the code easier to read). It also means that the functions can have predictable names which are easy to guess. For example:

Basically, the parent model is always followed by the child model with the get_ prefix in the beginning. For an overview of the available functions, call ?get_board, ?get_card, ?get_team, ?get_member, get_list or ?get_id.

Searching for model ID

Sometimes you don’t know the model ID but you have other information, such as name, description or other text. In such cases, you can call trello_search(), which is equivalent to the search field in Trello web app. To limit your search to specific models (e.g. only members), call the appropriately named version of the search function:

captain = trello_search_members("Captain America", token = my_token)

Searches need to be authorized; hence, the token argument is needed (see Getting private data).

Custom requests with trello_get()

Most of the functions in this package are wrappers for trello_get(). You can call it directly if you lack a particular data-fetching option, or you can define a new function by wrapping trello_get() and providing some default values.

The following example creates a function that fetches all updates made in a given card (it uses a filter because updates are a type of action, and there’s no need to retrieve all actions):

get_card_updates = function(id, ...) {
    trello_get(parent = "card", child  = "actions", id = id, filter = "updateCard", ...)
}

Such functions can be called the usual way by supplying a card ID:

idc = cards$id[1]
card_updates = get_card_updates(idc, limit = 5)
#> Sending request...
#> Request URL:
#> https://api.trello.com/1/card/57bc9cdff5ceb056e765b915/actions?filter=updateCard&limit=5
#> Received 2 results
#> Returning tbl_df tbl data.frame

For a detailed list of all possible queries, consult the Trello API reference.

Additional arguments for trello_get()

If bind.rows = FALSE, the result will be a list with as many elements as there are pages. This is also a fallback option for the rare occasion when the responses are not perfectly formatted and make dplyr::bind_rows fail.

When calling trello_get() directly, you have an option to either specify parent and child or provide the whole URL as a character vector of length 1.

board_comments = trello_get(parent = "board", child = "actions", id = idb,
                            filter = "commentCard", limit = 5)
#> Sending request...
#> Request URL:
#> https://api.trello.com/1/board/4d5ea62fd76aa1136000000c/actions?filter=commentCard&limit=5
#> Received 5 results
#> Returning tbl_df tbl data.frame

Error handling

If a request fails because of the client-side or server-side error, the error code is reprinted in the console. Additional server messages are also included to make debugging easier. See the example with invalid card ID below:

tryCatch(
    expr  = get_card_actions(id = "I_have_a_bad_feeling_about_this"),
    error = function(e) {
        print(e$message)})
#> Sending request...
#> Request URL:
#> https://api.trello.com/1/card/I_have_a_bad_feeling_about_this/actions?limit=1000
#> [1] "Client error: (400) Bad Request : invalid id"

In case of a server-side error, the request will be re-send two more times, with 1.5s delay before each attempt. If it fails for the 3rd time, the error message is printed in the console.

Getting private data

Access to private boards requires authorization. This is done by registering an “app” that uses a secure token to communicate with the Trello API. Supplying the token to data-fetching functions will allow you to retrieve data from private boards under the condition that the user who authorized the app has the right to access them.

To create a token, login to Trello and visit the Developer Start Page. There you can get your developer credentials, i.e. your “key” and “secret”. Then, call the trello_get_token() function to create a token for your project. This will also trigger first-time authorization in the browser (you only have to do it once):

my_token = trello_get_token(your_key, your_secret)

You will also be offered an option to store the authentication data in your working directory, in a hidden '.httr-oauth' file.

NOTE. Make sure you keep your credentials in a safe, non-shared location.

Using the token to retrieve private data

One thing you can do immediately after obtaining the token is call get_my_boards() to get an overview of your boards. It accepts the token as its only argument and returns a data.frame with the board names and IDs related to the user who authorized the app.

my_boards = get_my_boards(my_token)
Disclaimer

trelloR is not affiliated, associated, authorized, endorsed by or in any way officially connected to Trello, Inc. (www.trello.com).

Built with
sessionInfo()
#> R version 3.3.1 (2016-06-21)
#> Platform: x86_64-pc-linux-gnu (64-bit)
#> Running under: elementary OS Freya
#> 
#> locale:
#>  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
#>  [3] LC_TIME=cs_CZ.UTF-8        LC_COLLATE=C              
#>  [5] LC_MONETARY=cs_CZ.UTF-8    LC_MESSAGES=en_US.UTF-8   
#>  [7] LC_PAPER=cs_CZ.UTF-8       LC_NAME=C                 
#>  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
#> [11] LC_MEASUREMENT=cs_CZ.UTF-8 LC_IDENTIFICATION=C       
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#> [1] trelloR_0.1.0 httr_1.2.1   
#> 
#> loaded via a namespace (and not attached):
#>  [1] Rcpp_0.12.6     digest_0.6.10   dplyr_0.5.0     assertthat_0.1 
#>  [5] R6_2.1.3        jsonlite_1.1    DBI_0.4-1       formatR_1.4    
#>  [9] magrittr_1.5    evaluate_0.9    stringi_1.1.1   curl_2.0       
#> [13] rmarkdown_1.0   tools_3.3.1     stringr_1.0.0   yaml_2.1.13    
#> [17] htmltools_0.3.5 knitr_1.13      tibble_1.0