Amit Khanna
Amit Khanna

Reputation: 489

REST API convention for subresource

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

Answers (3)

Johnson
Johnson

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

VoiceOfUnreason
VoiceOfUnreason

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.

See Jim Webber's 2011 talk

Upvotes: 2

MaartenDev
MaartenDev

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

Related Questions