3

Long Version

For some, myself included, one of the most painful and headache causing parts of building a REST API is determining the name for each resource and the accompanying endpoints.

Whilst it is, of course, down to personal preference; there are certain things that are encouraged by the community. For example, most people, including me, will pluralise their resource names:

GET /notifications
POST /posts

However, there are cases where pluralising just doesn't seem correct. Consider the following example where user essentially represents the logged in user, not the entire users resource:

Endpoints only relevant to the authenticated user

// Phone Verification
POST /user/phone/request
POST /user/phone/resend
POST /user/phone/verify

// User creation based on authenticated and verified phone
POST /user

// Update authenticated user's profile
PUT /user

// Delete the authenticated user
DELETE /user

// Add/remove the authenticated user's profile image
POST /user/image
DELETE /user/image

// Update the authenticated user's device token
PUT /device/token

Endpoints that access the entire users resource

GET /user
GET /user/{id|self}

In the above example, to me, it feels like the singular user resource name is more suited given on the majority of the endpoints, user refers to the authenticated user, not the entire database of users. But, on the other hand, having GET /user return all users just seems plain wrong...

As a result, I am now torn between user and users - both have strong arguments either way as I see it but would very much welcome another person's opinion on the matter...


Short Version

TLDR - To put it simply, consider the following two endpoints:

// Get all users
GET /users

// Update the authenticated user's device token
PUT /user/device

Both of the above seem correct in my eyes. The problem with the above is that there is no way I am going to have both user and users, it has to be one or the other in my opinion.

The dilemma; Why would I use user when the resource refers to the entire users database? Why would I use users when the resource only refers to the authenticated user?

I cannot get my head around this one... Anyone got any thoughts on this? Or, even better, an alternative solution to my proposed endpoint structure?


Update

After some deep thinking, I have come up with an alternative solution to this but I am still not 100% sure on it as I am not overly keen on using the auth resource name.

Consider this:

// auth = authenticated user
// users = users collection

POST /auth/request
POST /auth/resend
POST /auth/verify

POST /auth
PUT /auth
DELETE /auth

POST /auth/image
DELETE /auth/image

PUT /auth/device/token

GET /users
GET /users/{id}
Ben Carey
  • 16,540
  • 19
  • 87
  • 169

2 Answers2

1

There are obviously different opinions on this matter, the answer below contains my personal views. The bottom line is that it's all quite subjective and depends on the way one looks at a certain (type of) resource.

Why would I use user when the resource refers to the entire users database?

In my opinion, you should never use singular for an endpoint that contains multiple resources.
Some people, however, argue that we should stick to singulars for all resources, mostly for the sake of simplicity and uniformity.

Why would I use users when the resource only refers to the authenticated user?

You will find quite some different opinions on this, but the consensus and most widely adopted is generally to stick with plurals, except for resources that can only contain a single item (for example, a user profile only containing only one avatar).
Also, since using a singular form for the users resource wouldn't make sense following the above logic, we don't want to mix singular and plural names.

// Update the authenticated user's device token
PUT /user/device

You can interpret 'updating the authenticated user's device token' as follows:
Add a device token to a user entity of the users resource collection.

Laurens Deprost
  • 1,653
  • 5
  • 16
  • 1
    I couldn't agree more, sticking with plurals for collections is the norm and what I have practiced for years. I have been thinking more about this and think my issue is with the related resources to the authenticated user. This endpoint just does not sit well with me `PUT /users/device` because you should technically be declaring which user on the resource you are editing the device of e.g. `PUT /users/self/device`. I am now thinking that I should do something like this `/auth/device` where `auth` represents the authenticated user (singular). What are your thoughts on that? – Ben Carey Jan 06 '19 at 00:31
  • Please don't bold random words and phrases. It makes the text annoying to read. – Eric Stein Jan 06 '19 at 00:31
  • 1
    @BenCarey I agree that `PUT /users/device` doesn't 'feel right'. Either `PUT /users/id/device` or `/auth/device` would be better. I personally would prefer the first option, since I feel like having a separate resource name for an authorized user is unnecessary. – Laurens Deprost Jan 06 '19 at 00:39
  • 1
    @LaurensDeprost - Welcome to my dilemma - I don't want to have a separate resource for the authenticated user; `auth` as that just seems overkill. BUT, having `PUT /users/{id|self}/device` just doesn't seem right because you cannot update another user's device. In other words, the endpoint will always be `/users/self/device`. I guess that isn't the end of the World but as a perfectionist, it is really annoying me as it just doesn't seem right... ahhhhh. What do you reckon? – Ben Carey Jan 06 '19 at 00:43
  • @EricStein Thanks for the feedback. It's a habit I picked up that I realize I need to be aware off, especially in longer answers. – Laurens Deprost Jan 06 '19 at 00:55
  • 2
    @BenCarey I understand your predicament, but I would still implement it as `/users/id/device`. It just seems like the most RESTful approach. – Laurens Deprost Jan 06 '19 at 00:56
  • @LaurensDeprost - The more I think about it, the more I agree with you... I'll leave the question open for the time being in case other's have opinions on it too – Ben Carey Jan 06 '19 at 00:57
0

If your API supports view devices' data of other users, the API can be like /users/$user_id/devices

whereas, when you always have to get the current logged-in user's devices information, the API can simply be /devices (as current user is implied).

i.e IMO, wherever you have only 1 parent resource accessible (say in this case current user is always singular), you can skip that resource in the API URL.

Deva Gerald
  • 284
  • 2
  • 6