8

Say I have a company directory application, so Companies have Employees. It's pretty clear to me why you would have the following GET endpoints:

api/companies                # Get all company records
api/companies/{id}           # Get company with specified id
api/companies/{id}/employees # Get all employees for the company with specified id

But say I want to get a specific employee record. It seems the common pattern is to provide a resource:

api/companies/{id}/employees/{id}

But assuming an employee record is only owned by one company, why would you provide the company's id in that URI? Isn't that simply a redundant parameter? Even if you need to acquire the company for some kind of logic behind the scenes, you can do that easily enough by just checking the parent of the employee. So my gut says to make the endpoint like this:

api/companies/employees/{id}

Yet the former pattern is so pervasive, I feel like I'm missing something. Would someone care to explain?

6

There is no guarantee that employee IDs are unique across companies.

In other words, we may run into this scenario:

> GET api/companies/4711/employees/42
Smith, Winston

> GET api/companies/815/employees/42
O'Brien, Seamus

If we really had the case where employee IDs are a resource independent of companies (such as the SSN in the U.S.), then api/employees/{id} would be much better.

  • 1
    GUIDs would fix that problem. SSN's are not guaranteed to be unique. – Robert Harvey Jun 30 '16 at 15:31
  • Ah, ok. I assumed they were. Good to know. – JensG Jun 30 '16 at 15:47
  • 4
    Which is why I always use synthetic primary keys. I've seen too many cases where a natural key was assumed to be unique when it actually wasn't. – Robert Harvey Jun 30 '16 at 15:50
9

The problem with supporting GET /companies/{id}/employees/{id} and GET /companies/employees/{id} is that the meaning of the path segment after /companies is overloaded. It would represent either "a specific company" or "a property shared by all companies". It's annoying to implement on your side, confusing for clients, and now you have to track that you've removed "employees" as a possible company id.

If there are no properties of an employee that differ among companies, then just do:

GET /companies/{id}
GET /employees/{id}

You can also support either GET /employees?company={id}, GET /companies/{id}/employees, or both, but any self links for the employees should point back to their canonical location (/employees/{id}).

Your ids for employees and companies should almost certainly be generated by your system and not related to user-specific data, because that can change.

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.