REST API Design, part 2

A few weeks ago, Kyle wrote a post about REST API designing and since I've written a few API's myself, I've decided to add some extra guidelines about good practices.

Versioning

Versioning allows you to maintain old versions of your API and develop new ones simultaneously. It also makes easier to iterate and avoid sending invalid requests to updated endpoints. However there is a case, when versioning is not required. It's happening when your API is consumed by systems which are updated in the same time as API (as with single page applications).

Documentation

Unless you create API only for own usage, you should write a documentation. Remember that, API is an interface created by developers for other developers so make it fair and easy to find. Few points which might be helpful:

  • Make it accessible for those developers who have access to API
  • Put basic info for all endpoints: URI, description, required fields and their types, structure of response, etc.
  • Try to write as much details as possible, even obvious things. They can be obvious for you, but might not for someone else.
  • Add examples of API usage
  • Use changelog to inform about updates in each iterations

Status of responses

According to Hypertext Transfer Protocol standards, use proper code for responses and use it effectively – this can be helpful to understand responses. Avoid contradictions like, returning status 204 No Content with resource in body.

Format

JSON is the most popular format for structured data exchange, but don't forget about XML. Despite it's verbose and hard to parse, there is still a group of developers who use this format for data exchanged between two systems. I believe not because they like it, but because it's required by systems they are developing. The best approach to change response format is to use extension in URLs, f.e. /models.xml or send it in query param: /models?format=xml You can also use JSON format as default, so defining extension in URLs will not be required for most of developers.

Filtering, sorting, searching, pagination

For listing APIs, it's a good practice to provide all common features like filtering, sorting, searching and pagination with page size.

Examples:

  • filtering: /models?type=a
  • sorting: /models?ordering=name (and reverse ordering /models?ordering=-name)
  • searching: /models?q=test
  • pagination: /models?page=1&page_size=10

Limiting which fields are returned in response

In some cases, developers want to reduce fields returned in response – allow them to do that by using GET param, for example: /models?fields=name,created,owner,description,image&ordering=name

Return object after update or creation

After creating or updating a single object, application is usually presenting this object to user, so to avoid sending one more request to the server, just return this object in response. Also, sending PUT or PATCH change existing resource, but it can also change resources which is not sent in request, f.e. updating status field may change status_timestamp field.