I have a question related to REST url design. I found some relevant posts here: Different RESTful representations of the same resource and here: RESTful url to GET resource by different fields but the responses are not quite clear on what the best practices are and why. Here's an example.
I have REST urls for representing "users" resource. I can GET a user with an id or with an email address but the URL representation remains the same for both. Going through a lot of blogs and books I see that people have been doing this in many different ways. For example
read this practice in a book and somewhere on stackoverflow (I can't seem to find the link again)
GET /users/id={id}
GET /users/email={email}
read this practice on a lot of blogs
GET /users/{id}
GET /users/email/{email}
Query params are normally used for filtering the results of the resources represented by the url, but I have seen this practice being used as well
GET /users?id={id}
GET /users?email={email}
My question is, out of all these practices, which one would make the most sense to developers consuming the apis and why? I believe there are no rules set in stone when it comes to REST url designs and naming conventions, but I just wanted to know which route I should take to help developers better understand the apis.
All help appreciated !
In my experience,
GET /users/{id} GET /users/email/{email}
is the most common approach. I would also expect the methods to return a 404 Not Found if a user doesn't exist with the providedid
oremail
. I wouldn't be surprised to seeGET /users/id/{id}
, either (though in my opinion, it is redundant).Comments on the other approaches
GET /users/id={id} GET /users/email={email}
GET /users?id={id} GET /users?email={email}
id
and anemail
(e.g.GET /users?id={id}&email={email}
)? If not, I wouldn't use a single resource method like this.id
,email
or any unique identifier to be among the parameters. For example:GET /users?status=BANNED
might return a list of banned users.Check out this answer from a related question.
Looking at this pragmatically, you've got a collection of users:
Each user has a dedicated resource location:
You've also got a number of ways to search for users:
Since these are all query parameters to /users, they should all return lists.. even if it's a list of 1.
I wrote a blog post on pragmatic RESTful API design here that talks about this, among other things, here: http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
About the user resources
on the path
/users
you will always get a collection resource returned.on the path
/users/[user_id]
you will get a singleton resource representing the user with its id [user_id] or alternatively a 404 response if no user exists with the requested [user_id] (or forbidden (401) if you are not allowed to access the requested user resource, etc). Each resource path has only one single identifier and you use this to find/identify the resources. It is not possible to use several identifiers for the same resource on the same resource path. If you get a resource returned in a response that identifier is included in the response as a self HREF to locate/identify the resource.You can query the path
/users
withGET
/query parameters. This will return a collection with users that meet the requested criteria. The collection that is returned contains the user resources, all with their identifying self HREF.About the email resources
If I look at what you suggested for email I would rather think the following:
Emails from users are also resources. So I would think that
/users/[user_id]/emails
returns a collection of email addresses for user with iduser_id
./users/[user_id]/emails/[email_id]
returns the email of user with user_id and ['email_id']. What you use as an identifier is up to you, but I would stick to an integer. You can delete an email from the user by sending aDELETE
request to the path that identifies the email you want to delete. So for exampleDELETE
on/users/[user_id]/emails/[email_id]
will delete the email with email_id that is owned by user with user_id. Most likely only that user is allowed to perform this delete operation. Other users will get a 401 response.If a user can have only one email address you can stick to
/users/[user_id]/email
This returns a singleton resource. The user can update his email address byPUT
ting orPOST
ing a new email address at that url. If in your application you do not allow users without an email you should respond with a 401 if he sends aDELETE
request to that url.