1. Use JSON
It may seem too obvious, but REST allows using different output formats, like plain text, JSON, CSV, XML, RSS, or even HTML. For sure this may depend on the application you have and specifically on what you need your API for. If you have a public-facing service which you want to be accessible through REST API almost in 99% of cases you should choose JSON as the data format used in the communication, both the payload and the response. What is more application/JSON is a generic MIME type which makes it a practical approach to use.
2. Use Nouns instead of Verbs
In API development REST approach can be called a resource based. So in your application, you work with resources and their collections (eg. a single book, and a list of all books). The actions on the resources are strictly defined by the HTTP methods such as GET, PUT, POST, PATCH, DELETE (and a few others, that are less relevant for this example) and only they should be used to change the state of the resource. This leads us to the endpoint URI construction. Taking the above into account properly constructed endpoint should look similar to this:
GET /addBook123 (by the way, GET should be only used to READ data and never to change its state in any way)
There are certain cases where it is ok to use actions in a similar way to manipulating resources, eg.:
Such a request create or update an activation property to a ‘123’ account, instead of simply saying the “activate” should be invoked.
It is tempting to use something like POST /activate_account/123 or PUT /account/123?activate=true but both of these are incorrect.
3. Name the collections using Plural Nouns
For the collections in REST API development use plural nouns. It is not just an established good practice. It actually makes it easier for humans to get an idea that something is actually a collection.
In the first example, you can see the reference to car number 123 from the whole list of “cars” available. Using “cars” in plural form informs us that this is actually a collection of different car objects.
In the second example, this is not so obvious, that there are other cars in the system.
4. Use resource nesting to show relations or hierarchy
Resource objects often have some kind of functional hierarchy or are related to each other. For example in the online store, we have ‘users’ and ‘orders’. Orders always belong to some user, therefore we may have the following endpoints structure laid out:
/users <- user’s list
/users/123 <- specific user
/users/123/orders <- orders list that belongs to a specific user
/users/123/orders/0001 <- specific order of a specific user
It is generally a good idea to limit the nesting to one level in REST API. Too many nested levels may not look too elegant. Also, it’s worth noting that a similar result may be achieved by filtering, which in our case could look like this: /orders?user=123. You will find more information on filtering in point 6.
5. Error Handling
Nobody likes to see the errors in a response that they’ve made to your API. But if they do, it’s good to provide them with enough information to know what has happened and possibly why. So, in API development, correct error handling should be considered as one of the best practices as well as testing API as the sooner a problem is detected, the faster, cheaper, and easier it is to fix it.
Standard HTTP error code handling is a must. There are 71 distinct HTTP status codes, so why not use them? These error codes are well defined and easily recognizable, therefore it makes perfect sense not to reinvent the wheel.
In many cases, at least correct handling of the HTTP statuses is enough, but it is even better to provide more verbose messages and some internal code reference for even more detailed explanation. So the “perfect” error message would consist of:
- HTTP Status Code
- Code ID - which may be an internal reference, you may also provide a link to the API documentation containing all the code id’s
- Human readable message shortly explaining the error (its cause, context or possible remedy)
Example from Twilio:
6. Filtering, sorting, paging, and field selection
Few of the most important features for consuming an API are filtering, sorting and paging. Resource collections are oftentimes enormous, and when some data has to be retrieved from them, it would be simply not very efficient to always get the full list and browse it for specific items. Therefore we can use:
- Filtering - to narrow down the query results by specific parameters, eg. creation date, or country
- Sorting - basically allows sorting the results ascending or descending by a chosen parameter or parameters, eg. by date
- Paging - uses “limit” in order to narrow down the number of results shown to a specific number, and “offset” to specify which part of the results range to be shown - this is important in cases where the number of total results is greater than the one presented, this works like pagination you may encounter on many websites
Filtering, sorting, and paging are used by adding a so-called query parameter to the endpoint that is being called. These may look as follows:
(this query should result in the list of 100 users from the USA, which account creation date was on 11/11/2019, sorted descending by the birth date, and the presented records are on the second page, which means are from a 101-200 record number range).
While we’re at the topic of query parameters, it’s also worth mentioning “field selection”. Field selection allows you to request only part of the data that would be available for a certain object. So if the objects you are querying have a lot of data (fields) and you only need a few specific ones, you may use a query parameter to specify which ones should be included in the response.
eg. we have a user object that has the following fields:
We want to get their username and e-mail to be used for sending a newsletter. The query may look something like this:
GET /users/123?fields=username,email (for one specific user)
GET /users?fields=username,email (for a full list of users)
Versioning your REST API is a good approach to take right from the start. This will allow you to introduce changes to the data structure or specific actions, even if they are breaking/non-backward compatible changes. At some point, you might end up managing more than one API versions. But this will allow you to introduce modifications and improve services on one hand, and on another not to lose a part of your API’s users as some of them might be either reluctant to change (their integrations) or are just slow adopters that need time in order to introduce changes on their side.
How to approach versioning? There are generally two routes to take. Implement the version in the request header or in the endpoint URI. The latter one seems to be more often used, and actually, to some extent, facilitates the readability and discoverability. Although some services (such as Stripe) combine both methods, this might actually be an “overkill” for your service.
Examples of endpoint URI versioning:
- https://us6.api.mailchimp.com/3.0/ (major + minor version indication)
- https://api.stripe.com/v1/ (major version indication only)
- https://developer.github.com/v3/ (major version indication only)
- https://api.twilio.com/2010-04-01/ (date based indication)
8. API Documentation
It is extremely important to have API documentation published. Not only developers like to know what they are dealing with when making an integration, but this also allows potential users to see what is made available via your API.
API documentation should provide information about the available endpoints and methods, preferably with request/response examples, possible response codes, information about the authorization, available limits or throttling. Publishing the documentation in the form of a browsable web page with interactive options, curl examples, maybe even a playground is a good idea.
Remember that the API documentation also shows how much your company cares. Well written, complete and nicely presented docs will be appreciated by the developers and/or partners and may serve as examples of how should it be made. Whereas sloppy, incomplete documentation that lacks examples, contains errors or is not up to date may be harmful to your company image.
Good API documentation examples:
9. Using SSL/TLS
Always use SSL/TLS to encrypt the communication with your API. No exceptions. Period.
Well made REST API development does not only follow the technical constraints but also takes into account User Experience considerations to make sure the API design solutions are discoverable and easy to use. Remember that API should be a part of business strategy and it is also a marketing tool for your organization, correctly executed and pleasant to use will grant you followers or even advocates. But this is a double-edged sword, so if you mess this up it might cost you a bad image.
Looking for engineers proficient in API development? We've got more battle-tested practices! Let's talk about the API's needs of your project.