Reputation: 489
Let's say there is an event hosting service. Hosts can login and create events using:
POST /events
to create event
GET /events
to get all events created by host
GET /events/1
to get event with Id 1 (if created by host, error otherwise)
Now the host wants to generate bulk invitation codes for an event on which guests can RSVP, and the host should be able to see responses. Host can share only share the code with the guests and doesn't want to share the event Id (because it doesn't look cool)
POST /events/1/invites
with a list of invitees to generate codes
GET /event/1/invites
to get the list of invitees and see their responses
GET /event/1/invites/SECRET007
to get a particular invite's response
Looks good so far, but what would be the convention for invitation RSVP?
One option is:PUT /invites/SECRET007
, but the problem is that it doesn't match it's GET counterpart.
Another option is to keep the PUT API and change all other APIs for invite
POST /invites
body : { event:1 ...} with a list of invitees to generate codes
GET /invites?event=1
to get the list of invitees and see their responses
GET /invites/SECRET007
to get an invite
But in this case GET /invites
makes no sense, it has to be always called with event id.
What is the correct convention to follow here?
Edit: the important requirement here is that the host can only share invite if with guest and the guest should be able to RSVP using that id only.
Upvotes: 1
Views: 2110
Reputation: 461
I don't know if this is "correct convention" but when I have faced similar situations I have adopted a pragmatic approach and tried to avoid deep resource nesting unless absolutely necessary.
I determine "absolutely necessary" to mean that the sub-resource identifier is not globally unique. E.g. if your paths were:
/events/1/invites/1
/events/1/invites/2
/events/2/invites/1
Then the invite ID isn't enough on its own to identify the exact invite, you need a composite ID which includes the event id.
If an invite ID is globally unique - not just unique to an event - then there is no reason why you can't to have a root /invites
resource.
/events:
get:
description: list events
post:
description: create event
/{id}:
get:
description: get event with id {id}
/invites:
get:
description: list all invites for an event
post:
description: create an invite for an event
/invites:
/{id}:
get:
description: get invite with id {id}
put:
description: update invite with id {id} (record RSVP)
If you think it is required, you can have essentially duplicate routes to access the same resource. E.g. you might have /events/{eventId}/invites/{inviteId}
and /invites/{inviteId}
to access the same invite. One route makes sense if you are discovering the invite through the event, and the second is a shortcut directly to a known invite.
Just my thoughts on the matter :)
Upvotes: 1
Reputation: 57279
On thing that may help: REST doesn't really understand "sub-resource" the way that you are describing here.
/invites
/invites?event=1
/invites/SECRET007
As far as REST is concerned, these are three completely independent identifiers, and therefore three completely independent resources. The spelling of the resource identifier doesn't communicate any semantic significance. The relationships here are equivalent to these:
/4498232d-9bf9-4405-a94d-ed5d2cfc5551
/951139d9-d5a9-43fb-ab23-ba4b383a7a11
/6b2d8b31-981d-4128-b354-776b8375decd
The routing library that you use might observe the similarities in the paths of the identifiers, and do something interesting with that information, but that's an implementation choice made behind the "uniform interface".
For example:
DELETE /invites
If that request is successful, a REST compliant cache will still hold copies of /invites?event=1
and /invites/SECRET007
. The hierarchy of the identifiers doesn't have any meaning.
Which in turn means that (a) you can arrange your resources any way you like, and (b) that you can choose any spelling that is convenient for you.
It's normal to have many resources that are "about" the same thing, each with its own identifier. Compare
https://stackoverflow.com/questions/57640910/rest-api-convention-for-subresource
https://api.stackexchange.com/2.2/questions/57640910?order=desc&sort=activity&site=stackoverflow
So if you want a spelling for your resource identifier that a human being will understand, then you need to be thinking carefully about your resource model, and the collections of affordances you are offering to clients.
Upvotes: 2
Reputation: 5811
Microsoft has published a sophisticated document with guidelines when setting up a REST api. There is no exhaustive rule for every use case so you will have to make your own decisions. Using CRUD patterns like GET/POST/PUT /events
seems preferred.
Checkout the guidelines: https://github.com/microsoft/api-guidelines/blob/vNext/Guidelines.md#931-nested-collections-and-properties
Upvotes: 1