Choosing how to design your REST API endpoints doesn’t restrict you to adhere to a concrete format, which is why there is a great level of freedom and flexibility in how you design them.
But, with this freedom comes responsibility. This responsibility is to make sure that we follow a certain architectural style when making choices about how we design our REST APIs.
This article explains the most important best practices and conventions to follow when designing your APIs, to support the client apps which use them, but also to make it understandable to developers who write those client apps.
Designing REST API URIs
URI stands for Uniform Resource Identifier and is a unique sequence of characters that identifies a logical or physical resource used by web technologies.
In our REST API endpoints, URIs identify resources and enable clients to access representations of that resource.
Use the plural form of nouns
For example, if you wanted to expose a resource of articles to the client, you would add the following URI endpoint to your REST API:
/articles
The convention here is to use the plural form of nouns like articles
instead of article
.
To understand why just suppose you want to give the client the ability to not only access “all articles” but also individual ones identified by their id
.
In that case, you can add the following URI to your REST API:
/articles/:id
If it’s not obvious at this point, just look at how logical this looks. We have a collection of articles, and we are accessing a specific article with a given id
in that collection.
It also potentially maps to the table in our database called articles
, where there are multiple rows in the table with each representing a single article identified by id
.
Just take note that the :id
is presented with a semicolon here, which I used as a notation signifying that the API captures the value in that part of the URI and stores it into a variable with the name of id
. There are different ways of doing this in the actual code and that depends on the framework you are using to write your APIs.
The request actually contains an integer here e.g. /articles/112
.
Never use verbs in URIs
What I mean here, is don’t use something like
/get-articles/:id
/update-articles/
This is bad practice. Where the verb like get
, update
, etc. is used to describe the operation being performed on the resource.
The operation performed on the resource is implicitly determined by the HTTP method the client uses to access a particular URI. The most common ones are of course POST
, GET
, PUT
, DELETE
that correspond to CRUD
operations (Create / Read / Update / Delete).
Performing those operations in our example would look like:
- POST
/articles
=> creating a new article in the collection of articles - GET
/articles
=> getting all current articles - PUT
/articles/:id
=> updating a specific article with the givenid
- DELETE
/articles/:id
=> deleting an existing article with the givenid
Nest URIs corresponding to the hierarchy of objects
Another important convention to follow is to stay consistent with the relationship between objects by nesting parts of URIs so it reflects that relationship.
In the articles
example, let’s say that our database contains a 1-to-many relationship between articles
and comments
on those articles. That means 1 article can have 1 or more comments.
To stay true to this relationship when designing our API endpoints, the URI should be consistent with it by nesting comments under an article. So in that case:
-
/articles/:article_id/comments
=> URI used to access all comments on the article with a given article ID -
/articles/:article_id/comments/:comment_id
=> URI used to access a specific comment of a specific article
This also makes it easy for clients of your API to understand the relationship between objects of your app.
Use hyphens in the URIs
In the URLs of your REST APIs, use hyphens (-
) instead of anything else, like underscores, to separate words, e.g. /users/jack-black
.
For naming the GET query parameters, it’s acceptable to use underscores (_
) since those are considered variables.
Gracefully handle errors
Any error that occurs in the REST API server code when processing the request should never crash the process or app. Instead, always handle your errors, and instead of crashing, return a corresponding HTTP response code.
In that case, the response body can also contain a description of the error to be presented to the client/user.
Filtering, pagination, and sorting
Use GET query parameters to achieve filtering, pagination, or sorting of the results that are returned from your REST API.
GET query parameters are appended in the format:
?param1=value1¶m2=value2&…
to the end of the URL.
Some examples:
- Filtering: GET
/users?firstname=Jack
—> returns all users which have “Jack” as their first name - Pagination: GET
/users?page=5&results=10
—> returns page number 5 where the complete users list is split into pages of 10 users - Sorting: GET
/users?sort_by=firstname&order=asc
—> returns all users sorted by their first name alphabetically A-Z
Versioning your REST API
Of course, as you do changes during the life of the app or service you host, sometimes those changes are non-backward compatible.
In that case, you can support different versions of your API.
One example of how to do this is to include a version number at the beginning of your URIs, e.g.
/v2/articles/
/v2/users/
/v2/articles/:id
Old versions of the APIs should be kept intact to avoid breaking changes with clients that are using those old versions.
Conclusion
Although there are many more facets to consider, these are the most common best practices to use when designing REST APIs.
So, to summarize the best practices:
- Use the plural form of nouns in URIs
- Never use verbs in URIs
- Nest URI segments that match the hierarchy of relational resources
- Use hyphens to delimit words in the URIs
- Gracefully handle errors and return proper HTTP response codes
- Use GET query parameters for filtering, sorting, or pagination
- Always version your REST APIs to support backward compatibility
Top comments (0)