In general you have one endpoint which represents the whole collection of x:
/products
Say, you want to update a single product, you make a PUT to /products/{id}
.
If you want to partially update a single product (not updating every field), you could also use a PATCH to /products/{id}
. The same goes for deletion of a single entity (DELETE to /products/{id}
).
If you want to target a single ressource, you qualify via path, which single ressource, you want to modify.
The only action which breaks the scheme is the creation of a ressource. When creating a ressource you target the collection as a whole, say POST to /products
.
That said, it should be clear, that the target for operations affecting the collection as a whole, should go to the appropriate collection-endpoint.
E.g. you want to retrieve a subset of products which are red, you ask for it by
GET to /products?colour=red
.
So, if you want to delete all of these, you DELETE /products?colour=red
. Or if you want to delete some of the products via id
, you could DELETE /products?id=1&id=2&id=3
.
What about bulk creation of ressources? POST your collection [{...},{...},{...}]
simply to /products
. The same goes for PUT and PATCH.
That's really straightforward.
To answer your questions:
If I need to add to the collection, is it OK that I pass only some products with PUT?
It is not only OK, you are encouraged to do it like that.
If I need to delete some products from the collection, is it OK that I pass filter data (an array of ID's) with DELETE?
That is okay. As Eneko Alonso wrote, sometimes there are bulkoperations encapsulated via "controller"-endpoints, i.e. a POST is used to trigger (complex) operations.