Let's take the following example:
We want to expose company and employee information from a RESTful API.
Company data should be quite simply:
GET api/v1/companies
GET api/v1/companies/{id}
Employees BELONG to a company, but we still want to retrieve them individually as well, so which solution is best:
Get all employees for a company:
GET api/v1/companies/{companyId}/employees
Get a specific employee:
GET api/v1/companies/{companyId}/employees/{employeeId}
Get all employees for a company:
GET api/v1/employees?companyId={companyId}
Get a specific employee:
GET api/v1/employees/{employeeId}
Both options seem to have their pros and cons.
With sub-resources, I may not always have the CompanyId on hand when wanting to retrieve an individual employee.
With an independent resource, getting all employees for a company should use the sub-resource approach if we want to be RESTful.
Otherwise, we could use a mix, but this lacks consistency:
Get all employees for a company:
GET api/v1/companies/{companyId}/employees
Get a specific employee:
GET api/v1/employees/{employeeId}
What is the best approach to take in such a situation if we want to stay true to RESTful standards?
For me this sounds like the common many-to-many relationship problem for RESTful services. (see How to handle many-to-many relationships in a RESTful API?)
Your first solution seems good at first but you will have problems whenever you want to access the relation itself.
Instead of returning the employee with the following GET request you should return the relation.
GET api/v1/companies/{companyId}/employees/{employeeId}
If the relation can be identified by 2 keys this solutions seems to be fine. But what happens if the relation is identified by 3+ id's? The URI becomes rather long.
GET api/v1/companies/{companyId}/employees/{employeeId}/categories/{categoryId}
In this case I would come up with a separate resource for the relation:
GET api/v1/company-employees/{id}
The returned model in JSON would look like this:
{
"id": 1 <- the id of the relation
"company": {
"id": 2
},
"employee": {
"id": 3
},
"category": {
"id": 4
}
}
I think it would be okay to provide both. If you want the client to browse through the list of companies first, then select a company and then get the list of all employees, the first approach is necessary. If, may be in addition, you want the client to be able to filter employees by name or age, but without knowing the company identifier, you must provide the second approach as well. It depends on what you want the client to do. In my opinion, it would not be necessary to provide the second approach, if clients can only filter employees by company identifier.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With