1

I have couple of nested resources like Merchant, Hotel, Room. A merchant can have many hotels and similarly a hotel can have many rooms. Right now for managing these resources I doing something like:

Create

POST api/v1/merchants/11/hotels

creates a new hotel.

Update

PUT api/v1/merchants/11/hotels/42

updates the given hotel.

Same for read and delete.

For rooms:

Create

POST api/v1/merchants/11/hotels/42/rooms

creates a new room.

Update

PUT api/v1/merchants/11/hotels/42/rooms/42

updates the given room etc.

In future there will be more nested resources like room facilities etc. and following this scheme will turn hairy.

I am in the early stage of development and I may expose these APIs for developers hence I can't change API scheme very quickly.

I am in doubt from day one regarding this approach. Can I assume that each entity has unique ID (which is true for now as I am using relational database and has its own table)? If yes, then the can I use these URLs for APIs instead of above ones?

POST api/v1/rooms

PUT api/v1/rooms/42

Etc for more nested resources.

Is there any violation of semantics or standard that I may be missing? I am using similar approach in views eg. in URLs in browsers which is looking ugly too.

  • Question: if I use PUT api/v1/merchants/12/hotels/42 am I talking to the same hotel as I am in PUT api/v1/merchants/11/hotels/42? Or is that a different hotel? Or is this sure to produce an error? – candied_orange Jul 16 '17 at 10:15
  • @CandiedOrange that was my question, should I rely completely on unique ids? – CodeYogi Jul 16 '17 at 10:18
  • Well you'd better have unique id's somewhere. What I'm trying to establish is if your nesting issue isn't simply a bread crumb issue. If the numbers you're showing me here ARE nested then your resources MUST live in a tree structure. That means no cycles. If the path is just a bread crumb and the id's shown are unique then what you're offering is to throw an error if merchant 12 has nothing to do with hotel 42. I could delete merchants/12 and talk directly to hotels/42 without caring if there even is a merchant. – candied_orange Jul 16 '17 at 10:27
  • @CandiedOrange if the parent resource is deleted then there should be error for sure. I think in backend when someone delete the merchant then I should do cascade delete and delete all hotels associated with it too in that sense hotel id will be invalid too. – CodeYogi Jul 16 '17 at 10:36
  • Then hotels/42 is meaningless without merchants/12. 42 isn't a unique id. It's part of a composite key. Now, suppose the merchant sells the hotel to a different merchant? What happens now? – candied_orange Jul 16 '17 at 10:40
2

following this scheme will turn hairy

Can you explain why you think the nested design is bad?

Can I assume that each entity has unique ID? If yes, then the can I use these URLs for APIs instead of above ones?
POST api/v1/rooms
PUT api/v1/rooms/42

Typically each type of entity will have its own id space, and each instance will have an id from that space. Each room will have a different id from every other room. It doesn't have to be this way, but usually it is, and yes that would give you flexibility and allow you to adopt a flat structure like you're suggesting.

Originally I thought perhaps a flat structure would be better. It would allow you to manage a hotel or a room without having to know the parent entities, but after thinking about the problem a bit, it makes sense that you need to know the merchant and hotel before changing a room. Am I right in thinking that a hotel only belongs to a single merchant and a room belongs to only a certain hotel? If these are one-to-one relationships, then the nested structure makes a lot of sense.

The choice you make will ultimately be decided by your use cases. How are developers going to be accessing your API? Are they going to only be looking at one merchant? -- If so, you may want to not show them the merchant layer (lookup merchant from authentication). Are they going to be iterating over every room or hotel in the API regardless of merchant? -- If so, the flat structure makes a lot of sense. Answering these questions will help you decide how to structure your API, and you may decide you want both a flat structure and a nested structure to meet all your use cases.

  • Mostly the users will be booking rooms via APIs. Generally merchant should be invisible because who cares about who owns the hotel most of the time we know that which hotel we need and would be interested in booking rooms in it. – CodeYogi Jul 16 '17 at 10:21
  • "after thinking about the problem a bit, it makes sense that you need to know the merchant and hotel before changing a room" why? now, suppose I add facilities which are part of the room so to update a facility I have to remember merchant id, hotel id, room id and at last facility id, right? – CodeYogi Jul 16 '17 at 18:10
  • Well in the context of booking a room you would definitely need the hotel->room relationship. User's will probably want to search for hotels by location and then find a room within the hotel. Yes, the merchant layer seems mostly cumbersome. There's nothing wrong with using multiple strategies. You can have /hotels/9/rooms/2/facilities/7 and /facilities/7 be the same entity with the same operations available. – Samuel Jul 16 '17 at 20:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.