API: An EPIC FAIL Story


May 26, 2008

I am working on integrating a third party service in to a web app for a client — a task I can always count on to be at least somewhat painful. This particular service's API, however, is worse than painful. Their API is a failure in nearly every possible way — and some new and surprising ways I could have never imagined. After a couple of weeks of working with this API, I have compiled a list of DON'Ts, FAILs, and OMGs for your enjoyment.

How to FAIL at API

Sample Code

On their libraries page, they list an "unfinished" ruby library. I thought: no problem, even if the implementation isn't complete, at least this is something I can work with — a starting point. Boy, was I wrong.

FAIL: The library doesn't work, isn't tested, and is impressively unreadable. Is it a gem? There's no gemspec. Is it a rails plugin? There's no init.rb. Out of the box, it's not even clear how to test it in a console. Once I did manage to get it running in a console, it was pretty obvious that nothing worked. Worst of all, the way the error handling was set up, it kicked me out of irb every time a call failed (which was every time, because the code was FUBARed).

Lesson Learned: DON'T provide untested client code that doesn't even come close to working. It's better to provide nothing at all than to waste your client's time working with an unreadable mess of garbage that leads them nowhere. If you want to be in the business of distributing code, learn the language, and make sure you're distributing something that works.

Error Messages

There is absolutely no mention of error codes in the documentation for this particular API. So, I assumed that their data validation was pretty loose, and that as long as I satisfied the required parameters for a call, it would succeed. So, when I re-implemented their API client in ruby, I didn't build in any exception handling beyond the http communications layer. I was pretty confused when nothing was working.

OMG: There are error codes; they're just not documented. I dumped the messages out to inspect them. Maybe I had goofed something up on my end? Apparently the authors of this API decided that their error messages are so good that documenting the error codes was an unnecessary task. Unfortunately, my code doesn't understand english particularly well.

Lesson Learned: Document your error codes! From an implementer's point of view, missing error codes almost definitely means that your API is going to be unreliable, and thus, useless for any important task.

Security

I'm no guru, but I know enough about security to know that asymmetric encryption (or public-key cryptography) is secure as hell; that's why https, ssh, pgp/gpg, etc, choose it as their supporting technology. Using a public / private key pair, asymmetric encryption allows two parties to create a secure connection over an otherwise insecure channel without worrying about interception.

Data encrypted with a given public key can only be decrypted with the corresponding private key. So, unless the private key has been compromised, it is impossible for the communication to be decrypted by a third party. The sender of data can also use their private key to sign the message, verifying its identity; the signature can then be decrypted with their corresponding public key. It's quite an elegant system, actually.

It has some traction, too: it's secure enough for your bank, operating system vendors of all kinds, secure email vendors, and more, but apparently, the implementers of this API didn't feel public-key cryptography was adequate.

OMG: Instead, they chose to use symmetric encryption. That means, there is one single key that both parties posses, and use to encrypt, and decrypt their communications. Naturally, the flaw in this approach is that somebody in possession of the key can intercept communications with ease. So, when making use of symmetric encryption, the key has to be transferred across a highly secure channel.

FAIL: They sent me the key in an unencrypted email.

Lesson Learned: If you're going to diverge from the industry standard somewhere, especially when it comes to security, make sure to have a good reason for doing it. It wouldn't have taken much research to determine that https is an extremely secure protocol.

It's supported on nearly every system in the world. So, piggy backing on https would have meant that clients wouldn't have had to re-invent the wheel just to use this particular API.

The fact that they weren't aware of that in advance suggests that they don't understand the technologies that they're using, which is going to throw up a gigantic red flag for anybody working on integrating with their service.

EPIC FAIL: The funniest part about the whole encryption thing? HTTPS only uses public-key crypto to create a secure channel, in which to exchange the symmetric key. For performance reasons, the rest of the data is exchanged using a symmetric algorithm. The result is effectively the same, except that https is actually secure, whereas this symmetric key may have been compromised by somebody sniffing my network traffic when I grabbed my email that day.

 

Remarkably, there is more to this story, but it'll have to wait for another day. For now, what are some of your integration horror stories?