I\'m new to REST and I\'ve observed that in some RESTful services they use different resource URI for update/get/delete and Create. Such as
I prefer to use both plural (/resources
) and singular (/resource/{id}
) because I think that it more clearly separates the logic between working on the collection of resources and working on a single resource.
As an important side-effect of this, it can also help to prevent somebody using the API wrongly. For example, consider the case where a user wrongly tries to get a resource by specifying the Id as a parameter like this:
GET /resources?Id=123
In this case, where we use the plural version, the server will most likely ignore the Id parameter and return the list of all resources. If the user is not careful, he will think that the call was successful and use the first resource in the list.
On the other hand, when using the singular form:
GET /resource?Id=123
the server will most likely return an error because the Id is not specified in the right way, and the user will have to realize that something is wrong.
For me is better to have a schema that you can map directly to code (easy to automate), mainly because code is what is going to be at both ends.
GET /orders <---> orders
POST /orders <---> orders.push(data)
GET /orders/1 <---> orders[1]
PUT /orders/1 <---> orders[1] = data
GET /orders/1/lines <---> orders[1].lines
POST /orders/1/lines <---> orders[1].lines.push(data)
Both representations are useful. I had used singular for convenience for quite some time, inflection can be difficult. My experience in developing strictly singular REST APIs, the developers consuming the endpoint lack certainty in what the shape of the result may be. I now prefer to use the term that best describes the shape of the response.
If all of your resources are top level, then you can get away with singular representations. Avoiding inflection is a big win.
If you are doing any sort of deep linking to represent queries on relations, then developers writing against your API can be aided by having a stricter convention.
My convention is that each level of depth in a URI is describing an interaction with the parent resource, and the full URI should implicitly describe what is being retrieved.
Suppose we have the following model.
interface User {
<string>id;
<Friend[]>friends;
<Manager>user;
}
interface Friend {
<string>id;
<User>user;
...<<friendship specific props>>
}
If I needed to provide a resource that allows a client to get the manager of a particular friend of a particular user, it might look something like:
GET /users/{id}/friends/{friendId}/manager
The following are some more examples:
GET /users
- list the user resources in the global users collectionPOST /users
- create a new user in the global users collectionGET /users/{id}
- retrieve a specific user from the global users collectionGET /users/{id}/manager
- get the manager of a specific userGET /users/{id}/friends
- get the list of friends of a userGET /users/{id}/friends/{friendId}
- get a specific friend of a userLINK /users/{id}/friends
- add a friend association to this userUNLINK /users/{id}/friends
- remove a friend association from this userNotice how each level maps to a parent that can be acted upon. Using different parents for the same object is counterintuitive. Retrieving a resource at GET /resource/123
leaves no indication that creating a new resource should be done at POST /resources
Use Singular and take advantage of the English convention seen in e.g. "Business Directory".
Lots of things read this way: "Book Case", "Dog Pack", "Art Gallery", "Film Festival", "Car Lot", etc.
This conveniently matches the url path left to right. Item type on the left. Set type on the right.
Does GET /users
really ever fetch a set of users? Not usually. It fetches a set of stubs containing a key and perhaps a username. So it's not really /users
anyway. It's an index of users, or a "user index" if you will. Why not call it that? It's a /user/index
. Since we've named the set type, we can have multiple types showing different projections of a user without resorting to query parameters e.g. user/phone-list
or /user/mailing-list
.
And what about User 300? It's still /user/300
.
GET /user/index
GET /user/{id}
POST /user
PUT /user/{id}
DELETE /user/{id}
In closing, HTTP can only ever have a single response to a single request. A path is always referring to a singular something.
Why not follow the prevalent trend of database table names, where a singular form is generally accepted? Been there, done that -- let's reuse.
Table Naming Dilemma: Singular vs. Plural Names
I don't like to see the {id}
part of the URLs overlap with sub-resources, as an id
could theoretically be anything and there would be ambiguity. It is mixing different concepts (identifiers and sub-resource names).
Similar issues are often seen in enum
constants or folder structures, where different concepts are mixed (for example, when you have folders Tigers
, Lions
and Cheetahs
, and then also a folder called Animals
at the same level -- this makes no sense as one is a subset of the other).
In general I think the last named part of an endpoint should be singular if it deals with a single entity at a time, and plural if it deals with a list of entities.
So endpoints that deal with a single user:
GET /user -> Not allowed, 400
GET /user/{id} -> Returns user with given id
POST /user -> Creates a new user
PUT /user/{id} -> Updates user with given id
DELETE /user/{id} -> Deletes user with given id
Then there is separate resource for doing queries on users, which generally return a list:
GET /users -> Lists all users, optionally filtered by way of parameters
GET /users/new?since=x -> Gets all users that are new since a specific time
GET /users/top?max=x -> Gets top X active users
And here some examples of a sub-resource that deals with a specific user:
GET /user/{id}/friends -> Returns a list of friends of given user
Make a friend (many to many link):
PUT /user/{id}/friend/{id} -> Befriends two users
DELETE /user/{id}/friend/{id} -> Unfriends two users
GET /user/{id}/friend/{id} -> Gets status of friendship between two users
There is never any ambiguity, and the plural or singular naming of the resource is a hint to the user what they can expect (list or object). There are no restrictions on id
s, theoretically making it possible to have a user with the id new
without overlapping with a (potential future) sub-resource name.