Suppose the following:
Building has 0...n Rooms
, Room has 0...n Seats
.
I am implementing a REST API which accepts data from different companies, with the caveat that the companies must be able themselves define the id (reference) of the entity. I'm generally unable to make any assumptions about those ids, other than being compatible with a HTTP URL. This means there's no guarantee ids are unique across companies, or even within a company (e.g. two rooms could have the same id but be linked to different buildings).
Since its possible that two companies would have the same id for a Building, I've decided to treat companyId
and buildingReference
as a composite id. The API endpoints I came up with are as follows:
buildings/
buildings/{companyId}/{buildingReference}/rooms
buildings/{companyId}/{buildingReference}/rooms/{roomReference}/seats
etc.
I have some doubts whether this is a good idea. Among other things:
- Most APIs I've come across only use a singular id
- If I ever decide to expose GET
/rooms
or/seats
, I'd have to return more and more fields to make the resource uniquely identifiable,companyId, buildingReference, roomReference
for room andcompanyId, buildingReference, roomReference, seatReference
for seat
I could possibly get rid of companyId
by requiring that the buildingReference
be some kind of String concatenation of the two, e.g. CompanyOne-1234
, but that doesn't strike me as a great idea either.
Are composite keys like this a good idea? Are there better alternatives?
companyId
,buildingId
androomId
are at different levels of the hierarchy. How can they collide? If companies are allowed to generate their own ids then they are responsible for avoiding collisions within their hierarchy. As you said, you cannot make assumptions. ID composition as the one suggested is made upon a lot of assumptions you don't even know yet. Basically those made (wrongly) by the clients of the API (who might generate their IDs ignoring they are not the only company in the system)buildingReference
is mis-typed? Do you implicitly create a new resource, or do you return an error because that resource hasn't been made yet? That can help design the API. I would avoid composite IDs if possible.