Blog helps developers connect to their users' content.

Connect your web/mobile application to Dropbox, Gmail, Facebook, et al. plus dragdrop, image conversion, and upload acceleration.

We at spend a lot of time thinking about APIs. With the release of our Version 1.0 javascript API, we thought about best practices for javascript API design, and wanted to share them so that when we use your API, it’ll be just as awesome as when you use ours.

Rules of your Javascript API

Rule 0: Never make breaking changes to your API. Unless you must.

An API is a contract between you and the developers who use your product. Don’t violate it. Unless it’s a terrible contract and you would both be better off moving to a better place.

The developers building on your API have invested time and energy into learning how to use your product and integrating it into theirs.

However as your knowledge about how people are using your product and API grows, the original API will become stale and a refresh will be in order. Wait until the cruft is unbearable, then in one giant leap move as far forward and future-proof as you can. Do it all at once in one clean break. If you can, provide a shim that maps the old API calls to the new one, so that someone can include the new API and a shim and not break any of their old calls.

Over the course of our early customer development during YC, the product and feature set was changing so fast it essentially meant we just piled more and more on to the API. It worked, but in dealing with our API, there were all sorts of inconsistencies, rough edges, almost-theres, gotchas, etc. So we made the tough call of redesigning our API from the ground up as a V1, and our developers seem pleased with the result.

Rule 1: Provide wood and nails, and a complete house for your API

Provide high-level functionality that completes a whole workflow in one line of code, and also raw primitives that allow a developer to build up entirely custom functionality. Things in the middle are just frustrating and confusing.

If someone comes to you asking for help building a house, there are two useful things you can do for them: give them a house, or give them the tools, instruction, and raw materials they need to build it themselves. If you give them three pieces of wood nailed together, it’s just frustrating: they’ll either find ways to rip it apart into the pieces they need, or they’ll have to wedge it into their application in an awkward way.

In the case of our API, we used to provide getFile, which would pick a file from Facebook, Google Drive, etc., optionally perform some conversions, and then store the result for you. Because of all the different things it did, configuring it was a mess. The developer had no way of getting progress, using individual components without the rest. Now, we have, amongst others, filepicker.pick,, and filepicker.convert, primitives that you can interweave and cascade as you see fit. We also have the HTML widgets which do the most common case in one line of code, perfect for people who just want basic uploading.

Rule 2: Have nouns, verbs, and a complete bipartite graph

Spec out what objects you pass around and what operations you can perform. You know you found a good candidate for a complete API when you can perform every action on every object.

It helps to think of your API in terms of nouns and verbs which developers can use to form sentences. Draw a grid, with the models/nouns/objects on the one axis and the verbs/actions on the other. Fill in a square if you can perform the given action on the given object. Any blank square will require a special warning in the documentation that explains why you can’t perform the action you wanted. It will require the developer to go back to their API docs every time he wants to do this one action you don’t allow, and will result in support tickets. If you can fill in every square, consider that a complete “block”, a good candidate for an API design.

In our case, our v0 would sometimes return urls, other time JSON blobs, certain ones could be cascaded into other actions but other ones couldn’t. In the new version, everything turns into an FPFile (a JSON format we use as our standard), which can then be used directly in,, filepicker.write, filepicker.convert, and filepicker.export.

Rule 3: When dealing with APIs fail fast, or better, not at all

When dealing with APIs programming errors should throw exceptions immediately. User errors or unexpected situations should pass back errors in a consistent fashion. Be willing to do extra work in the library to follow the principle of least surprise. Your API will thank you. Come up with a consistent way of treating errors, but here’s a scheme that we found particularly nice for javascript:

  • Developers should never have to use a try-catch. Exceptions are thrown in situations where the developer made an error (or you made the error of not documenting well enough) and should be alerted as soon as possible.

  • When unexpected things happen or the user does things that are “error-like” (closing the dialog without choosing something, uploading content that can’t be read, etc.), pass back a consistent error type in a consistent way. For us, we have an onError(FPError){} callback on each function. By default the error contains a lookup code, but we also have a filepicker-debug.js library that will automatically inject helpful error messages into the FPError.toString() method. This way we keep our library lightweight for production while still helping developers in development mode.

When interfacing with the API, see if there are things that your library can do which may take a little bit of extra work on your code, but will catch common mistakes. For instance, if you want to limit the user to only selecting images, you can set {mimetype: “image/*”}, or {mimetypes: “image/*”}, or {mimetypes: [“image/*”]}. The call accepts FPFiles, URLs, DOM File objects, and DOM input types. If you try to read a file in IE8, rather than fail, the library will jump through hoops to perform the action (see post), but to you the developer, it’s magic - things just work so you don’t have to futz with exceptions and error cases.

Rule 4: If the API is hard to use, it’s not good enough

Use your API as you’re building it. Try writing to the API before you even build it, and get some of your lead customers/friends to do the same.

The first thing we did in specifying the API was convert all our demos to the “new” design. If something felt awkward, we redesigned it. The API required too much boilerplate to do simple things, we simplified it. We ran through the same exercise with our customers, writing up a quick guide and having them look at migrating their implementation. It was only after we loved using our API internally and our customers loved it that we built it. This was now fun, because once we had played with what the V1 of our API would be like, we couldn’t wait to see it go live. If you want to try it out yourself, check out our documentation page, now with run-able, editable API code samples:

In summary:

  • Never make breaking changes to your API. Unless you must.

  • Provide high-level functionality in one line of code, and also the raw primitives.

  • Have nouns, verbs, and a complete bipartite graph.

  • User errors with your API or unexpected situations should pass back errors in a consistent fashion.

  • If your API is hard to use, it’s not good enough (meaning you have to use it first)

Try out the newest version of our javascript API.

If you’re interested in API design, there’s a burgeoning field of “Developer Experience” that might interest you.

And if you’re really interested in API design, we get to do this stuff all day long, and we’re hiring

Follow the discussion on hacker news -Brett van Zuiden
  1. notundefined reblogged this from filepicker
  2. repejota reblogged this from filepicker
  3. sourcetocode reblogged this from filepicker
  4. inetgate reblogged this from filepicker
  5. vishal-telangre reblogged this from filepicker and added:
    experience-based ideas regarding:
  6. lalitkapoor-web reblogged this from filepicker
  7. filepicker posted this