First case:
Let's say I have in my REST API a Customer resource available through the /customers
and /customers/{id}
endpoints.
Given that a customer can have multiple addresses, I have basically three options:
Add a /customers/{id}/addresses
sub-collection endpoint. In that case, we can GET/POST/PUT/DELETE to that endpoint to get/add/modify/delete an address.
Add a /addresses
endpoint representing top-level collection of addresses.
Do not create another endpoint, addresses are returned on GET /customers/{id}
requests and can be added/modified/deleted with a PATCH request, eg. if we are using JSON-PATCH:
PATCH /customers/{id}
{
"op": "add",
"path": "/addresses/-",
"value": /* new address */
}
Which one would be the more appropriate in the case of a "general purpose" API (ie. a public API having multiple different clients with different needs)?
Second case:
Now let's consider a Document resource representing a document shared amongst multiple users, such as a Google Doc. Each time a user starts editing a document, its ID is added to the list of users currently editing that document, eg:
GET /documents/{id}
{
"data": /* ... */,
"editors": ["userId1", "userId2"]
}
Would you handle this the same way as the previous case?
The option #1 does not seem that natural to me because an editor in this case is just an ID (internally, a foreign key), can we consider an ID (and more generally a simple primitive type such as a string, integer, etc) as a resource? Also, creating a different endpoint for each "sub-resource" will end up having lots of endpoints, whereas the PATCH option (#3) allows to keep a small number of endpoint while providing in addition the ability to update multiple sub-resources at the same time, eg:
PATCH /documents/{id}
[
{"op": "add", "path": "/editors/-", "value": "idUser"},
{"op": "replace", "path": "/title", "value "new title"}
]
First option. If the addresses
belongs to customer, that is, are not shared between different customer (at least, in the general case), I think the first option fits fine with a REST approach, since you model your system as a collection of resources and hierarchical relationship between them.
You could also use PATCH
in combination with the first option in case you need to make partial updates of the addresses (for instance, if you only need to modify the name of the street)