Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RESTful API - Designing sub-resources

I am designing a RESTful API and I came up with a problem related to sub-resources.

I see other APIs using full URL to operate over sub-resources. Take the example where Company has Departments and Department has Employees.

In the beginning I though about implementing all possible URLs. Resulting on the following:

Approach A

01. ### COMPANY URLS ### 02. DELETE /companies/{companyId} 03. GET    /companies/{companyId} 04. POST   /companies 05. PUT    /companies/{companyId} 06.  07. ### DEPARTMENT URLS ### 08. DELETE /companies/{companyId}/departments/{departmentId} 09. GET    /companies/{companyId}/departments/{departmentId} 10. POST   /companies/{companyId}/departments 11. PUT    /companies/{companyId}/departments/{departmentId} 12. DELETE /departments/{departmentId} 13. GET    /departments/{departmentId} 14. PUT    /departments/{departmentId} 15.  16. ### EMPLOYEE URLS ### 17. DELETE /companies/{companyId}/departments/{departmentId}/employees/{employeeId} 18. GET    /companies/{companyId}/departments/{departmentId}/employees/{employeeId} 19. POST   /companies/{companyId}/departments/{departmentId}/employees 20. PUT    /companies/{companyId}/departments/{departmentId}/employees/{employeeId} 21. DELETE /departments/{departmentId}/employees/{employeeId} 22. GET    /departments/{departmentId}/employees/{employeeId} 23. POST   /departments/{departmentId}/employees 24. PUT    /departments/{departmentId}/employees/{employeeId} 25. DELETE /employees/{employeeId} 26. GET    /employees/{employeeId} 27. PUT    /employees/{employeeId} 

As you can see, there are many URLs which do the same thing. Example: 08 is duplicated of 12; 09 is duplicated of 13; 17 is duplicated of 21 and 25...

I want to remove the duplication but keep consistency. So, re-designed the API with a principle in mind sup-resources are fine but sub-sub-resources are not. Which resulted on the following:

Approach B

01. ### COMPANY URLS ### 02. DELETE /companies/{companyId} 03. GET    /companies/{companyId} 04. POST   /companies 05. PUT    /companies/{companyId} 06.  07. ### DEPARTMENT URLS ### 08. DELETE /departments/{departmentId} 09. GET    /departments/{departmentId} 10. GET    /companies/{companyId}/departments 11. POST   /companies/{companyId}/departments 12. PUT    /departments/{departmentId} 13.  14. ### EMPLOYEE URLS ### 15. DELETE /employees/{employeeId} 16. GET    /employees/{employeeId} 17. GET    /departments/{departmentId}/employees 18. POST   /departments/{departmentId}/employees 19. PUT    /employees/{employeeId} 

My Questions

Q1. Is Approach B considered RESTful? (I am assuming yes)

Q2. Are there pitfalls Approach B I should consider, assuming that documentation is also provided?

Bonus points if you point to other APIs following Approach B.

EDIT

Elad Tabak presented good insights.

I fond some API using Approach B:

https://developers.google.com/youtube/v3/docs/

https://developer.github.com/guides/getting-started/

https://dev.twitter.com/rest/public

like image 533
Rafa Avatar asked Oct 13 '16 14:10

Rafa


People also ask

What is sub resource API?

A subresource is a collection or an item that belongs to another resource. API Platform makes it easy to create such operations. Watch the Subresources screencast. The starting point of a subresource must be a relation on an existing resource.

What is RESTful API resources?

Resources are the basic building block of a RESTful service. Examples of a resource from an online book store application include a book, an order from a store, and a collection of users. Resources are addressable by URLs and HTTP methods can perform operations on resources.


2 Answers

Both approaches can be considered RESTful, provided you do not break the REST constraints defined in the chapter 5 of Roy Thomas Fielding's dissertation:

  • Client-server
  • Stateless
  • Cache
  • Uniform interface
  • Layered system
  • Code-on-demand

I cannot see major pitfalls in both approaches, but I would prefer the Approach B over the Approach A: the URLs are shorter, easier to remember and not many parameters are required.


Bonus points: Spotify and Facebook APIs follow this approach. For sure there are other APIs, but these are the ones that came up to my mind.

like image 52
cassiomolin Avatar answered Sep 23 '22 04:09

cassiomolin


The design approach raises a few questions you need to consider when choosing between the two:

Existence dependency

In A, it's very intuitive, that when you DELETE a company, you also deleting all it's sub resources - departments and employees. In B, the API user needs to think a moment about such action - do I need to invoke delete on all employees, or is it enough to delete the company? of course, this can be documented, but still, it's not straight-forward.

A have an advantage here, becuase it's very clear - when deleting a resouce, you delete all it's sub resources.

Operation endpoint

Another question it raises - how do I update an entity? from which end-point?

If I want to delete an employee, is it enough to update the company with a new set of employees? or must I DELETE the employee?

Or say I want to change employee from one company to another. In B, theoretically I can update employee with company field, and be done with it. In A there's no such way...

A have an advantage where it's very straight-forward how to do an action - CRUD on the entity URL. B makes the API user stop and wonder which action he can do on which URL.

But at the same time, B have an advantage that changing the "parenting" of an entity is easier (in cases where it's relevant).

Validation

In A, you must validate the URL arguments match, as user can provide employee id with the wrong company or department. In B there's no such problem.

like image 25
Elad Tabak Avatar answered Sep 23 '22 04:09

Elad Tabak