Heads Up Before August 2018 Saber was known as "BugMuncher", so you'll see the name BugMuncher instead of Saber throughout these older posts. You can read more about the name change here - BugMuncher rebrands to Saber.
I had high hopes of Basecamp, after all, it was created by the same people who created Ruby on Rails, and I love Ruby on Rails. To me, Rails is like a breath of fresh air in an atmosphere full of confusing, overly-verbose, enterprisey bull shit. So imagine my surprise to discover Basecamp’s API was confusing, overly-verbose, and suspiciously enterprisey. It’s about as un-Rails-esq as possible.
My day started a little late again, as I had to answer some support emails. As always, my first job was to dive in the developer documentation and get a feel for things. My first surprise was that Basecamp keeps two old versions online, as well as their current offering - each version is incompatible with the next, and has a separate API.
No big deal though, they offer an easy way to import data from one version to the next, and some people probably prefer the old versions.
Anyway, I decided that I would only be integrating with their latest version, Basecamp 3, which had a pretty standard looking REST API, and OAuth 2 based authentication.
Having chosen my version of Basecamp, I created an account, set up my OAuth client, and started playing around with the API.
The first bit of weirdness came pretty early on, when I got my first OAuth access token, the thing was massive. For some reason, the access token and refresh tokens are prepended with a non-URL safe, base64 encoded, serialised object containing some information about your session, including account id and token expiry date. The actual token is separated from this data with a --, which seems to serve as a comment when parsing the base64 data.
I’ll admit I’ve never read the OAuth specification, but I have worked with a lot of OAuth providers, and this is the first time I’ve seen tokens like this. Maybe it is part of the spec, but it serves no purpose to whomever is using the API, is undocumented by Basecamp, and makes the tokens ridiculously long.
The next bit of weirdness came when trying to make requests to Basecamp’s API, the docs say “All URLs start with https://3.basecampapi.com/999999999/“, but don’t make it clear that 999999999 should be replaced with your account ID. Once I’d figured that out, and found where to find my account ID, it became apparent that a Basecamp user can belong to more than one account, which is whey this account ID URL prefix is used.
Except that’s bullshit. Consider GitHub, who are in my humble opinion the gold standard of REST APIs. A GitHub account can belong to multiple organisations. When I want to use the GitHub API to get a list of repositories to which the authenticated user has access, they don’t require an organisation to be specified when getting repositories. I can just get a list of all the user’s repositories, regardless of organisation. That makes sense. That to me seems like the Rails way of doing things. Basecamp could learn a thing or two from GitHub.
Anyway, after far too many hours, I did manage to get BugMuncher’s back end API integrated with Basecamp, and fully unit / integration tested.
Finally I was able to start on the front end, which was for the most part like any other, except that I needed to add an extra step to the process where users could choose their account. I did make it auto select the account if the user only had access to one, which should make the user experience a little nicer.
I found early on that my access tokens kept being rejected by Basecamp when I was working from the front end. I was able to test the tokens in the Rails console, and they worked there, so I came to the conclusion that the strange base64 prepended format of the tokens was causing them to get mangled as they were passed around in URL parameters.
I then wasted a good couple of hours trying to find a reliable to send and retrieve these weird-ass tokens as part of a URL, until eventually I reverted all my changes with the plan of trying a new approach, when I found it just worked. I have no idea what caused the tokens to get rejected earlier, maybe I’d made a stupid mistake on the front end, maybe Basecamp’s API had a temporary glitch, but either way it was working now.
I was finally ready to try a staging test, and to my surprise it all worked fine. So now it was just a case of writing some documentation and making it live, ready to retire for the week at 7:00pm.
Total time taken: 8 hours, 30 minutes
Basecamp was by far the worst of the 5 API integrations I built this week. Although it would have been more like 6 hours had I not gone on that wild goose chase relating to the access tokens. Maybe I’m being harsh on Basecamp, I’m sure there are much worse APIs out there. I think I just expected so much more from the people behind my beloved Ruby on Rails.