There's nothing wrong in identifying a subset of resources through the query string and add|update resources to the subset.
However, in this particular case, the URI here raises some doubts
/api/products?addToAllStores=true
On one side /api/products
identifies a specific set of resources Products
, on the other side addToAllStores
identifies (somehow) another different set of resources and also denotes operability (something we usually delegate to the HTTP method and to the semantics of the API). Altogether, makes me wonder if it would not be better placed in the payload. For clarity.
Then, reading @VoiceOfUnreason' answer
How would you do it on a web site? There would be a form that the
client can fill out and submit to tell you to create the product. If
you also wanted to give the client an option to add the product to the
store, then you might add a checkbox to the form.
Emphasis of mine
Making addToAllStores
part of the message instead of the identifier (URI) would make the API less ambiguous. And practical I would dare to say.
For example, say we want to add products to a smaller subset of stores. We would have to add something like addToStores=x,y,z
to the URI. That would make us have 2 different parameters with different types, handled in different ways. Another doubt involves single stores. If there's addToAllStores
, well there must be a way to inform a single store. If that way is in the payload, a consistent API would send addToAllStores
in the payload too.
Finally (and this is an opinion of mine), if we need to add different Products
in different Stores
in the same transaction, we have to add a new parameter or change the payload to support product - stores
relationships. More likely the later because it would be complicated to do in the former.
Say then, we move this "relationship" to the payload as we had filled up the web form suggested by @VoiceOfUnreason. The payload could be similar to
{
"products":[
{ "name":"x", code:"x", stores:["*"] },
{ "name":"y", code:"y", stores:["A","B"] },
{ "name":"z", code:"z", stores:["C"] },
{ "name":"w", code:"w", stores:[] },
]
}
It's just an example but it shows how we could reach the same goal with a single payload scheme, without having to delegate intentionality to the URI with different query parameters -- a place we (devs) usually don't look for loads parameters. Additionally, the input is packed in such a way it's portable to other protocols that might not rely on URIs to carry information.
Anyways, again, there's nothing wrong in using query strings + POST
. It's a matter of convenience or pragmatism. If you have identified reasons to send addToAllStores
through the query string and it meets your needs, that's fine too.