What does it take to design a good API? Let's take a look at that question by considering some of the mistakes that developers commonly make when creating APIs.
Error 1: Inconsistent APIs
Consistency could be defined as "agreement or harmony of parts or features to one another or a whole." When you design an API, it signifies that you keep your decisions aligned to a single line of thought in several aspects.
First, naming conventions. It is generally acknowledged that a good practice is to use plural-concrete-nouns instead of verbs or abstract/singular nouns. This way, you take advantage of the combination URL noun + HTTP verb.
Second, your URL structure should be easy for a human to read. Consider that a URL like
has four levels of abstraction and two real values to identify the desired resource. This makes it difficult to read and test, since the hierarchy of resources is difficult to interpret and follow. Additionally, field naming is inconsistent as it mixes camelCase with underscore_case.
A third aspect of consistent APIs is the use of standard headers. You should keep with the standards and use them in a proper way. The rule of thumb is that an API should not require custom headers to be consumed. But this advice has an exception related to a second common error — API versioning.
Error 2: Lack of API Versioning
An API should be consistent over time, but because business requirements change, you could end up with an inconsistent API which changes the resources and mapping reflecting those changes. This can make it difficult to consume your API, and thus it should be avoided. The standard recommendation is to make the version of the API to be consumed explicit to the developers. There are at least four ways to accomplish this:
■ Add the version number to the URL. This is the easiest path, but it mixes information about the API (the version number) with information about the actual resource. The version is usually included in the form:
■ Use a custom header. (Consistency warning!) Previously in this blog we said that an API should not require custom headers to be consumed, but since necessity is the mother of invention, you could aggregate a custom header like X-api-version as needed.
■ Use the Acceptheader. This also breaks consistency because an API with a header like Accept: application/vnd.mysuperservice.api+json;version=2 is cumbersome to use and document.
■ Use a query string parameter of the URL like:
There are no universally accepted solutions. Some authors disagree with all the solutions, but the cost of not versioning is usually higher than the remorse from implementing it in a certain way.
Error 3: Not Learning from API Errors
The API world is tough. Higher complexity of services implies an increased probability of errors, and when an error occurs, not having a policy to handle it and communicate properly is also an error. The first advice is to use the appropriate status codes. In the HTTP protocol, they are classified in common groups:
■ 2xx represents successful operations.
■ 3xx are redirections. Pay special attention to: 304 - Not modified
■ 4xx are errors attached to the client's request. The common 422 - Unprocessable entityis useful to return validation issues.
■ 5xx represents errors in the processing of the resource.
The above are not the only good practices. To increase the information available to the client, it is usually a good idea to include a link in the payload with a deeper description of the error and the way to solve it. For example, more_info Twilio includes a link as part of their response.
There are many potential mistakes that can be made when designing and implementing an API. This short list can give you a consistent, evolutive and understandable API, and can help you keep an eye on easily detectable errors, saving you time and headaches in a production environment.