Last Updated: 27 Jun 2023


Author: dordal

Building an API: Best Practices

Update 25 Sept 2018: As a commenter points out, this 2012 article 'has not aged well'. I agree, and while I hope to update it at some point in the future, please see the comments ( and add comments!) for more modern best practices.

This doc outlines a few thoughts and best practices for building an API. This is based on my own experience building APIs, as well as examining popular APIs such as Twitter, Twilio, Facebook and foursquare.

Be sure to check out these resources for more on API development:


One of the early decisions you'll need to make is whether your API will be 'RESTful' or use SOAP. SOAP is a protocol ('Simple Object Access Protocol') and is generally used for more complex 'enterprise-level' APIs. It requires that you POST a specially crafted SOAP message to make the request, and then decode a second specially crafted SOAP message when the results come back. In contrast, 'RESTful' APIs are typically accessed by simply calling a URL and passing parameters ( ), and then decoding the results from some agreed upon format, such as JSON or XML. Unless you have some reason not to, you want to build using a RESTful model; nearly every major public API today does this.

Note: To be fully RESTful, an API has to do a lot more than be accessible via a URL; APIGee has a good blog post with details. I believe in a 'pragmatic RESTful' approach; e.g. its OK to break some of the rules of REST for the purpose of being practical.


Now that you've decided on your API will be RESTful, you should decide how you're planning to return data. There are two common choices: JSON or XML. The world seems to be moving to JSON; for example FourSquare dropped XML support in its latest V2 API. XML is harder to parse, and it can't (easily) be parsed in JavaScript. There are JSON encoders and decoders for nearly every language, including non-web languages like iOS's Objective-C.

Many APIs today offer a 'format' argument; for example's API offers a format==json paramter, and Twilio allows you to append a .json to any call to get the response in JSON format. Think long and hard before you do this: it increases your coding & testing complexity, and doesn't usually add much value unless you need legacy compatibility. I generally just use JSON.

GET & POST (and PUT, DELETE, etc.)

Another decision if you're using a RESTful model: do you use GET or POST for calls? I'd strongly recommend you follow the HTTP & REST standards; e.g. use GET for all calls for retrieving data (getUser, getObject, etc.) and POST (or PUT) for all calls where you send data (addUser, updateUser, etc.). You can also use other less common methods such as DELETE if you need to do an operation like removing a resource.

Use an Envelope

You'll generally want to wrap all your API responses in an 'envelope' which specifies metadata about the API call.

// sample JSON envelope
  "status": {
    "code": 200,
    "message": 'Success'
  "response": {

Doing this allows for client handler code to behave the same way for all API calls, since it gets a responses back in a universal format.

Handling Authentication

Most APIs you build will require some sort of authentication. Generally you want to implement one of the following:

  1. Use an established authentication standard, like oAuthV2.
  2. Roll your own token based authentication; you pass a username and password to an authenticate call and it returns an auth token, which the client app then passes on all subsequent calls. You might also consider session-based authentication; you call the authenticate call and it establishes a session, and all you have to pass back is the session identifier (which is frequently handled automatically).
  3. Roll your own HTTP Auth based authentication.

I don't have a strong preference. Foursquare, Facebook and Twitter all went the oAuth route, and it's clearly an emerging standard, but it seems particularly useful for social applications & API designed for application-to-application communication. Many other APIs use their own authentication scheme, and a few use standard HTTP authentication.

Handling Errors

Errors in APIs are an interesting beast. There are generally two ways to handle them, and they're not mutually exclusive: you can either return an HTTP status code if something goes wrong (e.g. '400 Bad Request' if a required parameter is missing ), or you can always return '200 OK' and pass the error back as part of the return envelope. I'm not really sure which one I prefer, although I've generally tended toward the latter.

There are also a number of cases where both are done; for example the foursquare API provides HTTP status return codes and then also sends those codes in the response body. Even more interesting, actually changes the handling of error codes depending on the return type (txt vs. json vs. xml).


You'll almost certainly want to version your API so you can make changes in the future without breaking your existing clients. I recommend a version string at the root, e.g.<call><call>

Developer Key

You might consider making your clients register for a 'developer key' (a.k.a. 'client key' or 'application key'). This lets you objectively track what apps are using your API, and also lets you block the bad apples if need be.

One interesting strategy here is BART's: they provide a 'public' application key that everyone can use, but threaten to rate-limit or cut it off if it's abused. Then they allow you to signup for a private key too.

Usage Limits

You may want to put some usage limits on your API, depending on its purpose and intended audience. Nearly every public API has rate limits, from Facebook to foursquare to to Twitter.

SSL vs. Not

There's often a question of whether to use SSL to secure your API; I generally recommend the same thing I do for normal websites: use SSL if you have personal (non-public) data; otherwise don't.

SSL generally adds a 10%-15% overhead to a web transaction, so its not significant enough of a penalty if you need to use it, but its not so insignificant that you'd want to use it all the time.


Arend , Jul 13, 2012 09:02 AM

Thanks for this great article, neat and to the point.

Ahsan, Nov 12, 2012 12:11 PM

You have presented very useful points (in a summarized manner). It was very helpful to me.

test1.39.60.217, Oct 30, 2015 10:08 PM

Nice writeup. The link to Bitly's API documentation is dead.

test186.136.148.230, Dec 8, 2015 11:57 AM

Nice article.
I just want to mention that you shouldn't use verbs if you are designing your application in a RESTful way.

test207.239.114.234, Feb 2, 2016 11:27 PM

Why duplicate the the “status” (HTTP Status) field when it is returned anyways as part of the HTTP Response. Just trying to see if there's a benefit to duplicating this information…

dordal, Feb 3, 2016 12:59 AM

I think it makes it easier for developers to read, and it the only cost is a (very) small increase in API payload size.

However, you could certainly argue the other side too… just relying on the actual HTTP status code is reasonable.

test136.33.152.71, Sep 6, 2018 03:49 AM

This article has not aged well.

1.) You should always use SSL. Always.

2.) As others have pointed out, the URL structure shown here is not RESTful. It's more of an RPC-style design. Both have their places, but this is a case where REST would make more sense and be properly implemented using plural nouns, not verbs. E.g. /users/david instead of /getuser?username=david

3.) The use of HTTP verbs GET, POST, PUT, PATCH, and DELETE is well-defined in the RESTful model.

4.) Envelopes are generally shunned in modern RESTful APIs, as long as the API is stateless (there is a potential security vulnerability if the API is stateful). HTTP is the envelope. Use HTTP status codes to indicate the status and provide the details in the body in JSON format.

dordal, Sep 25, 2018 06:21 PM

Yeah, I'd agree. I put a note at the top telling people to look at the comments; six years later I wouldn't agree with everything I wrote here. Hopefully will have time to update it soon.

Enter your comment. Wiki syntax is allowed: