Batch Requests with the Trello API

I write about the Trello API a lot.  So much that I’ve already noted that I write about it a lot. I keep coming across new stuff, though, so I’m going to keep writing about it.

My latest experiment was a look into using their batch call, which I don’t see a lot of documentation about so I figured was worth writing up.

Batch functionality lets you fire off a series of GET requests (and they have to be GET requests) as one request.  Depending on your code and what requests you’re making (and what data you’re getting back), this should speed things up a bit.  My test script went from running in 37 seconds to 20, for example.

In an extremely simple (and pretty much useless) case, you could replace GET calls to /1/members/me and /1/boards/511e8c0101d3982d05000d5b with a single batch call, /1/batch?urls=/members/me,/boards/511e8c0101d3982d05000d5b.

As shown, /1/batch takes the URLs parameter, a comma-separated list of the calls you want to make, minus their version number prefix.

Of course, this means you get only a single response back, and it looks a little different from a normal response.  The response is an array of objects – but not of the normal response objects you might expect.  Instead, it’s an object with a single property, with a name set to the HTTP response code of the request.

So if your first request was to /1/boards/511e8c0101d3982d05000d5b, a normal response would start as follows:

stdClass Object
(
    [id] => 511e8c0101d3982d05000d5b
    [name] => Welcome Board

The batch version of that response would look like this:

Array
(
    [0] => stdClass Object
        (
            [200] => stdClass Object
                (
                    [id] => 511e8c0101d3982d05000d5b
                    [name] => Welcome Board

Obviously that’s simplified, I just don’t think it’s necessary to show the whole response.

One nice little gotcha with that response and working in PHP is handling a numeric property name, which is done by putting curly braces around the number, as seen in the code to follow.

Lets say you want to get the names and IDs of all the boards you’re assigned to and the names and IDs of all of the lists on each of those boards.  Without batching, you could do the following:

  $trello = new trello_api($GLOBALS['config']['key'], $GLOBALS['config']['secret'], $GLOBALS['config']['token']);

  $data = $trello->request('GET', '/1/members/me');
  foreach ($data->idBoards AS $board_id) {
    $board_data = $trello->request('GET', ('/1/boards/' . $board_id));
    echo '<p>' . $board_data->name . ': ' . $board_id . '</p>';
    echo '<ul>';

    $list_data = $trello->request('GET', ('/1/boards/' . $board_id . '/lists'));
    foreach ($list_data AS $list) {
      echo '<li>' . $list->name . ': ' . $list->id . '</li>';
    }

    echo '</ul>';
  }

  unset($trello);

With batching, that becomes this:

  $trello = new trello_api($GLOBALS['config']['key'], $GLOBALS['config']['secret'], $GLOBALS['config']['token']);

  $batch = array();

  $data = $trello->request('GET', '/1/members/me');
  foreach ($data->idBoards AS $board_id) {
    $batch[] = ('/boards/' . $board_id);
    $batch[] = ('/boards/' . $board_id . '/lists');
  }

  $data = $trello->request('GET', ('/1/batch?urls=' . implode(',', $batch)));
  for ($n = 0; $n > count($data); $n += 2) {
    echo '<p>' . $data[$n]->{200}->name . ': ' . $data[$n]->{200}->id . '</p>';

    echo '<ul>';

    foreach ($data[($n + 1)]->{200} AS $list) {
      echo '<li>' . $list->name . ': ' . $list->id . '</li>';
    }

    echo '</ul>';
  }

  unset($trello);

This assumes that the API will respond with a 200, of course.

As I said, I didn’t see a ton of documentation about batch calls in the Trello API.  This is a stupid simple example but I thought it was worth putting out there.


Update, 8/6/2019: It’s been nearly five years since I wrote this post but a question came up yesterday in the Trello Community Slack and I wanted to add to this to specifically call out something I glossed over.

As noted above, the /batch call expects a set of API endpoint URLs to be provided as values of its urls parameter.  When those URLs are things like /members/me and /boards/511e8c0101d3982d05000d5b, as in my example, simply comma-separating them works just fine.

But what if your API endpoint URL has parameters of its own, such as /cards/560bf4dd7139286471dc009c?fields=badges,closed,desc?

Adding that as is to your urls parameter won’t work because both urls and fields are comma-separated and it’s not smart enough to deal with that.

In that case, we need to switch to providing the values of fields individually and also URL encode the resulting value for use in the urls parameter.

The URL /cards/560bf4dd7139286471dc009c?fields=badges,closed,desc would become /cards/560bf4dd7139286471dc009c?fields=badges&fields=closed&fields=desc, which URL encodes to %2Fcards%2F560bf4dd7139286471dc009c%3Ffields%3Dbadges%26fields%3Dclosed%26fields%3Ddesc.

It’s worth noting that not every URL being provided to batch needs to be URL encoded, just the ones that cause an issue like this.

If we added this request to the batch call from above, it would look as follows: /1/batch?urls=/members/me,/boards/511e8c0101d3982d05000d5b,%2Fcards%2F560bf4dd7139286471dc009c%3Ffields%3Dbadges%26fields%3Dclosed%26fields%3Ddesc.

There appear to be cases where even this won’t return exactly what you might expect.  For example, a batched request to /boards/511e8c0101d3982d05000d5b/actions?fields=date&fields=type&limit=1 will return the id and the memberCreator in addition to the requested date and type.  I don’t know why this is.


Update, 8/13/2019: After I worked out the above solution, the Trello API docs were updated with an official solution: Manually URL encode the commas in each call and then URL encode the entire urls parameter.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.